Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Beispiel für sys.dm_sql_referenced_entities() von SQL Server, das eine Entität zurückgibt, die auf einen verknüpften Server verweist

Eines der Dinge über sys.dm_sql_referenced_entities() Die dynamische Verwaltungsfunktion des Systems besteht darin, dass Sie sie für datenbank- und serverübergreifende Entitäten verwenden können.

Das bedeutet, dass Sie referenzierte Entitäten finden können, die sich in einer anderen Datenbank und sogar auf einem anderen Server befinden.

Dieser Artikel enthält ein Beispiel für sys.dm_sql_referenced_entities() Zurückgeben einer gespeicherten Prozedur, die eine Datenbank auf einem Verbindungsserver abfragt.

Beispiel 1 – Die gespeicherte Prozedur

Lassen Sie uns zunächst eine gespeicherte Prozedur erstellen, die Daten von einem Verbindungsserver zurückgibt:

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

Wir können sehen, dass die gespeicherte Prozedur einen vierteiligen Namen verwendet, um auf die Datenbanktabelle zu verweisen. Dies liegt daran, dass sich die Datenbank auf einem anderen Server befindet, der als Verbindungsserver konfiguriert wurde, als der Server, auf dem sich die gespeicherte Prozedur befindet.

Mit anderen Worten, diese gespeicherte Prozedur gibt Daten von einem Verbindungsserver zurück.

In diesem Beispiel Homer ist der Verbindungsserver und Music ist die Datenbank.

Beispiel 2 – Führen Sie sys.dm_sql_referenced_entities() für die gespeicherte Prozedur aus

Lassen Sie uns nun sys.dm_sql_referenced_entities() verwenden um die Entitäten zurückzugeben, auf die in der gespeicherten Prozedur verwiesen wird.

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

Ergebnis:

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

Es hat also erfolgreich die Tabelle zurückgegeben, auf die verwiesen wird (jedoch nicht den Spalten-/Minor-Namen). Es enthält auch den Servernamen ( Homer ) und den Datenbanknamen ( Music ).

Beachten Sie, dass ich in diesem Beispiel der Kürze halber nicht alle Spalten zurückgegeben habe.

Beispiel 3 – Ausführen von sys.dm_sql_referenced_entities() auf dem verknüpften Server

Sehen diese Ergebnisse anders aus, als wenn sich die gespeicherte Prozedur auf dem tatsächlichen (entfernten) verknüpften Server befände?

Lass es uns versuchen.

Hier springe ich auf den anderen Server und führe den folgenden Code aus:

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

Beachten Sie, dass ich die vierteilige Benennung nicht verwenden muss, da Tabellen vom selben Server abgefragt werden.

Führen Sie nun sys.dm_sql_referenced_entities() aus auf dem Verbindungsserver:

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

Ergebnis:

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

In diesem Fall werden die Spalten in die Ergebnisse aufgenommen.

Beachten Sie auch, dass die Spalten Server und Database für alle Zeilen NULL sind. Dies liegt daran, dass keines davon in der Definition der gespeicherten Prozedur enthalten ist. Wenn ich die Definition der gespeicherten Prozedur so ändere, dass sie den Server und die Datenbank enthält, würde ich sie hier sehen. Allerdings erscheint der Server nur in der ersten Zeile.

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

Ergebnis:

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

In diesem Fall lautet der Name des Servers SQLServer007, also musste ich diesen anstelle von Homer verwenden (das ist der Name, den ich ihm gegeben habe, als ich einen Verbindungsserver von dem anderen Server erstellt habe).

Wir können auch OPENQUERY() verwenden wenn wir zum lokalen Server zurückspringen und ihn gegen den verknüpften Server ausführen wollten:

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

Ergebnis:

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

Beachten Sie, dass ich in diesem Fall alle einfachen Anführungszeichen maskieren musste.

Auch wenn ich versuche, die Funktion über eine verteilte Abfrage auszuführen (ohne OPENQUERY() zu verwenden). ), erhalte ich die Fehlermeldung 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');

Ergebnis:

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