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.