与NOWAIT的RAISERROR不那么直接?

SF *_*Lee 11 sql t-sql

我之前问过一个关于如何PRINT在脚本的其余部分仍在运行时立即提供输出的问题(请参阅:如何查看运行SQL存储过程的进度?).简单的答案是使用:

RAISERROR ('My message', 0, 1) WITH NOWAIT
Run Code Online (Sandbox Code Playgroud)

但是,我注意到返回的输出并不总是立即的,特别是当它返回大量结果时.作为一个简单的实验,请考虑以下脚本:

DECLARE @count INT
SET @count = 1

WHILE @count <= 5000
BEGIN
    RAISERROR ('Message %d', 0, 1, @count) WITH NOWAIT
    WAITFOR DELAY '00:00:00.01'
    SET @count = @count + 1
END
Run Code Online (Sandbox Code Playgroud)

上面的脚本将吐出5000行文本.如果您运行脚本,您会注意到:

  • 对于前500行(1 - 500行),它立即返回每个输出行.
  • 对于接下来的500行(501-1000行),它每50行返回一次输出.(所有50行将一起批处理,并且仅在每个第50行的末尾返回.)
  • 对于之后的每一行(1001 - *行),它每100行返回一次输出.(所有100行将一起批处理,仅在每100行末尾返回.)

所以这意味着在前500行之后,RAISERROR WITH NOWAIT不再按预期工作,并且给我带来问题,因为我想看看我长时间运行的脚本的进度.

所以我的问题:是否有任何方法可以禁用这种"批量"行为并使其始终立即返回?


编辑:我正在使用SSMS(SQL Server Management Studio)来运行上面的脚本.它似乎影响所有版本(SSMS和SQL Server),以及输出是否设置为"结果到文本"或"结果到网格"没有区别.

编辑:显然,这个批处理行为发生在500行后,无论字节数.所以,我已经相应地更新了上面的问题.

编辑:感谢Fredou指出这是SSMS的问题,而像LinqPad这样的第三方工具也不会有这个问题.

但是,我发现当你在输出中有表结果时,LinqPad不会立即输出.例如,请考虑以下代码:

RAISERROR ('You should see this immediately', 0, 1) WITH NOWAIT
SELECT * FROM master.sys.databases
RAISERROR ('You should see this immediately too, along with a table above.', 0, 1) WITH NOWAIT
WAITFOR DELAY '00:00:05'
RAISERROR ('You should see this 5 seconds later...', 0, 1) WITH NOWAIT
Run Code Online (Sandbox Code Playgroud)

在LinqPad中运行上述脚本时,只会立即输出第一行.其余的只会在5秒后输出......

所以,任何人都知道SSMS的轻量级替代品是免费的,不需要安装,并且可以使用NOWAIT与表结果混合的RAISERROR的即时输出吗?

小智 6

如果您将结果设置为文本,这似乎在 2008R2 中有效。 在此处输入图片说明


SF *_*Lee 3

只要将输出选项设置为“文本中的结果” , Query ExPlus似乎就可以解决问题。

另一个粗略的替代方案是sqlcmd,它作为 SQL Server 的一部分安装。这也有效,但表格结果往往很混乱并且难以在命令控制台屏幕上阅读......