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

Exemple de sys.dm_sql_referenced_entities() de SQL Server renvoyant une entité qui référence un serveur lié

Une des choses à propos de sys.dm_sql_referenced_entities() La fonction de gestion dynamique du système est que vous pouvez l'utiliser sur des entités inter-bases de données et inter-serveurs.

Cela signifie que vous pouvez trouver des entités référencées qui se trouvent dans une base de données différente et même sur un serveur différent.

Cet article fournit un exemple de sys.dm_sql_referenced_entities() renvoyant une procédure stockée qui interroge une base de données sur un serveur lié.

Exemple 1 - La procédure stockée

Commençons par créer une procédure stockée qui renvoie les données d'un serveur lié :

CREATE PROCEDURE [dbo].[uspGetAlbumsByArtist] @ArtistId int AS
SELECT AlbumName
FROM [Homer].[Music].[dbo].[Albums]
WHERE ArtistId = @ArtistId;

Nous pouvons voir que la procédure stockée utilise un nom en quatre parties pour référencer la table de la base de données. Cela est dû au fait que la base de données se trouve sur un serveur différent qui a été configuré en tant que serveur lié à partir du serveur sur lequel se trouve la procédure stockée.

En d'autres termes, cette procédure stockée renvoie les données d'un serveur lié.

Dans cet exemple, Homer est le serveur lié, et Music est la base de données.

Exemple 2 – Exécuter sys.dm_sql_referenced_entities() sur la procédure stockée

Utilisons maintenant sys.dm_sql_referenced_entities() pour retourner les entités référencées dans la procédure stockée.

SELECT 
    referenced_server_name AS [Server],
     referenced_database_name AS [Database],
     referenced_schema_name AS [Schema],
     referenced_entity_name AS [Entity],
     referenced_minor_name AS [Minor],
     referenced_class_desc AS [Class]
FROM sys.dm_sql_referenced_entities (
    'dbo.uspGetAlbumsByArtist', 
    'OBJECT');

Résultat :

+----------+------------+----------+----------+---------+------------------+
| Server   | Database   | Schema   | Entity   | Minor   | Class            |
|----------+------------+----------+----------+---------+------------------|
| Homer    | Music      | dbo      | Albums   | NULL    | OBJECT_OR_COLUMN |
+----------+------------+----------+----------+---------+------------------+

Ainsi, il a renvoyé avec succès la table référencée (mais pas le nom de colonne/mineur). Il inclut également le nom du serveur ( Homer ) et le nom de la base de données ( Musique ).

Notez que je n'ai pas renvoyé toutes les colonnes de cet exemple par souci de brièveté.

Exemple 3 - Exécution de sys.dm_sql_referenced_entities() SUR le serveur lié

Ces résultats sont-ils différents de ce que nous obtiendrions si la procédure stockée se trouvait sur le serveur lié réel (distant) ?

Essayons.

Ici, je saute sur l'autre serveur et j'exécute le code suivant :

CREATE PROCEDURE [dbo].[uspGetAlbumsByArtist] @ArtistId int AS
SELECT AlbumName
FROM [dbo].[Albums]
WHERE ArtistId = @ArtistId;

Notez que je n'ai pas besoin d'utiliser le nommage en quatre parties, car il interroge les tables sur le même serveur.

Exécutez maintenant sys.dm_sql_referenced_entities() sur le serveur lié :

SELECT 
    referenced_server_name AS [Server],
     referenced_database_name AS [Database],
     referenced_schema_name AS [Schema],
     referenced_entity_name AS [Entity],
     referenced_minor_name AS [Minor],
     referenced_class_desc AS [Class]
FROM sys.dm_sql_referenced_entities (
    '[dbo].uspGetAlbumsByArtist', 
    'OBJECT');

Résultat :

+----------+------------+----------+----------+-----------+------------------+
| Server   | Database   | Schema   | Entity   | Minor     | Class            |
|----------+------------+----------+----------+-----------+------------------|
| NULL     | NULL       | dbo      | Albums   | NULL      | OBJECT_OR_COLUMN |
| NULL     | NULL       | dbo      | Albums   | AlbumName | OBJECT_OR_COLUMN |
| NULL     | NULL       | dbo      | Albums   | ArtistId  | OBJECT_OR_COLUMN |
+----------+------------+----------+----------+-----------+------------------+

Dans ce cas, les colonnes sont incluses dans les résultats.

Notez également que les colonnes Server et Database sont NULL pour toutes les lignes. En effet, aucun de ceux-ci n'est inclus dans la définition de la procédure stockée. Si je modifie la définition de la procédure stockée pour inclure le serveur et la base de données, je les verrais ici. Cependant, le serveur n'apparaît que dans la première ligne.

ALTER PROCEDURE [dbo].[uspGetAlbumsByArtist] @ArtistId int AS
SELECT AlbumName
FROM [SQLServer007].[Music].[dbo].[Albums]
WHERE ArtistId = @ArtistId;

Résultat :

+--------------+------------+----------+----------+-----------+------------------+
| Server       | Database   | Schema   | Entity   | Minor     | Class            |
|--------------+------------+----------+----------+-----------+------------------|
| SQLServer007 | Music      | dbo      | Albums   | NULL      | OBJECT_OR_COLUMN |
| NULL         | Music      | dbo      | Albums   | AlbumName | OBJECT_OR_COLUMN |
| NULL         | Music      | dbo      | Albums   | ArtistId  | OBJECT_OR_COLUMN |
+--------------+------------+----------+----------+-----------+------------------+

Dans ce cas, le nom du serveur est SQLServer007, j'ai donc dû l'utiliser à la place de Homer (qui est le nom que je lui ai donné lors de la création d'un serveur lié à partir de l'autre serveur).

Nous pouvons également utiliser OPENQUERY() si nous voulions revenir au serveur local et l'exécuter sur le serveur lié :

SELECT * FROM OPENQUERY(
    Homer,
    'SELECT 
    referenced_server_name AS [Server],
     referenced_database_name AS [Database],
     referenced_schema_name AS [Schema],
     referenced_entity_name AS [Entity],
     referenced_minor_name AS [Minor],
     referenced_class_desc AS [Class]
FROM sys.dm_sql_referenced_entities (
    ''[dbo].uspGetAlbumsByArtist'', 
    ''OBJECT'');'
);

Résultat :

+--------------+------------+----------+----------+-----------+------------------+
| Server       | Database   | Schema   | Entity   | Minor     | Class            |
|--------------+------------+----------+----------+-----------+------------------|
| SQLServer007 | Music      | dbo      | Albums   | NULL      | OBJECT_OR_COLUMN |
| NULL         | Music      | dbo      | Albums   | AlbumName | OBJECT_OR_COLUMN |
| NULL         | Music      | dbo      | Albums   | ArtistId  | OBJECT_OR_COLUMN |
+--------------+------------+----------+----------+-----------+------------------+

Notez que dans ce cas, j'ai dû échapper tous les guillemets simples.

De plus, si j'essaie d'exécuter la fonction via une requête distribuée (sans utiliser OPENQUERY() ), j'obtiens le message d'erreur 4122 :

SELECT 
    referenced_server_name AS [Server],
     referenced_database_name AS [Database],
     referenced_schema_name AS [Schema],
     referenced_entity_name AS [Entity],
     referenced_minor_name AS [Minor],
     referenced_class_desc AS [Class]
FROM [Homer].[Music].[sys].dm_sql_referenced_entities (
    '[dbo].[uspGetAlbumsByArtist]', 
    'OBJECT');

Résultat :

Msg 4122, Level 16, State 1, Line 10
Remote table-valued function calls are not allowed.