【发布时间】:2018-03-14 20:07:31
【问题描述】:
我之前问过一个关于如何在脚本的其余部分仍在运行时立即提供输出的PRINT 的问题(请参阅:How to see progress of running SQL stored procedures?)。简单的答案是使用:
RAISERROR ('My message', 0, 1) WITH NOWAIT
但是,我注意到返回的输出并不总是即时的,尤其是当它返回大量结果时。作为一个简单的实验,请考虑以下脚本:
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
上面的脚本会输出 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),输出设置为“Results to Text”还是“Results to Grid”没有区别。
编辑:显然,这种批处理行为发生在 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
当您在 LinqPad 中运行上述脚本时,只会立即输出第一行。其余的只会在 5 秒后输出...
那么,任何人都知道 SSMS 的一个很好的轻量级替代品,它是免费的,不需要安装,并且可以使用 RAISERROR WITH NOWAIT 的即时输出和表格结果?
【问题讨论】:
-
我怀疑它是一个批处理问题,在我看来,它只是当处理器让线程吐到窗口时,你看到的只是机器上的延迟。
-
那为什么会有 3 组不同的行为呢?他们也非常一致......