Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Esempio di sys.dm_sql_referenced_entities() di SQL Server che restituisce un'entità che fa riferimento a un server collegato

Una delle cose su sys.dm_sql_referenced_entities() la funzione di gestione dinamica del sistema è che puoi utilizzarla su entità cross-database e cross-server.

Ciò significa che puoi trovare entità referenziate che si trovano in un database diverso e anche su un server diverso.

Questo articolo fornisce un esempio di sys.dm_sql_referenced_entities() restituire una procedura memorizzata che interroga un database su un server collegato.

Esempio 1 – La procedura archiviata

Per prima cosa, creiamo una procedura memorizzata che restituisce i dati da un server collegato:

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

Possiamo vedere che la procedura memorizzata utilizza un nome in quattro parti per fare riferimento alla tabella del database. Ciò è dovuto al fatto che il database si trova su un server diverso che è stato configurato come server collegato dal server in cui si trova la procedura memorizzata.

In altre parole, questa procedura memorizzata restituisce i dati da un server collegato.

In questo esempio, Homer è il server collegato e Music è il database.

Esempio 2:eseguire sys.dm_sql_referenced_entities() rispetto alla stored procedure

Ora usiamo sys.dm_sql_referenced_entities() per restituire le entità a cui si fa riferimento nella procedura memorizzata.

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

Risultato:

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

Quindi ha restituito correttamente la tabella a cui si fa riferimento (sebbene non la colonna/nome secondario). Include anche il nome del server ( Homer ) e il nome del database ( Music ).

Nota che non ho restituito tutte le colonne in questo esempio per motivi di brevità.

Esempio 3 – Esecuzione di sys.dm_sql_referenced_entities() sul server collegato

Questi risultati hanno un aspetto diverso da quello che otterremmo se la stored procedure fosse sul server collegato (remoto) effettivo?

Proviamolo.

Qui, salto all'altro server ed eseguo il seguente codice:

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

Nota che non ho bisogno di usare la denominazione in quattro parti, visto che sta interrogando le tabelle sullo stesso server.

Ora esegui sys.dm_sql_referenced_entities() sul server collegato:

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

Risultato:

+----------+------------+----------+----------+-----------+------------------+
| 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 questo caso, le colonne vengono incluse nei risultati.

Si noti inoltre che le colonne Server e Database sono NULL per tutte le righe. Questo perché nessuno di questi è incluso nella definizione della stored procedure. Se alterassi la definizione della stored procedure per includere il server e il database, li vedrei qui. Tuttavia, il server appare solo nella prima riga.

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

Risultato:

+--------------+------------+----------+----------+-----------+------------------+
| 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 questo caso, il nome del server è SQLServer007, quindi ho dovuto usarlo al posto di Homer (che è il nome che gli ho dato durante la creazione di un server collegato dall'altro server).

Possiamo anche usare OPENQUERY() se volessimo tornare al server locale ed eseguirlo sul server collegato:

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

Risultato:

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

Nota che in questo caso ho dovuto evitare tutti i caratteri delle virgolette singole.

Inoltre, se provo a eseguire la funzione tramite una query distribuita (senza usare OPENQUERY() ), ottengo il messaggio di errore 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');

Risultato:

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