OpenQuery 関数を使用してリモート テーブルに対する UPDATE、INSERT、または DELETE Transact-SQL ステートメントを実行するとエラー メッセージ "7357" および "7320" が表示される

現象

データの更新、削除、または挿入に OpenQuery 関数を使用する、次のような分散クエリを実行します。

exec sp_dropserver 'linked1', 'droplogins'
exec sp_addlinkedserver 'linked1', 'SQL Server'
exec sp_setnetname 'linked1', '<servername>'
exec sp_addlinkedsrvlogin 'linked1', 'false', null, '<login name>', '<password>'

SET ANSI_NULLS ON
go
SET ANSI_WARNINGS ON
go
select * from openquery (linked1, 'update testlinked set ssn=ssn+1')
select * from openquery (linked1, 'insert into testlinked (ssn) values (1000)')
select * from openquery (linked1, 'delete from testlinked where ssn=1')

この場合に、次のエラー メッセージが生成されることがあります。

サーバー : メッセージ 7357、レベル 16、状態 2、行 1
オブジェクト 'update testlinked set ssn=ssn' を処理できませんでした。OLE DB プロバイダ 'SQLOLEDB' はオブジェクトが列を持っていないことを示しています。



サーバー : メッセージ 7357、レベル 16、状態 2、行 1
[Microsoft][ODBC SQL Server Driver][SQL Server] オブジェクト 'update testlinked set ssn=ssn' を処理できませんでした。OLE DB プロバイダ 'MSDASQL' はオブジェクトが列を持っていないことを示しています。

エラー メッセージの実際のテキストは OLE DB プロバイダおよび実行しようとした操作 (UPDATE、INSERT、または DELETE) によって異なりますが、エラー番号は常に 7357 です。



Microsoft SQL Server 2005 を使用している場合には、次のエラー メッセージが表示されます。

サーバー : メッセージ 7357、レベル 16、状態 2、行 1
オブジェクト "update testlinked set ssn=ssn" を処理できません。リンク サーバー "ServerName" の OLE DB プロバイダ "SQLOLEDB" では、オブジェクトに列がないか、現在のユーザーがそのオブジェクトに対する権限を持っていないことが示されています。

原因

OpenQuery では結果セットが返される必要がありますが、OpenQuery で使用されている UPDATE、DELETE、および INSERT ステートメントでは結果セットが返されません。

回避策

この問題は、以下の方法で回避することができます。

  1. 4 部構成の名前 (linked_server_name.catalog.schema.object_name) を使用して挿入、更新、または削除操作を行います。

  2. SQL Server Books Online に記載されているように、OLE DB プロバイダの機能によっては、OpenQuery 関数を INSERT、UPDATE、または DELETE ステートメントの対象テーブルとして参照します。次のクエリは SQL Server OLE DB プロバイダでの正しい使用方法の例です。

    update openquery(linked1, 'select ssn from testlinked where ssn=2')
    set ssn=ssn + 1
    insert openquery(linked1, 'select ssn from testlinked where 1=0') values (1000)
    delete openquery(linked1, 'select ssn from testlinked where ssn>100')

    注 : INSERT ステートメントでは "where 1=0" という述語を使用して、リモート サーバーからデータを取得しないようにしています。リモート サーバーからデータを取得すると、パフォーマンスが低下する可能性があるためです。また、UPDATE および DELETE 操作については、インデックスに関して特別な要件があります。詳しくは「詳細」を参照してください。

詳細

一意のインデックスに関する要件


SQL Server OLE DB プロバイダでは、UPDATE や DELETE 操作の対象となるテーブルには一意のインデックスが存在している必要があります。リモート テーブルに一意のインデックスがない場合、UPDATE または DELETE を実行するときに次のエラーが発生します。

サーバー : メッセージ 7320、レベル 16、状態 2、行 1
OLE DB プロバイダ 'SQLOLEDB' に対してクエリを実行できませんでした。プロバイダが必要な行照合インターフェイスをサポートできませんでした。プロバイダが、ほかのプロパティまたは必要条件と競合が発生したことを示しています。
[OLE/DB provider returned message: 複数ステップの OLE DB の操作でエラーが発生しました。各 OLE DB の状態の値を確認してください。作業は終了しませんでした。]

これは、OpenQuery を使用した場合と 4 部構成の名前を使用した場合の両方の UPDATE および DELETE 操作に当てはまります。この問題は、リモート テーブルに一意のインデックスを追加することによって解決されます。


OpenQuery を使用した動的実行



次の例に示すように、OpenQuery を使用した場合と同じ結果を得るために、動的クエリを使用した方が良い場合があります。

begin tran
SET QUOTED_IDENTIFIER OFF
SET XACT_ABORT ON
declare @cmd varchar(2500)
declare @cmd1 varchar(2500)
declare @var varchar(20)
set @var = 'White'
declare @var1 varchar(20)
set @var1 = 'White1'
declare @var2 varchar(20)
set @var2 = 'Johnson1'

select @cmd = "Update openquery(linked1,'select au_lname, au_fname from pubs.dbo.authors
where au_lname = ''" + @var + "''' )
set au_lname = '" + @var1 + "',
au_fname = '" + @var2 + "'"

exec ( @cmd )

commit tran
select * from <servername>.pubs.dbo.authors

ヘルプを表示

スキルを磨く
トレーニングの探索
新機能を最初に入手
Microsoft Insider に参加する

この情報は役に立ちましたか?

フィードバックをお送りいただきありがとうございます!

フィードバックをお寄せいただき、ありがとうございます。Office サポートの担当者におつなぎいたします。

×