Olá pessoal,
Bom dia!
Neste post vou mostrar a vocês como encontrar dependências entre objetos de vários níveis de hierarquia no SQL Server utilizando queries Transact-SQL, simulando um comportamento semelhante ao que nos é apresentado na interface do Management Studio.
Utilizando o SQL Server Management Studio
Essa é a forma mais fácil de realizar esse mapeamento, pois não exige nenhum conhecimento técnico, basta utilizar a interface do Management Studio. Um contra dessa implementação é que você não pode trabalhar com os dados retornados para criar algum levantamento ou mapeamento em massa por exemplo, ou definição de nível de hierarquia para a busca. Além disso, essa tela não mostra as dependências cross-databases, ou seja, dependências entre objetos de databases diferentes.
Para visualizar as dependências, basta abrir o Object Explorer, selecionar o objeto que deseja visualizar as dependências (no exemplo, escolhi a tabela Clientes), clicar com o botão direito e selecionar a opção “View Dependencies”

Uma vez que a tela é aberta, você pode escolher visualizar:
– Objetos que dependem do objeto em questão (Objects that depend on [Clientes])
– Outros objetos que o objeto em questão possui dependência (Objects on which [Clientes] depends)

Essa tela lista tanto dependências direta (nível 1), quando um objeto depende diretamente de outro quanto dependências indiretas (quando um objeto depende de outro objeto e esse outro objeto é que possui a dependência). Quando mais níveis aparecem entre o objeto inicial e o final, maior é a hierarquia deles.
Utilizando Transact-SQL
Nos exemplos abaixo, vou demonstrar como listar os objetos e suas dependências utilizando queries T-SQL, fazendo uso das DMV’s sys.dm_sql_referenced_entities e sys.dm_sql_referencing_entities e da view de catálogo sys.sql_expression_dependencies.
Utilizando a sp_depends
Com o uso dessa SP de sistema, pode-se rapidamente listar os dependências de um objeto (apenas 1º nível e não é cross-database)
EXEC sp_depends @objname = N'dbo.Clientes'
Exemplo:

Utilizando a sp_MSdependencies
Uma outra SP de sistema que pode ajudar nessa situação, é a sp_MSdependencies. Apesar de não ser cross-database, ela permite visualizar os objetos dependentes do objeto X (Flag 1315327) e os que o objeto X depende (Flag 1053183).
-- Lista os objetos que dependem da tabela dbo.Clientes
EXEC sp_MSdependencies N'dbo.Clientes', null, 1315327
-- Lista os objetos que a tabela dbo.Clientes depente
EXEC sp_MSdependencies N'dbo.Clientes', null, 1053183
Exemplos:

Utilizando a view de catálogo syscomments
Utilizando essa view de catálogo, pode-se facilmente realizar uma busca textual (é busca de texto, não é por objeto) entre os objetos para tentar entrar uma string específica em objetos como views, functions, procedures, triggers, etc. Esse recurso não é cross-database e retorna apenas dependências de 1º nível.
SELECT DISTINCT
B.name
FROM
syscomments A
INNER JOIN sysobjects B ON A.id = B.id
WHERE
CHARINDEX('Clientes', text) > 0
Exemplo:

Utilizando a view de catálogo INFORMATION_SCHEMA.ROUTINES
Com a query abaixo, podemos fazer uma busca textual em procedures e functions que possuem uma string no nome, como o nome do objeto que estamos buscando dependências. Essa solução não é cross-database e é uma busca textual.
SELECT
ROUTINE_CATALOG,
ROUTINE_SCHEMA,
ROUTINE_NAME,
ROUTINE_TYPE,
ROUTINE_DEFINITION
FROM
INFORMATION_SCHEMA.ROUTINES
WHERE
ROUTINE_DEFINITION LIKE '%Clientes%'
Dependências Cross Database
Com a query abaixo, é possível selecionar todas as dependências cross-database, onde os objetos do banco atual da conexão possuem dependências para outros databases.
SELECT
OBJECT_NAME(referencing_id) AS referencing_object,
referenced_database_name,
referenced_schema_name,
referenced_entity_name
FROM
sys.sql_expression_dependencies
WHERE
referenced_database_name IS NOT NULL
AND is_ambiguous = 0
Exemplo:

Dependências de schema-bound
Com a query abaixo, é possível identificar a mapear as dependências do tipo schema-bound, como views indexadas (criadas com o hint SCHEMABINDING), colunas calculadas e check constraints:
SELECT
OBJECT_NAME(d.referencing_id) AS referencing_name,
o.type_desc referencing_object_type,
d.referencing_minor_id AS referencing_column_id,
cc2.name AS referencing_column_name,
d.referenced_entity_name,
d.referenced_minor_id AS referenced_column_id,
cc.name AS referenced_column_name
FROM
sys.sql_expression_dependencies d
JOIN sys.all_columns cc ON d.referenced_minor_id = cc.column_id AND d.referenced_id = cc.[object_id]
JOIN sys.objects o ON d.referencing_id = o.[object_id]
LEFT JOIN sys.all_columns cc2 ON d.referencing_minor_id = cc2.column_id AND d.referencing_id = cc2.[object_id]
WHERE
d.is_schema_bound_reference = 1
AND d.referencing_minor_id > 0
Exemplo de Retorno:

