Sql-Server

如何將連結伺服器中儲存過程的結果保存到變數或表中?

  • February 13, 2022

我需要讀取連結伺服器中儲存過程的結果,並將它們儲存在變數中,如果不可能的話,將它們儲存在臨時表中。

我可以這樣做,並且得到正確的結果:

EXEC ('EXEC DBName.dbo.procedure_name') AT [xxx.xx.xxx.xx]

但是,當我嘗試做這樣的事情時:

DECLARE @Result NVARCHAR(200) = (EXEC ('EXEC DBName.dbo.procedure_name') AT [xxx.xx.xxx.xx])

或者是這樣的:

INSERT #TempTable EXEC ('EXEC DBName.dbo.procedure_name') AT [xxx.xx.xxx.xx]

我收到這個錯誤

無法執行操作,因為連結伺服器的 OLE DB 提供程序“SQLNCLI11”無法開始分佈式事務

我怎樣才能將這個結果儲存在某個地方?更大的過程需要它,因此必須儲存它。

如果它是問題中所示的單個值,並且您可以修改遠端過程,則另一種選擇是使用輸出參數:

-- On the remote server
CREATE PROCEDURE dbo.ProcName
   @Result nvarchar(200) OUTPUT
AS
   ...
   SET @Result = ...

然後在本地實例上:

DECLARE @Result nvarchar(200);
EXECUTE [xxx.xx.xxx.xx].DBName.dbo.ProcName @Result OUTPUT;
SELECT @Result;

您的 INSERT 創建了一個本地事務,其中 SQL Server 正在嘗試使用分佈式事務來登記遠端過程呼叫,但失敗了。

所以禁用連結伺服器的分佈式事務提升,例如

EXEC master.dbo.sp_serveroption @server=N'[MyLinkedServer]', @optname=N'remote proc transaction promotion', @optvalue=N'false'

那麼它應該可以工作,例如

exec [MyLinkedServer].SomeDb.sys.sp_executesql N'create proc foo as select ''hello'' msg'
go
drop table if exists #TempTable
create table #TempTable( m varchar(200))
INSERT #TempTable EXEC ('EXEC SomeDb.dbo.foo') AT [MyLinkedServer]
select * from #TempTable

或者您可以使用輸出參數從遠端過程中擷取單個標量值,

declare @msg varchar(200);
exec [MyLinkedServer].SomeDb.sys.sp_executesql N'
declare @t table(msg varchar(200))
insert into @t(msg) 
exec dbo.foo
set @msg = (select msg from @t)', N'@msg varchar(200) output', @msg = @msg output;
select @msg msg

引用自:https://dba.stackexchange.com/questions/307361