无法完成游标操作,因为在声明游标后表架构发生了变化

Eri*_*c S 2 schema linked-server sql-server-2014

当我执行从多个链接服务器提取信息并聚合数据的存储过程时,偶尔会收到此错误消息。它看起来与我下面的相似。

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
Run Code Online (Sandbox Code Playgroud)

它在每台服务器上调用的存储过程在每台服务器上都完全相同,并且是从 dbo 模式下的表中提取的基本选择语句。它将“随机”出错并显示“无法完成游标操作,因为在声明游标后表架构发生了变化”。有时它运行良好,有时则不然。每次运行时,即使背靠背有时会起作用,有时也不会。什么可能导致这种情况发生,为什么会如此断断续续?该错误可以在对其中一台服务器上的过程的任何给定调用中生成。它并不总是试图查询产生错误的同一台服务器。

值得一提的是,我有几个每个程序都做一些非常相似的事情,但从未产生过问题。但它们都在同一个架构 (dbo) 下,这是第一次使用不同的架构。

编辑 - 我忘了提到我曾尝试使用 FAST_FORWARD 游标,但它似乎没有帮助。

Aar*_*and 6

尝试将光标显式设置为LOCAL STATIC FORWARD_ONLY.

我不知道您的链接服务器上可能会发生哪些特定更改,或者该存储过程可能会涉及哪些内容,但 static 会复制数据以便光标不受影响(好吧,不关心)任何这些变化。

这与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;
Run Code Online (Sandbox Code Playgroud)