sql >> Base de Datos >  >> RDS >> Sqlserver

Encuentre entidades referenciadas en SQL Server:sys.dm_sql_referenced_entities

En SQL Server, puede usar sys.dm_sql_referenced_entities() función de gestión dinámica del sistema para obtener una lista de todas las entidades definidas por el usuario a las que se hace referencia por nombre, en la definición de una entidad dada.

En otras palabras, devuelve una lista de todas las entidades definidas por el usuario de las que depende una entidad específica.

Específicamente, informa sobre los siguientes tipos de entidades a las que hace referencia la entidad de referencia especificada:

  • Entidades vinculadas al esquema
  • Entidades no vinculadas al esquema
  • Entidades entre bases de datos y entre servidores
  • Dependencias a nivel de columna en entidades vinculadas y no vinculadas al esquema
  • Tipos definidos por el usuario (alias y CLR UDT)
  • Colecciones de esquemas XML
  • Funciones de partición

Sintaxis

La sintaxis es así:

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

Ejemplo 1 – Ejemplo básico

He aquí un ejemplo 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                      |
+----------+------------+------------+------------------+-----------------+------------------------+

Aquí obtengo todas las entidades a las que se hace referencia en dbo.uspGetClient procedimiento almacenado. En este caso hay cinco entidades.

La primera es la tabla llamada “Cliente”. Las siguientes tres son todas columnas dentro de esa tabla. El último es un tipo de datos de alias definido por el usuario llamado "código de cliente".

También podemos ver que los primeros cuatro se usan en una declaración de selección que usa el asterisco (* ) comodín para seleccionar todas las columnas (porque su is_select_all se establece en 1 ).

Esta es la definición real utilizada para crear el procedimiento almacenado que estamos analizando:

CREATE PROCEDURE [dbo].[uspGetClient] @ClientCode clientcode AS
SELECT * 
FROM [dbo].[Client]
WHERE ClientCode = @ClientCode;

Sí, es un procedimiento almacenado muy simple, pero es ideal para nuestros propósitos. Podemos ver todas las entidades a las que se hace referencia devueltas por sys.dm_sql_referenced_entities() .

También podemos ver que el procedimiento consta de un solo SELECT consulta que utiliza el comodín asterisco para seleccionar todas las columnas.

Ejemplo 2:elimine "Seleccionar todo" (* )

Modifiquemos el procedimiento almacenado para que no use el comodín asterisco para seleccionar todas las columnas.

ALTER PROCEDURE [dbo].[uspGetClient] @ClientCode clientcode AS
SELECT 
    FirstName,
    LastName
FROM [dbo].[Client]
WHERE ClientCode = @ClientCode;

Entonces ahora devuelve explícitamente las columnas "Nombre" y "Apellido". No se encontraron comodines.

Ahora ejecute sys.dm_sql_referenced_entities() de nuevo:

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                      |
+----------+------------+------------+------------------+-----------------+------------------------+

Esta vez, el is_select_all la columna muestra 0 en todas las filas.

Ejemplo 3:hacer referencia a una entidad inexistente

¿Qué sucede si su entidad hace referencia a una entidad inexistente?

Por ejemplo, ¿qué sucede si su colega suelta una columna a la que realmente hace referencia un procedimiento almacenado y luego ejecuta sys.dm_sql_referenced_entities()? contra ese procedimiento almacenado?

Vamos a averiguarlo.

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

Acabo de soltar el LastName columna de mi tabla.

Ahora ejecute sys.dm_sql_referenced_entities() de nuevo:

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.

Ejemplo 4:Suelta toda la tabla

Averigüemos qué sucede si dejamos caer toda la tabla.

DROP TABLE Client;

La mesa se ha caído.

Ejecute 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.

Ejemplo 5:devolver todas las columnas

Microsoft recomienda específicamente no usar el asterisco (* ) para seleccionar todas las columnas de las vistas y funciones de administración dinámica (de las cuales sys.dm_sql_referenced_entities() es uno). Esto se debe a que sus esquemas y los datos que devuelven pueden cambiar en futuras versiones de SQL Server. Esto podría resultar en que se agreguen columnas al final de la lista de columnas en versiones futuras, lo que podría estropear su aplicación si confía en el asterisco para seleccionar todas las columnas.

Dicho esto, aquí hay un ejemplo que hace exactamente eso:usa el asterisco (* ) para seleccionar todas las columnas de sys.dm_sql_referenced_entities() . Solo estoy haciendo esto para mostrarle qué columnas se devuelven realmente desde esta función (al menos en SQL Server 2019).

SELECT *
FROM sys.dm_sql_referenced_entities (
    'dbo.uspGetClient', 
    'OBJECT');

Resultado (usando salida 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)

Documentación Oficial

Para obtener información más detallada y ejemplos, consulte sys.dm_sql_referenced_entities en el sitio web de Microsoft.