web-dev-qa-db-fra.com

Comment aller chercher les colonnes des Synonymes de serveurs liés dans SQL Server

J'utilise deux serveurs local (SQL Server exécutant sur mon système) et à distance (SQL Server exécutant sur un autre système). J'ai créé des synonymes sur mon serveur local pour une table située sur le serveur distant.

Synonyme utilisé- CREATE SYNONYM [dbo].[test] FOR remoteserver_name .[database_name].[schema_name].object_name

exigence

J'ai besoin d'aller chercher les colonnes du synonyme.

Je peux récupérer les colonnes du synonyme à l'aide de la requête ci-dessous dans SQL Server.

select * from dbo.test

dbo est le nom de schéma de synonyme (nom de schéma de serveur local) et test est nom de synonyme.

J'ai essayé de récupérer les colonnes des synonymes à l'aide de la requête ci-dessous, mais je ne peux pas récupérer les colonnes.

SELECT sys.schemas.name   AS SCHEMA_NAME,
       sys.synonyms.name  AS view_name,
       sys.columns.name   AS COL_NAME,
       sys.types.name     AS data_typename
FROM   sys.columns
       INNER JOIN sys.synonyms
            ON  OBJECT_ID(sys.synonyms.base_object_name) = sys.columns.object_id
       INNER JOIN sys.schemas
            ON  sys.schemas.schema_id = sys.synonyms.schema_id
       LEFT OUTER JOIN sys.types
            ON  sys.columns.system_type_id = sys.types.system_type_id
WHERE  sys.types.system_type_id = sys.types.user_type_id
       AND sys.schemas.name = N'scehmaname'
       AND sys.synonyms.name = N'synonymname'

Pouvez-vous suggérer une autre solution pour récupérer les colonnes du synonyme ou corriger la requête ci-dessus?

4

Votre erreur est que vous demandez à votre local Server sur l'objet à partir d'un autre, télécommande serveur.

OBJECT_ID(sys.synonyms.base_object_name) à partir de votre code sera résolu sur un serveur local car OBJECT_ID() fonctionne dans le serveur local, mais vous vous transmettez le nom du serveur distant, vous obtiendrez donc NULL ici.

Si vous souhaitez obtenir l'objet de l'objet distant object_id, Vous devriez faire de la smth comme ceci:

exec ('select object_id(''[remote_db].[remote_schema].[remote_table]'')') at [remote_server]

Et en général, si vous souhaitez obtenir les colonnes de l'objet distant, vous devez exécuter votre code sur le serveur remote, à la recherche de colonnes de REMOTE objet dans le Remotesys.columns Dans Télécommande Base de données, par exemple, de cette façon:

declare @obj_name sysname = '[remote_server].[remote_db].[remote_table]';
declare @code nvarchar(4000) =
N'select c.name   AS COL_NAME,
       t.name     AS data_typename
from sys.columns c
     join sys.types t
        on c.system_type_id = t.system_type_id
where c.object_id = object_id(@obj_name)';

declare @param_def nvarchar(400) = N'@obj_name sysname';

execute [remote_server].[remote_db].dbo.sp_executesql @code, @param_def, @obj_name = @obj_name;

Mise à jour 0

Scénario: J'ai un serveur A qui a deux bases de données (base de données1 et (base de données2). J'ai créé synonyme dans la base de données1. Créer synonyme [DBO]. [Synonyme] pour la base de données2. [DGNOM] Comment écrire une requête communément à Obtenez Object_ID pour ce scénario et objet distant?

Comme l'a mentionné Scott Hodgin, vous pouvez utiliser PARSENAME() pour vous débarrasser de la partie de votre objet de Remote_Server comme ceci:

declare @cmd varchar(8000) = (select 
       'select object_id(' + 
       quotename (
       PARSENAME(base_object_name,3)  + '.' + 
       PARSENAME(base_object_name,2)  + '.' + 
       PARSENAME(base_object_name,1), '''')+ ')'
from sys.synonyms )

exec (@cmd) at [server_A];

Mettre à jour 1

Je veux savoir si je peux accéder à la procédure stockée du serveur distant (serveur B) à partir du serveur local (serveur A).

...

Je ne peux pas obtenir la liste de la procédure stockée.

Vous pouvez obtenir la liste des procédures stockées à distance à l'aide de ce code:

select *
from remote_server.remote_db.sys.objects
where type = 'p';
4
sepupic

J'ai suscité sépupic réponse.

C'est un autre exemple de la façon dont vous pourriez faire cela - il peut être nécessaire d'être ajusté selon vos besoins.

J'utilise dynamique SQL et sp_columns .

Dans mon exemple, j'ai créé un synonyme appelé syntest comme suit:

CREATE SYNONYM [dbo].[SynTest] FOR [SqlCompare].[SCOPERATIONAL_DBCC].[SCFBDM].[CFG_LINE_BUS]

Ce synonyme pointe sur le serveur SqlCompare, base de données SCOPERATIONAL_DBCC, schéma SCFBDM et table CFG_LINE_BUS.

Émettre select * from sys.synonyms where name = 'syntest' révèle un nom de base_object de [SqlCompare].[SCOPERATIONAL_DBCC].[SCFBDM].[CFG_LINE_BUS]. Je peux utiliser PARSENAME Pour extraire les parties individuelles de la base_Object_name pour construire l'instruction SQL dynamique

Declare @Cmd nvarchar(4000)

select @Cmd = 
    'exec ' + PARSENAME(base_object_name,4) + '.' + 
    PARSENAME(base_object_name,3) + 
    '.dbo.sp_columns @table_name = ' + '''' + 
    PARSENAME(base_object_name,1) + 
    ''',@table_owner = ' + 
    '''' +  PARSENAME(base_object_name,2) + ''''
    from sys.synonyms where name = 'syntest'    --<<<< The name of your synonym
PRINT @CMD
exec sp_executesql @cmd

L'instruction PRINT montre le SQL dynamique construit comme étant

exec SqlCompare.SCOPERATIONAL_DBCC.dbo.sp_columns @table_name = 'CFG_LINE_BUS',@table_owner = 'SCFBDM'

3
Scott Hodgin