与NOWAIT的RAISERROR不那么直接?

时间:2014-04-02 23:01:02

标签: sql tsql

我之前曾问过一个问题,即如何在脚本的其余部分仍在运行时立即提供输出的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的轻量级替代品是免费的,不需要安装,可以使用NOWAIT与表结果混合的RAISERROR的即时输出吗?

3 个答案:

答案 0 :(得分:3)

它似乎是sql server management studio的限制&gt; = 2005

如果您有2000,则不会有此限制

source

我刚用LinqPad尝试过你的代码,我无法重现这种行为

答案 1 :(得分:3)

如果您将结果设置为文本,它将在2008R2中显示。 enter image description here

答案 2 :(得分:2)

只要你将输出选项设置为“文本结果”

Query ExPlus似乎就可以了。

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