web-dev-qa-db-ja.com

INSERT INTO ... EXEC ATリンクサーバーを一時テーブルに使用すると、メッセージ7391で失敗する

SQL Server 2014を使用しています。EXEC (@remotecmd) AT [server_name];(@remotecmdはストアドプロシージャではなく動的SQLです)を##eapbに実行します。私のコードは

insert into ##eapb
EXEC (@remotecmd) AT [ADSQLDB3S\DEV];

しかし、私はエラーが出ます:

リンクサーバー "server_name"のOLE DBプロバイダー "SQLNCLI11"は、メッセージ "トランザクションマネージャーがリモート/ネットワークトランザクションのサポートを無効にしました。"を返しました。
メッセージ7391、レベル16、状態2、行71
リンクサーバー「server_name」のOLE DBプロバイダー「SQLNCLI11」が分散トランザクションを開始できなかったため、操作を実行できませんでした。

insert into ##eapbを削除しても、エラーは発生しません。

リンクサーバーのRPC OutオプションはTrueに設定されています。

5

私のテストでは(別のサーバーではなく同じサーバー上の別のインスタンスに対して)、リンクサーバーオプションRPCの分散トランザクションのプロモーションを有効にするを "False"に設定している場合に機能しました。これは、次のコマンドで実行できます。

EXEC master.dbo.sp_serveroption
       @server = N'{linked_server_name}',
       @optname = N'remote proc transaction promotion',
       @optvalue = N'false';

これは、分散トランザクションコーディネーター(MSDTC)で、ON(実行中)とOFF(停止中)の両方で機能しました。

通常、「リモートプロシージャトランザクションプロモーション」オプションを「True」に設定する必要があり、「False」に設定すると、このINSERT...EXECが機能する場合は、同じプロパティをすべて備えた別のリンクサーバーを設定できます。この1つのオプションが異なることを除いて。

「リモートプロシージャトランスプロモーション」を無効にすることの主な欠点は、リモートサーバーでのトランザクションではないということです。したがって、そこでエラーが発生した場合、データはローカルに(明らかに)挿入されませんが、リモートで実行されたDMLステートメントがある場合、それらはまだコミットできます(単一のステートメントか複数のステートメントかによって異なります)。それでも、リモートクエリで適切なトランザクション処理を使用できます(つまり、TRY...CATCH構成を使用します)。

CREATE TABLE #Local ([name] [sysname]);


INSERT INTO #Local ([name])
    EXEC (N'
BEGIN TRY
    BEGIN TRAN;
    SELECT [name] FROM sys.servers WHERE 1/0 = ''a'';
    COMMIT;
END TRY
BEGIN CATCH
    ROLLBACK TRAN;
    THROW;
END CATCH;
') AT [{linked_server_name}];

追伸RPC Outオプションを有効にする必要があります/ True。質問に対するコメントによると、このオプションはすでに正しく設定されているため、これについては上記で触れていません。

5
Solomon Rutzky

使うことができます:

SELECT *
INTO #TABLATEMP
FROM Openquery([link-server-name],N' Execute anything ')

Select Campo1, Campo2, Campo3, .... CampoN
FRom #TABLATEMP

DROP TABLE #TABLATEMP

- それで全部です!!!

1
Erwin Gonzalez