web-dev-qa-db-ja.com

リンクサーバーを介してSQLサーバーメタデータをクエリできません

ユーザーがリンクサーバーを介して次のことを実行したいというシナリオがあります。

SELECT *
FROM [DBTEST].[AdventureWorks].sys.objects
WHERE object_id = OBJECT_ID(N'dbo.DatabaseLog');

リンクサーバーはBe made using this security contextを使用するように構成されており、リンクサーバーログインは[DBTEST].[AdventureWorks]データベースに対する読み取りアクセス権を持っています。

上記のクエリは、リンクサーバーを介して実行された場合、行を返しません。ただし、リンクサーバーログインを使用してDBTESTに直接ログインし、次の操作を行うと、行が返されます。

SELECT * 
FROM [AdventureWorks].sys.objects
WHERE object_id = OBJECT_ID(N'dbo.DatabaseLog')

リンクサーバーを介して機能しない理由と、それを修正するために何をする必要があるのか​​、混乱しています。

もう1つの奇妙なことは、リンクサーバーのログインにsa権限を付与しても、リンクサーバーを介して実行されても行が返されないことです。

どちらのサーバーもSQL Server 2008 Enterprise Editionです。

3
SQLPRODDBA

@srutzkyは正しいです。これはnotセキュリティに関連しています。彼が言ったように、OBJECT_ID()関数はリモートインスタンスではなくローカルSQL Serverインスタンスに対して動作しています。

ステートメントを変更せずにリモートサーバーに対して実行する場合は、次のコマンドを使用して、動的T-SQLを介して実行する必要があります。

DECLARE @sql NVARCHAR(MAX);

SET @sql = 'SELECT *
FROM [AdventureWorks].sys.objects
WHERE object_id = OBJECT_ID(N''dbo.DatabaseLog'');';

EXEC [DBTEST].AdventureWorks.sys.sp_executesql @sql;

これにより、@sqlのコンテンツ全体がリモートサーバーで実行されます。

3
Max Vernon

問題はセキュリティ関連ではありません:-)。

クエリでは、リモートシステムのテーブルから選択していますが、WHERE条件はOBJECT_ID()関数を使用しています。これはローカルインスタンスのみを表示でき、リンクサーバーのスコープでは実行されていません接続。

やってみませんか:

select *
from [DBTEST].[AdventureWorks].sys.objects
where [name] = N'DatabaseLog';

このクエリは、既に名前を持っているので、とにかく意味があり、2番目のクエリでIDを使用するためだけに名前からIDを取得するクエリでは意味がありません;-)。

スキーマ名でもフィルタリングする必要がある場合は、[DBTEST].[AdventureWorks].sys.schemasもローカルスコープのみであるため、JOINをOBJECT_SCHEMA_NAMEテーブルに追加する必要があります。

3
Solomon Rutzky