Expressions Recursivas(Recursive CTEs)Nao vou entrar nos detalhes das CTEs recursivas umavez que ha varios assuntos sobre elas na Internet alem do que as mesmas saomuito bem abordadas pelo colaborador Thiago Zavaschi em Entendendo as Common TableExpressions CTE Parte 1. Eu ja abordei um exemplo de CTErecursiva emDicas e Truques sobre consultascomplexas no SQL Server, mas as apresentacoes do Zavaschi sobre CTEs (tanto em seus artigos quantono SQL Server Day) saocertamente superiores.Umavez que exista uma relacao hierarquica entre as sessoes, e possivel utilizaruma CTE recursiva para explorar essas relacoes. Aconsulta abaixo demonstra aquantidade real de bloqueios de cada sessao, ou seja, tanto os bloqueios queuma sessao pode provocar diretamente em outras, quanto bloqueios provocadosindiretamente, ou seja, se A bloqueia B e B bloqueia C, indiretamente Abloqueia C.;WITH Sessoes(Sessao, Bloqueadora) As ( SELECT Session_Id,Blocking_Session_Id FROM sys.dm_exec_requests As R WHERE blocking_session_id> 0 UNION ALL SELECT Session_Id, CAST(0 AsSMALLINT) FROM sys.dm_exec_sessions As S WHERE EXISTS( SELECT * FROM sys.dm_exec_requests As R WHERE S.Session_Id= R.Blocking_Session_Id) AND NOT EXISTS ( SELECT * FROM sys.dm_exec_requests As R WHERE S.Session_Id= R.Session_Id)),Bloqueios As ( SELECT Sessao, Bloqueadora, Sessao As Ref,1 As Nivel FROM Sessoes UNION ALL SELECT S.Sessao,B.Sessao, B.Ref, Nivel + 1 FROM Bloqueios As B INNER JOIN Sessoes As S ON B.Sessao= S.Bloqueadora)SELECT Ref As Sessao, COUNT(DISTINCT R.Session_Id) As BloqueiosDiretos, COUNT(DISTINCT B.Sessao) 1 As BloqueiosTotal, COUNT(DISTINCT B.Sessao) COUNT(DISTINCT R.Session_Id) 1 AsBloqueiosIndiretosFROM Bloqueios As B INNER JOIN sys.dm_exec_requests As R ON B.Ref= R.blocking_session_idGROUPBY RefOresultado pode ser observado logo abaixo: Sessao Bloqueios Diretos Bloqueios Total Bloqueios Indiretos 52 5 25 20 54 6 6 0 55 5 5 0 57 4 4 0 59 3 3 0 62 2 2 0 Eliminara sessao 54 significa liberar 6 bloqueios diretos. A sessao 52 bloqueia apenas5 sessoes diretamente, mas indiretamente bloqueia outras 20 ja que as 5 sessoesbloqueadas diretamente bloqueam outras sessoes. A eliminacao da sessao 52libera outras 25 sessoes e visivelmente e a medida mais efetiva para ajudar queos bloqueios sejam resolvidos.Umapequena mudanca no codigo e capaz de mostrar os comandos executados por cadauma das sessoes que impoe bloqueios sobre as outras.;WITH Sessoes(Sessao, Bloqueadora) As ( SELECT Session_Id,Blocking_Session_Id FROM sys.dm_exec_requests As R WHERE blocking_session_id> 0 UNION ALL SELECT Session_Id, CAST(0 AsSMALLINT) FROM sys.dm_exec_sessions As S WHERE EXISTS( SELECT * FROM sys.dm_exec_requests As R WHERE S.Session_Id= R.Blocking_Session_Id) AND NOT EXISTS ( SELECT * FROM sys.dm_exec_requests As R WHERE S.Session_Id= R.Session_Id)),Bloqueios As ( SELECT Sessao, Bloqueadora, Sessao As Ref,1 As Nivel FROM Sessoes UNION ALL SELECT S.Sessao,B.Sessao, B.Ref, Nivel + 1 FROM Bloqueios As B INNER JOIN Sessoes As S ON B.Sessao= S.Bloqueadora)SELECT Ref As Sessao, COUNT(DISTINCT R.Session_Id) As BloqueiosDiretos, COUNT(DISTINCT B.Sessao) 1 As BloqueiosTotal, COUNT(DISTINCT B.Sessao) COUNT(DISTINCT R.Session_Id) 1 AsBloqueiosIndiretos, (SELECTTEXT FROM sys.dm_exec_sql_text( (SELECT most_recent_sql_handle FROM sys.dm_exec_connections WHERE session_id= B.Ref))) As ComandoFROM Bloqueios As B INNER JOIN sys.dm_exec_requests As R ON B.Ref= R.blocking_session_idGROUPBY RefOresultado pode ser observado logo abaixo: Sessao Bloqueios Diretos Bloqueios Total Bloqueios Indiretos Comando 52 5 25 20 Muda o contexto de banco de dados USE TempDB; M 54 6 6 0 (@1 int)UPDATE [T1] set [COD] = [COD]+@1 55 5 5 0 (@1 tinyint)SELECT [COD] FROM [T2] WHERE [COD]<@1 57