ユーザーがリンクサーバーを介して次のことを実行したいというシナリオがあります。
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です。
@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
のコンテンツ全体がリモートサーバーで実行されます。
問題はセキュリティ関連ではありません:-)。
クエリでは、リモートシステムのテーブルから選択していますが、WHERE条件はOBJECT_ID()
関数を使用しています。これはローカルインスタンスのみを表示でき、リンクサーバーのスコープでは実行されていません接続。
やってみませんか:
select *
from [DBTEST].[AdventureWorks].sys.objects
where [name] = N'DatabaseLog';
このクエリは、既に名前を持っているので、とにかく意味があり、2番目のクエリでIDを使用するためだけに名前からIDを取得するクエリでは意味がありません;-)。
スキーマ名でもフィルタリングする必要がある場合は、[DBTEST].[AdventureWorks].sys.schemas
もローカルスコープのみであるため、JOINをOBJECT_SCHEMA_NAME
テーブルに追加する必要があります。