Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Localizar entidades referenciadas no SQL Server:sys.dm_sql_referenced_entities


No SQL Server, você pode usar o sys.dm_sql_referenced_entities() função de gerenciamento dinâmico do sistema para obter uma lista de todas as entidades definidas pelo usuário que são referenciadas por nome, na definição de uma determinada entidade.

Em outras palavras, ele retorna uma lista de todas as entidades definidas pelo usuário das quais uma entidade específica depende.

Especificamente, ele relata os seguintes tipos de entidade referenciados pela entidade de referência especificada:
  • Entidades vinculadas ao esquema
  • Entidades não vinculadas a esquema
  • Entidades entre bancos de dados e entre servidores
  • Dependências em nível de coluna em entidades vinculadas e não vinculadas a esquema
  • Tipos definidos pelo usuário (alias e CLR UDT)
  • Coleções de esquema XML
  • Funções de partição


Sintaxe


A sintaxe fica assim:
sys.dm_sql_referenced_entities (  
    ' [ schema_name. ] referencing_entity_name ' ,
    '  ' )  
  
 ::=  
{  
    OBJECT  
  | DATABASE_DDL_TRIGGER  
  | SERVER_DDL_TRIGGER  
}

Exemplo 1 – Exemplo básico


Segue um exemplo de uso:
USE Test;
SELECT 
  referenced_schema_name AS [Schema],
  referenced_entity_name AS Entity,
  referenced_minor_name AS Minor,
  referenced_class_desc AS Class,
  is_select_all,
  is_all_columns_found
FROM sys.dm_sql_referenced_entities (
    'dbo.uspGetClient', 
    'OBJECT');

Resultado:
+----------+------------+------------+------------------+-----------------+------------------------+
| Schema   | Entity     | Minor      | Class            | is_select_all   | is_all_columns_found   |
|----------+------------+------------+------------------+-----------------+------------------------|
| dbo      | Client     | NULL       | OBJECT_OR_COLUMN | 1               | 1                      |
| dbo      | Client     | ClientCode | OBJECT_OR_COLUMN | 1               | 1                      |
| dbo      | Client     | FirstName  | OBJECT_OR_COLUMN | 1               | 1                      |
| dbo      | Client     | LastName   | OBJECT_OR_COLUMN | 1               | 1                      |
| NULL     | clientcode | NULL       | TYPE             | 0               | 0                      |
+----------+------------+------------+------------------+-----------------+------------------------+

Aqui eu recebo todas as entidades que são referenciadas no dbo.uspGetClient procedimento armazenado. Neste caso, existem cinco entidades.

A primeira é a tabela chamada “Cliente”. As próximas três são todas as colunas dessa tabela. O último é um tipo de dados de alias definido pelo usuário chamado “clientcode”.

Também podemos ver que os quatro primeiros são usados ​​em uma instrução select que usa o asterisco (* ) curinga para selecionar todas as colunas (porque seu is_select_all está definido como 1 ).

Aqui está a definição real usada para criar o procedimento armazenado que estamos analisando:
CREATE PROCEDURE [dbo].[uspGetClient] @ClientCode clientcode AS
SELECT * 
FROM [dbo].[Client]
WHERE ClientCode = @ClientCode;

Sim, é um procedimento armazenado muito simples, mas é ideal para nossos propósitos. Podemos ver todas as entidades referenciadas como retornadas por sys.dm_sql_referenced_entities() .

Também podemos ver que o procedimento consiste em um único SELECT consulta que usa o curinga asterisco para selecionar todas as colunas.

Exemplo 2 – Remova a opção “Selecionar tudo” (* )


Vamos alterar o procedimento armazenado para que ele não use o curinga asterisco para selecionar todas as colunas.
ALTER PROCEDURE [dbo].[uspGetClient] @ClientCode clientcode AS
SELECT 
    FirstName,
    LastName
FROM [dbo].[Client]
WHERE ClientCode = @ClientCode;

