Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Rechercher des entités référencées dans SQL Server :sys.dm_sql_referenced_entities

Dans SQL Server, vous pouvez utiliser le sys.dm_sql_referenced_entities() fonction de gestion dynamique du système pour obtenir une liste de toutes les entités définies par l'utilisateur qui sont référencées par leur nom, dans la définition d'une entité donnée.

En d'autres termes, il renvoie une liste de toutes les entités définies par l'utilisateur dont dépend une entité spécifique.

Plus précisément, il signale les types d'entités suivants référencés par l'entité de référence spécifiée :

  • Entités liées au schéma
  • Entités non liées au schéma
  • Entités inter-bases de données et inter-serveurs
  • Dépendances au niveau des colonnes sur les entités liées et non liées au schéma
  • Types définis par l'utilisateur (alias et CLR UDT)
  • Collections de schémas XML
  • Fonctions de partition

Syntaxe

La syntaxe ressemble à ceci :

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

Exemple 1 - Exemple de base

Voici un exemple d'utilisation :

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');

Résultat :

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

Ici, je récupère toutes les entités référencées dans le dbo.uspGetClient procédure stockée. Dans ce cas, il y a cinq entités.

La première est la table appelée "Client". Les trois suivantes sont toutes des colonnes de ce tableau. Le dernier est un type de données d'alias défini par l'utilisateur appelé "clientcode".

Nous pouvons également voir que les quatre premiers sont utilisés dans une instruction select qui utilise l'astérisque (* ) joker pour sélectionner toutes les colonnes (parce que leur is_select_all est défini sur 1 ).

Voici la définition réelle utilisée pour créer la procédure stockée que nous analysons :

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

Oui, c'est une procédure stockée très simple, mais elle est idéale pour nos besoins. Nous pouvons voir toutes les entités référencées telles qu'elles sont renvoyées par sys.dm_sql_referenced_entities() .

Nous pouvons également voir que la procédure consiste en un seul SELECT requête qui utilise le caractère générique astérisque pour sélectionner toutes les colonnes.

Exemple 2 - Supprimer le "Sélectionner tout" (* )

Modifions la procédure stockée afin qu'elle n'utilise pas le caractère générique astérisque pour sélectionner toutes les colonnes.

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

Ainsi, il renvoie désormais explicitement les colonnes "FirstName" et "LastName". Aucun caractère générique à trouver.

Exécutez maintenant sys.dm_sql_referenced_entities() encore :

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');

Résultat :

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

Cette fois, le is_select_all la colonne affiche 0 sur toutes les lignes.

Exemple 3 - Référencer une entité inexistante

Que se passe-t-il si votre entité fait référence à une entité inexistante ?

Par exemple, que se passe-t-il si votre collègue supprime une colonne qui est en fait référencée par une procédure stockée, puis que vous exécutez sys.dm_sql_referenced_entities() contre cette procédure stockée ?

Découvrons.

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

Je viens de supprimer le LastName colonne de ma table.

Exécutez maintenant sys.dm_sql_referenced_entities() encore :

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');

Résultat :

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.

Exemple 4 - Supprimer toute la table

Découvrons ce qui se passe si nous supprimons toute la table.

DROP TABLE Client;

La table a été supprimée.

Exécutez 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');

Résultat :

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.

Exemple 5 - Renvoyer toutes les colonnes

Microsoft recommande spécifiquement de ne pas utiliser l'astérisque (* ) pour sélectionner toutes les colonnes des vues et fonctions de gestion dynamique (dont sys.dm_sql_referenced_entities() est une). En effet, leurs schémas et les données qu'ils renvoient peuvent changer dans les futures versions de SQL Server. Cela pourrait entraîner l'ajout de colonnes à la fin de la liste des colonnes dans les versions futures, ce qui pourrait perturber votre application si vous comptez sur l'astérisque pour sélectionner toutes les colonnes.

Cela dit, voici un exemple qui fait exactement cela :utilise l'astérisque (* ) pour sélectionner toutes les colonnes de sys.dm_sql_referenced_entities() . Je fais cela uniquement pour vous montrer quelles colonnes sont réellement renvoyées par cette fonction (au moins dans SQL Server 2019).

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

Résultat (en utilisant la sortie verticale) :

-[ 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)

Documentation officielle

Pour des informations plus détaillées et des exemples, voir sys.dm_sql_referenced_entities sur le site Web de Microsoft.