Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Exemplo de sys.dm_sql_referenced_entities() do SQL Server retornando uma entidade que faz referência a um servidor vinculado


Uma das coisas sobre o sys.dm_sql_referenced_entities() A função de gerenciamento dinâmico do sistema é que você pode usá-lo em entidades entre bancos de dados e servidores cruzados.

Isso significa que você pode encontrar entidades referenciadas que estão em um banco de dados diferente e até mesmo em um servidor diferente.

Este artigo fornece um exemplo de sys.dm_sql_referenced_entities() retornando um procedimento armazenado que consulta um banco de dados em um servidor vinculado.


Exemplo 1 - O Procedimento Armazenado


Primeiro, vamos criar um procedimento armazenado que retorne dados de um servidor vinculado:
CREATE PROCEDURE [dbo].[uspGetAlbumsByArtist] @ArtistId int AS
SELECT AlbumName
FROM [Homer].[Music].[dbo].[Albums]
WHERE ArtistId = @ArtistId;

Podemos ver que o procedimento armazenado usa um nome de quatro partes para fazer referência à tabela do banco de dados. Isso ocorre porque o banco de dados está em um servidor diferente que foi configurado como um servidor vinculado do servidor em que o procedimento armazenado está localizado.

Em outras palavras, esse procedimento armazenado retorna dados de um servidor vinculado.

Neste exemplo, Homer é o servidor vinculado e Music é o banco de dados.

Exemplo 2 – Execute sys.dm_sql_referenced_entities() no procedimento armazenado


Agora vamos usar sys.dm_sql_referenced_entities() para retornar as entidades referenciadas no procedimento armazenado.
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');

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

Portanto, ele retornou com sucesso a tabela que está sendo referenciada (embora não o nome da coluna/menor). Também inclui o nome do servidor ( Homer ) e o nome do banco de dados ( Música ).

Observe que não retornei todas as colunas neste exemplo por questões de brevidade.

Exemplo 3 – Executando sys.dm_sql_referenced_entities() NO Servidor Vinculado


Esses resultados parecem diferentes do que obteríamos se o procedimento armazenado estivesse no servidor vinculado real (remoto)?

Vamos tentar.

Aqui, eu pulo para o outro servidor e executo o seguinte código:
CREATE PROCEDURE [dbo].[uspGetAlbumsByArtist] @ArtistId int AS
SELECT AlbumName
FROM [dbo].[Albums]
WHERE ArtistId = @ArtistId;

Observe que não preciso usar a nomenclatura de quatro partes, visto que está consultando tabelas no mesmo servidor.

Agora execute sys.dm_sql_referenced_entities() no servidor vinculado:
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');

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

Nesse caso, as colunas são incluídas nos resultados.

Observe também que as colunas Servidor e Banco de Dados são NULL para todas as linhas. Isso ocorre porque nenhum deles está incluído na definição do procedimento armazenado. Se eu alterar a definição do procedimento armazenado para incluir o servidor e o banco de dados, eu os veria aqui. No entanto, o servidor aparece apenas na primeira linha.
ALTER PROCEDURE [dbo].[uspGetAlbumsByArtist] @ArtistId int AS
SELECT AlbumName
FROM [SQLServer007].[Music].[dbo].[Albums]
WHERE ArtistId = @ArtistId;

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

Nesse caso, o nome do servidor é SQLServer007, então tive que usar isso em vez de Homer (que é o nome que dei ao criar um servidor vinculado do outro servidor).

Também podemos usar OPENQUERY() se quisermos voltar para o servidor local e executá-lo no servidor vinculado:
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'');'
);

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

Observe que neste caso eu tive que escapar de todos os caracteres de aspas simples.

Além disso, se eu tentar executar a função por meio de uma consulta distribuída (sem usar OPENQUERY() ), recebo a mensagem de erro 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');

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