Portanto, agora ele retorna explicitamente as colunas “FirstName” e “LastName”. Nenhum curinga encontrado.

Agora execute sys.dm_sql_referenced_entities() novamente:
USE Test;
SELECT 
  referenced_schema_name AS [Schema],
  referenced_entity_name AS Entity,
  referenced_minor_name AS Minor,
  referenced_class_desc AS Class,
  is_select_all,
  is_all_columns_found
FROM sys.dm_sql_referenced_entities (
    'dbo.uspGetClient', 
    'OBJECT');

Resultado:
+----------+------------+------------+------------------+-----------------+------------------------+
| Schema   | Entity     | Minor      | Class            | is_select_all   | is_all_columns_found   |
|----------+------------+------------+------------------+-----------------+------------------------|
| dbo      | Client     | NULL       | OBJECT_OR_COLUMN | 0               | 1                      |
| dbo      | Client     | ClientCode | OBJECT_OR_COLUMN | 0               | 1                      |
| dbo      | Client     | FirstName  | OBJECT_OR_COLUMN | 0               | 1                      |
| dbo      | Client     | LastName   | OBJECT_OR_COLUMN | 0               | 1                      |
| NULL     | clientcode | NULL       | TYPE             | 0               | 0                      |
+----------+------------+------------+------------------+-----------------+------------------------+

Desta vez, o is_select_all coluna mostra 0 em todas as linhas.

Exemplo 3 – Referenciando uma entidade inexistente


E se sua entidade fizer referência a uma entidade inexistente?

Por exemplo, e se seu colega descartar uma coluna que está realmente sendo referenciada por um procedimento armazenado e você executar sys.dm_sql_referenced_entities() contra esse procedimento armazenado?

Vamos descobrir.
ALTER TABLE [dbo].[Client] 
DROP COLUMN LastName;

Acabei de soltar o LastName coluna da minha tabela.

Agora execute sys.dm_sql_referenced_entities() novamente:
SELECT 
  referenced_schema_name AS [Schema],
  referenced_entity_name AS Entity,
  referenced_minor_name AS Minor,
  referenced_class_desc AS Class,
  is_select_all,
  is_all_columns_found
FROM sys.dm_sql_referenced_entities (
    'dbo.uspGetClient', 
    'OBJECT');

Resultado:
Msg 207, Level 16, State 1, Procedure uspGetClient, Line 4
Invalid column name 'LastName'.
Msg 2020, Level 16, State 1, Line 3
The dependencies reported for entity "dbo.uspGetClient" might not include references to all columns. This is either because the entity references an object that does not exist or because of an error in one or more statements in the entity. Before rerunning the query, ensure that there are no errors in the entity and that all objects referenced by the entity exist.

Exemplo 4 – Descarte a tabela inteira


Vamos descobrir o que acontece se derrubarmos a tabela inteira.
DROP TABLE Client;

A mesa foi descartada.

Execute sys.dm_sql_referenced_entities() :
SELECT 
  referenced_schema_name AS [Schema],
  referenced_entity_name AS Entity,
  referenced_minor_name AS Minor,
  referenced_class_desc AS Class,
  is_select_all,
  is_all_columns_found
FROM sys.dm_sql_referenced_entities (
    'dbo.uspGetClient', 
    'OBJECT');

Resultado:
Msg 2020, Level 16, State 1, Line 2
The dependencies reported for entity "dbo.uspGetClient" might not include references to all columns. This is either because the entity references an object that does not exist or because of an error in one or more statements in the entity. Before rerunning the query, ensure that there are no errors in the entity and that all objects referenced by the entity exist.

Exemplo 5 – Retornar todas as colunas


A Microsoft recomenda especificamente não usar o asterisco (* ) para selecionar todas as colunas de visualizações e funções de gerenciamento dinâmico (das quais sys.dm_sql_referenced_entities() é um). Isso ocorre porque seus esquemas e os dados que eles retornam podem ser alterados em versões futuras do SQL Server. Isso pode resultar na adição de colunas ao final da lista de colunas em versões futuras, o que pode atrapalhar seu aplicativo se você estiver contando com o asterisco para selecionar todas as colunas.

