sql >> Base de Datos >  >> RDS >> Sqlserver

Ejemplo de sys.dm_sql_referenced_entities() de SQL Server que devuelve una entidad que hace referencia a un servidor vinculado

Una de las cosas sobre sys.dm_sql_referenced_entities() La función de administración dinámica del sistema es que puede usarla en entidades de bases de datos cruzadas y servidores cruzados.

Esto significa que puede encontrar entidades a las que se hace referencia que están en una base de datos diferente e incluso en un servidor diferente.

Este artículo proporciona un ejemplo de sys.dm_sql_referenced_entities() devolver un procedimiento almacenado que consulta una base de datos en un servidor vinculado.

Ejemplo 1:el procedimiento almacenado

Primero, creemos un procedimiento almacenado que devuelva datos de un servidor vinculado:

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

Podemos ver que el procedimiento almacenado usa un nombre de cuatro partes para hacer referencia a la tabla de la base de datos. Esto se debe a que la base de datos está en un servidor diferente que se ha configurado como un servidor vinculado desde el servidor en el que se encuentra el procedimiento almacenado.

En otras palabras, este procedimiento almacenado devuelve datos de un servidor vinculado.

En este ejemplo, Homer es el servidor vinculado, y Music es la base de datos.

Ejemplo 2:ejecute sys.dm_sql_referenced_entities() contra el procedimiento almacenado

Ahora usemos sys.dm_sql_referenced_entities() para devolver las entidades a las que se hace referencia en el procedimiento almacenado.

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

Por lo tanto, devolvió con éxito la tabla a la que se hace referencia (aunque no la columna/nombre secundario). También incluye el nombre del servidor ( Homer ) y el nombre de la base de datos ( Música ).

Tenga en cuenta que no devolví todas las columnas en este ejemplo por razones de brevedad.

Ejemplo 3:ejecutar sys.dm_sql_referenced_entities() EN el servidor vinculado

¿Esos resultados se ven diferentes a lo que obtendríamos si el procedimiento almacenado estuviera en el servidor vinculado real (remoto)?

Vamos a intentarlo.

Aquí, salto al otro servidor y ejecuto el siguiente código:

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

Tenga en cuenta que no necesito usar el nombre de cuatro partes, ya que está consultando tablas del mismo servidor.

Ahora ejecute sys.dm_sql_referenced_entities() en el 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 |
+----------+------------+----------+----------+-----------+------------------+

En este caso, las columnas se incluyen en los resultados.

También tenga en cuenta que las columnas Servidor y Base de datos son NULL para todas las filas. Esto se debe a que ninguno de ellos está incluido en la definición del procedimiento almacenado. Si modifico la definición del procedimiento almacenado para incluir el servidor y la base de datos, los vería aquí. Sin embargo, el servidor solo aparece en la primera fila.

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

En este caso, el nombre del servidor es SQLServer007, así que tuve que usarlo en lugar de Homer (que es el nombre que le di al crear un servidor vinculado desde el otro servidor).

También podemos usar OPENQUERY() si quisiéramos volver al servidor local y ejecutarlo contra el 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 |
+--------------+------------+----------+----------+-----------+------------------+

Tenga en cuenta que en este caso tuve que escapar de todos los caracteres de comillas simples.

Además, si trato de ejecutar la función a través de una consulta distribuida (sin usar OPENQUERY() ), aparece el mensaje de error 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.