Sql-Server-2014

無法完成游標操作,因為在聲明游標後表架構發生了變化

  • September 27, 2018

當我執行從多個連結伺服器提取資訊並聚合數據的儲存過程時,偶爾會收到此錯誤消息。它看起來類似於我下面的內容。

DECLARE Cur CURSOR FOR SELECT name FROM sys.servers WHERE is_linked = 1 AND (@Environments IS NULL OR name IN (SELECT Item FROM clrStringSplit(@Environments, ',')))
OPEN cur
FETCH NEXT FROM cur INTO @Environment
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY   

   SET @Query = '          
       EXEC ' + @Environment + '.db.dashboard.storedproc ''' + CAST(@StartDate AS VARCHAR(10)) + ''', ''' + CAST(@EndDate AS VARCHAR(10)) + ''''

   INSERT INTO #Table (Environment, Column1, Column2, Column3, Column4, Column5, Column6, Column7)
   EXEC(@Query)
END TRY
BEGIN CATCH
   PRINT 'There was an error trying to query against ' + @Environment
   PRINT ERROR_MESSAGE() 
END CATCH

FETCH NEXT FROM cur INTO @Environment
END

它在每台伺服器上呼叫的儲存過程在每台伺服器上都完全相同,並且是從 dbo 模式下的表中提取的基本選擇語句。它將“隨機”出錯,並顯示“無法完成游標操作,因為聲明游標後表模式已更改”的消息。有時它執行良好,有時則不然。每次執行時,即使背靠背有時會起作用,有時不會。什麼可能導致這種情況發生,為什麼它如此斷斷續續?對其中一台伺服器上的過程的任何給定呼叫都可能會生成錯誤。它嘗試查詢的伺服器並不總是會產生錯誤。

值得一提的是,我有幾個程序執行極其相似但從未產生問題的每個程序。但它們都在同一個模式(dbo)下,這是第一次使用不同的模式。

編輯 - 我忘了提到我曾嘗試使用 FAST_FORWARD 游標,但它似乎沒有幫助。

嘗試將游標顯式設置為LOCAL STATIC FORWARD_ONLY.

我不知道您的連結伺服器上可能會發生哪些特定更改,或者該儲存過程可能會觸及什麼,但是靜態會複製數據,這樣游標就不會受到影響(好吧,不關心)任何這些變化。

這與sp_MSforeachdb導致它跳過數據庫的問題相同。他們在那裡使用了錯誤類型的游標,並且由於錯誤處理,自游標打開以來以任何方式觸及的數據庫都會被靜默地跳過。這就是為什麼我在 Brent Ozar Unlimited 的First Responder Kit中編寫了一個也可用的替代品- 並進行了一些方便的改進。

順便說一句,有一種更好的方法可以在由變數提供的數據庫/伺服器上執行動態 SQL。這通常使得使用sp_executesql和傳遞強類型參數成為可能(而不是在所有地方加倍引號,將整數和日期轉換為字元串,等等)。

DECLARE @exec nvarchar(512);

... while loop ...

SET @exec = @Environment + N'.db.sys.sp_executesql';

INSERT INTO #Table 
(
  Environment, Column1, Column2, Column3, 
    Column4, Column5, Column6, Column7
)
EXEC @exec N'EXEC dashboard.storedproc @StartDate, @EndDate;',
  N'@StartDate datetime, @EndDate datetime', @StartDate, @EndDate;

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