ローカル(システムで実行されているSQL Server)とリモート(別のシステムで実行されているSQL Server)の2つのサーバーを使用しています。ローカルサーバーに、リモートサーバーにあるテーブルのシノニムを作成しました。
使用されている同義語-CREATE SYNONYM [dbo].[test] FOR remoteserver_name .[database_name].[schema_name].object_name
要件
シノニムの列をフェッチする必要があります。
SQLサーバーで以下のクエリを使用して、シノニムの列を取得できます。
select * from dbo.test
場所
dbo
はシノニムで作成されたスキーマ名(ローカルサーバースキーマ名)で、test
はシノニム名です。
以下のクエリを使用してシノニムの列を取得しようとしましたが、列をフェッチできません
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'
シノニムの列を取得する別の方法を提案したり、上記のクエリを修正したりできますか?
あなたのエラーは、別のリモートサーバーからのオブジェクトについてlocalサーバーに質問することです。
OBJECT_ID(sys.synonyms.base_object_name)
はローカルサーバー内で動作するため、コードからのOBJECT_ID()
はローカルサーバーで解決されますが、リモートサーバーから名前を渡すため、NULL
ここに。
リモートオブジェクトの_object_id
_を取得する場合は、次のように実行する必要があります。
_exec ('select object_id(''[remote_db].[remote_schema].[remote_table]'')') at [remote_server]
_
そして一般的に、リモートオブジェクトの列を取得したい場合は、remote
サーバーでコードを実行し、remoteオブジェクトの列をリモート _sys.columns
_ remoteデータベースで、たとえば、次のように:
_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;
_
更新
シナリオ:2つのデータベース(database1と(database2)を持つサーバーAがあります。database1にシノニムを作成しました。CREATESYNONYM [dbo]。[synonym] FOR database2。[dbo]。[objectname]クエリを一般的に書き込む方法このシナリオとリモートオブジェクトのobject_idを取得しますか?
Scott Hodginが述べたように、PARSENAME()
を使用して、次のようにオブジェクトのremote_serverの部分を取り除くことができます。
_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];
_
更新1
ローカルサーバー(サーバーA)からリモートサーバー(サーバーB)のストアドプロシージャにアクセスできるかどうかを知りたい。
...
ストアドプロシージャのリストを取得できません。
次のコードを使用して、リモートストアドプロシージャのリストを取得できます。
_select *
from remote_server.remote_db.sys.objects
where type = 'p';
_
sepupic の回答に賛成しました。
これは、これを行う方法のもう1つの例です。要件に応じて調整する必要がある場合があります。
動的SQLと sp_columns を使用しています。
私の例では、次のようにsyntest
という同義語を作成しました。
CREATE SYNONYM [dbo].[SynTest] FOR [SqlCompare].[SCOPERATIONAL_DBCC].[SCFBDM].[CFG_LINE_BUS]
この同義語は、サーバーSqlCompare
、データベースSCOPERATIONAL_DBCC
、スキーマSCFBDM
、およびテーブルCFG_LINE_BUS
を指します。
select * from sys.synonyms where name = 'syntest'
を発行すると、base_object_nameが[SqlCompare].[SCOPERATIONAL_DBCC].[SCFBDM].[CFG_LINE_BUS]
であることがわかります。 [〜#〜] parsename [〜#〜] を使用して、base_object_nameの個々の部分を抽出し、動的SQLステートメントを作成できます
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
PRINT
ステートメントは、構築された動的SQLを次のように示します。
exec SqlCompare.SCOPERATIONAL_DBCC.dbo.sp_columns @table_name = 'CFG_LINE_BUS',@table_owner = 'SCFBDM'