Dito isso, aqui está um exemplo que faz exatamente isso:usa o asterisco (* ) para selecionar todas as colunas de sys.dm_sql_referenced_entities() . Estou fazendo isso apenas para mostrar quais colunas são realmente retornadas dessa função (pelo menos no SQL Server 2019).
SELECT *
FROM sys.dm_sql_referenced_entities (
    'dbo.uspGetClient', 
    'OBJECT');

Resultado (usando saída vertical):
-[ RECORD 1 ]-------------------------
referencing_minor_id     | 0
referenced_server_name   | NULL
referenced_database_name | NULL
referenced_schema_name   | dbo
referenced_entity_name   | Client
referenced_minor_name    | NULL
referenced_id            | 434100587
referenced_minor_id      | 0
referenced_class         | 1
referenced_class_desc    | OBJECT_OR_COLUMN
is_caller_dependent      | 0
is_ambiguous             | 0
is_selected              | 1
is_updated               | 0
is_select_all            | 0
is_all_columns_found     | 1
is_insert_all            | 0
is_incomplete            | 0
-[ RECORD 2 ]-------------------------
referencing_minor_id     | 0
referenced_server_name   | NULL
referenced_database_name | NULL
referenced_schema_name   | dbo
referenced_entity_name   | Client
referenced_minor_name    | ClientCode
referenced_id            | 434100587
referenced_minor_id      | 1
referenced_class         | 1
referenced_class_desc    | OBJECT_OR_COLUMN
is_caller_dependent      | 0
is_ambiguous             | 0
is_selected              | 1
is_updated               | 0
is_select_all            | 0
is_all_columns_found     | 1
is_insert_all            | 0
is_incomplete            | 0
-[ RECORD 3 ]-------------------------
referencing_minor_id     | 0
referenced_server_name   | NULL
referenced_database_name | NULL
referenced_schema_name   | dbo
referenced_entity_name   | Client
referenced_minor_name    | FirstName
referenced_id            | 434100587
referenced_minor_id      | 2
referenced_class         | 1
referenced_class_desc    | OBJECT_OR_COLUMN
is_caller_dependent      | 0
is_ambiguous             | 0
is_selected              | 1
is_updated               | 0
is_select_all            | 0
is_all_columns_found     | 1
is_insert_all            | 0
is_incomplete            | 0
-[ RECORD 4 ]-------------------------
referencing_minor_id     | 0
referenced_server_name   | NULL
referenced_database_name | NULL
referenced_schema_name   | dbo
referenced_entity_name   | Client
referenced_minor_name    | LastName
referenced_id            | 434100587
referenced_minor_id      | 3
referenced_class         | 1
referenced_class_desc    | OBJECT_OR_COLUMN
is_caller_dependent      | 0
is_ambiguous             | 0
is_selected              | 1
is_updated               | 0
is_select_all            | 0
is_all_columns_found     | 1
is_insert_all            | 0
is_incomplete            | 0
-[ RECORD 5 ]-------------------------
referencing_minor_id     | 0
referenced_server_name   | NULL
referenced_database_name | NULL
referenced_schema_name   | NULL
referenced_entity_name   | clientcode
referenced_minor_name    | NULL
referenced_id            | 257
referenced_minor_id      | 0
referenced_class         | 6
referenced_class_desc    | TYPE
is_caller_dependent      | 0
is_ambiguous             | 0
is_selected              | 0
is_updated               | 0
is_select_all            | 0
is_all_columns_found     | 0
is_insert_all            | 0
is_incomplete            | 0
(5 rows affected)

Documentação oficial


Para obter informações e exemplos mais detalhados, consulte sys.dm_sql_referenced_entities no site da Microsoft.