Demonstração da dependência:

Mostrando dependências em vários níveis
Com a query abaixo é possível listar as dependências em vários níveis hierárquicos, da mesma forma que a interface do SQL Server Management Studio nos mostra
WITH Arvore_Dependencias ( referenced_id, referenced_name, referencing_id, referencing_name, NestLevel )
AS (
SELECT
A.[object_id] AS referenced_id,
A.name AS referenced_name,
A.[object_id] AS referencing_id,
A.name AS referencing_name,
0 AS NestLevel
FROM
sys.objects A
WHERE
A.name = 'Clientes'
UNION ALL
SELECT
A.referenced_id,
OBJECT_NAME(A.referenced_id),
A.referencing_id,
OBJECT_NAME(A.referencing_id),
NestLevel + 1
FROM
sys.sql_expression_dependencies A
JOIN Arvore_Dependencias B ON A.referenced_id = B.referencing_id
)
SELECT DISTINCT
referenced_id,
referenced_name,
referencing_id,
referencing_name,
NestLevel
FROM
Arvore_Dependencias
WHERE
NestLevel > 0
ORDER BY
NestLevel,
referencing_id
Exemplo:

Encontrando dependências por tipo de dado
Como você deve saber, os tipos de dados TEXT, NTEXT e IMAGE serão descontinuados e não mais suportados em futuras versões do SQL Server. Se você planeja realizar o upgrade da sua aplicação e substituir esses tipos, a query abaixo pode ser um bom ponto de partida. A query abaixo vai mostrar todos os objetos que utilizam esses tipos de dados e suas dependências:
WITH Arvore_Dependencias
AS (
SELECT DISTINCT
A.name,
A.[object_id] AS referenced_id,
A.name AS referenced_name,
A.[object_id] AS referencing_id,
A.name AS referencing_name,
0 AS NestLevel
FROM
sys.objects A
JOIN sys.columns B ON A.[object_id] = B.[object_id]
WHERE
A.is_ms_shipped = 0
AND B.system_type_id IN ( 34, 99, 35 ) -- TEXT, NTEXT e IMAGE
UNION ALL
SELECT
B.name,
A.referenced_id,
OBJECT_NAME(A.referenced_id),
A.referencing_id,
OBJECT_NAME(A.referencing_id),
NestLevel + 1
FROM
sys.sql_expression_dependencies A
JOIN Arvore_Dependencias B ON A.referenced_id = B.referencing_id
)
SELECT
name AS parent_object_name,
referenced_id,
referenced_name,
referencing_id,
referencing_name,
NestLevel
FROM
Arvore_Dependencias t1
WHERE
NestLevel > 0
ORDER BY
name,
NestLevel
Relatório completo de dependências
A query abaixo vai mostrar uma linha para cada objeto do database que possua dependências, com os objetos dependentes separados por vírgula.
SELECT
DB_NAME() AS dbname,
o.type_desc AS referenced_object_type,
d1.referenced_entity_name,
d1.referenced_id,
STUFF((
SELECT
', ' + OBJECT_NAME(d2.referencing_id)
FROM
sys.sql_expression_dependencies d2
WHERE
d2.referenced_id = d1.referenced_id
ORDER BY
OBJECT_NAME(d2.referencing_id)
FOR XML PATH('')
), 1, 1, '') AS dependent_objects_list
FROM
sys.sql_expression_dependencies d1
JOIN sys.objects o ON d1.referenced_id = o.[object_id]
GROUP BY
o.type_desc,
d1.referenced_id,
d1.referenced_entity_name
ORDER BY
o.type_desc,
d1.referenced_entity_name
Exemplo:

Procedure de Dependências Diretas
Após demonstrar todas essas utilizações, vou compartilhar uma stored procedure que eu uso sempre que preciso listar as dependências cross-database rapidamente. Existe um pré-requisito para criar essa SP, que é a fncSplit, que deve ser criada antes.
Essa procedure lista todas as dependências diretas de um objeto, de modo cross-database:
Visualizar código-fonte
Exemplo:

Procedure Cross-database e multi-nível
Com a procedure abaixo, que utiliza CTE e recursividade, é possível listar todos os objetos dependentes com vários níveis de hierarquia no banco de origem e as dependências diretas (1º nível) e cross-database.
Visualizar código-fonteExemplo:

Como identificar, apagar e recriar Foreign Keys (FK)
Caso você queira identificar ou recriar dependências a nível de chaves Foreign Key’s, leia o artigo Como identificar, apagar e recriar Foreign Keys (FK) de uma tabela no SQL Server
É isso aí, pessoal!
Até o próximo post!
Comentários (0)
Carregando comentários…