Jedna z rzeczy związanych z sys.dm_sql_referenced_entities()
funkcja dynamicznego zarządzania systemem polega na tym, że można go używać w jednostkach międzybazowych i międzyserwerowych.
Oznacza to, że możesz znaleźć jednostki odniesienia, które znajdują się w innej bazie danych, a nawet na innym serwerze.
Ten artykuł zawiera przykład sys.dm_sql_referenced_entities()
zwracając procedurę składowaną, która wysyła zapytania do bazy danych na serwerze połączonym.
Przykład 1 – Procedura składowana
Najpierw utwórzmy procedurę składowaną, która zwraca dane z połączonego serwera:
CREATE PROCEDURE [dbo].[uspGetAlbumsByArtist] @ArtistId int AS SELECT AlbumName FROM [Homer].[Music].[dbo].[Albums] WHERE ArtistId = @ArtistId;
Widzimy, że procedura składowana używa czteroczęściowej nazwy do odwoływania się do tabeli bazy danych. Dzieje się tak, ponieważ baza danych znajduje się na innym serwerze, który został skonfigurowany jako serwer połączony z serwerem, na którym znajduje się procedura składowana.
Innymi słowy, ta procedura składowana zwraca dane z połączonego serwera.
W tym przykładzie Homer
jest połączonym serwerem, a Music
to baza danych.
Przykład 2 – Uruchom sys.dm_sql_referenced_entities() przeciwko procedurze przechowywanej
Teraz użyjmy sys.dm_sql_referenced_entities()
aby zwrócić jednostki, do których odwołuje się procedura składowana.
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');
Wynik:
+----------+------------+----------+----------+---------+------------------+ | Server | Database | Schema | Entity | Minor | Class | |----------+------------+----------+----------+---------+------------------| | Homer | Music | dbo | Albums | NULL | OBJECT_OR_COLUMN | +----------+------------+----------+----------+---------+------------------+
Więc pomyślnie zwrócił tabelę, do której się odwołujemy (choć nie nazwę kolumny/pobocznej). Zawiera również nazwę serwera ( Homer ) i nazwę bazy danych ( Muzyka ).
Zwróć uwagę, że nie zwróciłem wszystkich kolumn w tym przykładzie ze względu na zwięzłość.
Przykład 3 – Uruchamianie sys.dm_sql_referenced_entities() NA połączonym serwerze
Czy te wyniki wyglądają inaczej niż te, które otrzymalibyśmy, gdyby procedura składowana znajdowała się na rzeczywistym (zdalnym) serwerze połączonym?
Spróbujmy.
Tutaj przeskakuję na inny serwer i uruchamiam następujący kod:
CREATE PROCEDURE [dbo].[uspGetAlbumsByArtist] @ArtistId int AS SELECT AlbumName FROM [dbo].[Albums] WHERE ArtistId = @ArtistId;
Zauważ, że nie muszę używać czteroczęściowego nazewnictwa, ponieważ odpytuje on tabele na tym samym serwerze.
Teraz uruchom sys.dm_sql_referenced_entities()
na połączonym serwerze:
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');
Wynik:
+----------+------------+----------+----------+-----------+------------------+ | 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 | +----------+------------+----------+----------+-----------+------------------+
W takim przypadku kolumny są uwzględniane w wynikach.
Należy również zauważyć, że kolumny Serwer i Baza danych mają wartość NULL we wszystkich wierszach. Dzieje się tak, ponieważ żaden z nich nie jest zawarty w definicji procedury składowanej. Jeśli zmienię definicję procedury składowanej tak, aby zawierała serwer i bazę danych, zobaczyłbym je tutaj. Jednak serwer pojawia się tylko w pierwszym wierszu.
ALTER PROCEDURE [dbo].[uspGetAlbumsByArtist] @ArtistId int AS SELECT AlbumName FROM [SQLServer007].[Music].[dbo].[Albums] WHERE ArtistId = @ArtistId;
Wynik:
+--------------+------------+----------+----------+-----------+------------------+ | 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 | +--------------+------------+----------+----------+-----------+------------------+
W tym przypadku nazwa serwera to SQLServer007, więc musiałem użyć tej nazwy zamiast Homera (takiej nazwy nadałem mu podczas tworzenia serwera połączonego z innego serwera).
Możemy również użyć OPENQUERY()
gdybyśmy chcieli wrócić do lokalnego serwera i uruchomić go na połączonym serwerze:
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'');' );
Wynik:
+--------------+------------+----------+----------+-----------+------------------+ | 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 | +--------------+------------+----------+----------+-----------+------------------+
Zauważ, że w tym przypadku musiałem uciec przed wszystkimi znakami pojedynczego cudzysłowu.
Ponadto, jeśli spróbuję uruchomić funkcję za pomocą zapytania rozproszonego (bez użycia OPENQUERY()
), otrzymuję komunikat o błędzie 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');
Wynik:
Msg 4122, Level 16, State 1, Line 10 Remote table-valued function calls are not allowed.