2009-11-19 56 views
0

我需要一個鏈接服務器(SQL Server 2005中),這樣在同步執行三個動態SQL語句:執行多個動態報表一併在鏈接服務器

declare @statement nvarchar(max); 

set @statement = 'exec ' + @server_name + '.' + @database_name + '.dbo.Foo;exec ' + @server_name + '.' + @database_name + '.dbo.Bar;exec ' + @server_name + '.' + @database_name + '.dbo.BigTime'; 

exec sp_executesql @statement; 

爲了驗證這一點,我有一個鏈接的服務器的設置是鏈接到自己。

當執行本地(通過刪除@server_name),使用SQL事件探查器,我發現它作爲一個語句執行得很好。但是,當我通過鏈接服務器執行此操作時(使用@server_name變量),我在SQL Profiler中看到每個語句都單獨執行,每個語句後都會執行sp_reset_connection

跟蹤看起來是這樣的:

Audit Login .... 
exec database.dbo.Foo 
exec sp_reset_connection 
Audit Logout 
Audit Login .... 
exec database.dbo.Bar 
exec sp_reset_connection 
Audit Logout 
Audit Login .... 
exec database.dbo.BigTime 
exec sp_reset_connection 
Audit Logout 

這引起了我的問題。有沒有什麼原因可以指定給SQL Server在語句之間不調用sp_reset_connection

回答

0

你能不能在鏈接的服務器上調用其他3然後調用那個服務器?

爲什麼重置連接會導致問題?每個SP是否使用某種特殊類型的連接持久性存儲,如臨時表或其他?

+0

我不能修改鏈接的服務器上的任何東西。是的,重置連接會導致問題。 – 2009-11-20 14:47:10

1

您正在對三臺鏈接的服務器執行三次調用,結果正是您應該期待的內容(即使3臺鏈接的服務器並不相同)。要達到什麼樣的描述,你描述執行呼叫:執行一個鏈接服務器上三個步驟:

linkedserver.master.dbo.sp_ExecuteSQL N' 
    exec dbname.dbo.Foo; 
    exec dbname.dbo.Bar; 
    exec dbname.dbo.BigTime;'; 

所有你需要做的就是在動態生成的SQL繞到此:

declare @remoteStatement nvarchar(max), @localStatement nvarchar(max); 
set @remoteStatement = N'exec ' + @database_name + N'.dbo.Foo; 
    exec ' + @database_name + N'.dbo.Bar; 
    exec '+ @database_name + N'.dbo.BigTime'; 
set @localStatement = @server_name + N'.master.dbo.sp_executesql @remoteStatement;'; 

exec sp_executesql @localStatement, N'@remoteStatement nvarchar(max)', @remoteStatement; 
+0

Remus,我發佈了一些非常相似的東西。然而,你的聲明行將被炸燬。 – 2009-11-19 23:50:37

+0

謝謝Aaron,我修好了。即使沒有進行語法檢查,也能正確發佈信息... – 2009-11-19 23:56:39

0

這可能有所幫助:

BEGIN DISTRIBUTED TRANSACTION 
your stuff here 
COMMIT TRANSACTION 

爲此,您需要分佈式事務協調器運行。

+0

這沒有奏效。我得到:「服務器無法恢復交易,說明:3500000006。」回。雖然這是一個很好的想法。 – 2009-11-20 14:26:41

+0

MS DTC是否正在運行? – 2009-11-20 15:17:36

2
DECLARE @sql1 NVARCHAR(MAX), @sql2 NVARCHAR(MAX); 

SET @sql1 = 'EXEC ' + @database_name + '.dbo.Foo;' 
      + 'EXEC ' + @database_name + '.dbo.Bar;' 
      + 'EXEC ' + @database_name + '.dbo.BigTime;'; 

SET @sql2 = 'EXEC ' + @server_name + '.master.dbo.sp_executeSQL ''' + @sql1 + ''';'; 

EXEC sp_executeSQL @sql2; 
+0

這是master.sys.sp_executesql,順便說一句。我非常喜歡這個想法,但令我驚訝的是,它的表現非常相似。使用SQL事件探查器,我發現它觸發了第一個,然後是第二個,然後用sp_executesql作爲語句參數觸發sp_executesql!?! – 2009-11-20 15:15:24

+0

?這似乎對我很好:EXEC master.dbo.sp_executeSQL N'print''1'';'; ...對於多個調用,您運行profiler的服務器是哪個服務器,或者是接受它們的命令(@server_name)? – 2009-11-20 15:19:50

+0

爲了測試,我在本地做了一切。我有一個鏈接到自己的鏈接服務器。我發現在目標鏈接服務器上執行sp_executeSQL仍然導致每個語句都被sp_resetconnection調用分離出來,這真的很奇怪。 – 2009-12-12 22:26:45

0

根據Remus的回答,但是避免了一些使用sp_setnetname的動態SQL。因人而異。

這是問天或2前:Fully qualified table names with SP_ExecuteSql to access remote server

+0

我實際上並不知道sp_setnetname。是一個巧妙的技巧,但在併發環境中可能很危險,多個調用者可以相互更改名稱並造成嚴重破壞。 – 2009-11-20 07:15:38

+0

@remus:我在有限的情況下將它用作DBA,說實話我沒有想到它。我會使用sp_getapplock來控制它 – gbn 2009-11-20 07:31:18

+0

我不想將服務器名稱設置爲參數。 – 2009-11-20 14:34:45