SQL Server:SET NOCOUNT ON 仍在返回数据

Mar*_*ark 2 sql-server sql-server-2016

按照此页面中的示例,我无法阻止存储过程返回选择数据集。

执行这个:

SET NOCOUNT OFF;
GO
-- Display the count message.
SELECT 'should be displayed'
GO
-- SET NOCOUNT to ON to no longer display the count message.
SET NOCOUNT ON;
GO
SELECT 'should NOT be displayed'
GO
-- Reset SET NOCOUNT to OFF
SET NOCOUNT OFF;
GO
Run Code Online (Sandbox Code Playgroud)

将返回给我:

在问题上设置无计数

这是一个错误吗?有什么不对?我在 SQL Server 13.0.4206 上

Dav*_*ett 14

您正在查看 SQL Server 输出的错误部分。NOCOUNT只控制在SELECT/ INSERT/ UPDATE/ DELETE/MERGE操作之后输出的额外的“受影响的行”消息,而不是任何SELECT没有指定目的地的行集输出。如果您将 SSMS 设置为将输出显示为文本,您可以看到这一点:

SET NOCOUNT OFF
SELECT test='NoCount is OFF'
SET NOCOUNT ON
SELECT test='NoCount is ON'
SET NOCOUNT OFF
SELECT test='NoCount is OFF again'
-- now lets try with operations that store the rowset instead of sending as output
SET NOCOUNT OFF
PRINT 'A rows affected count should follow'
SELECT test='NoCount is OFF' INTO #temptable
SET NOCOUNT ON
PRINT 'But there won''t be one for this statement'
SELECT test='NoCount is ON' INTO #temptable2
SET NOCOUNT OFF
PRINT 'A rows affected count should follow'
SELECT test='NoCount is OFF again' INTO #temptable3
Run Code Online (Sandbox Code Playgroud)

将产生输出:

test
--------------
NoCount is OFF

(1 row(s) affected)

test
-------------
NoCount is ON

test
--------------------
NoCount is OFF again

(1 row(s) affected)

A rows affected count should follow

(1 row(s) affected)
But there won't be one for this statement
A rows affected count should follow

(1 row(s) affected)
Run Code Online (Sandbox Code Playgroud)

或者,如果您将 SSMS 设置为在网格中显示输出,您将在结果选项卡中获得网格,并在消息选项卡中获得以下内容:

(1 row(s) affected)

(1 row(s) affected)
A rows affected count should follow

(1 row(s) affected)
But there won't be one for this statement
A rows affected count should follow

(1 row(s) affected)
Run Code Online (Sandbox Code Playgroud)

没有办法(据我所知)阻止想要输出它们的存储过程输出的所有行集。

可以使用该表单INSERT <table> EXEC <procedure> <params>将输出放入临时表中(然后只需删除该表或在会话结束时将其删除)以隐藏第一组结果,但这有许多重大限制:

  1. 表必须已经存在,你不能做等效的SELECT <stuff> INTO <newtable> FROM ...,它添加了一大块额外的代码(创建表)

  2. 与其他INSERT任何表一样,要么表必须具有正确的列数,要么您需要指定目标列,当然,在任何一种情况下,它们都必须是兼容的类型

  3. INSERT <table> EXEC ... 不能嵌套,因此如果该过程可能也使用任何依赖项,则会中断 INSERT <table> EXEC ...

  4. 它只能捕获一个结果集,因此如果被调用的过程返回多个结果集,则不会按您的意愿工作

另一件要注意的事情NOCOUNT是,被调用的存储过程可能会通过使用SET NOCOUNT {ON|OFF}自己来覆盖您指定的设置,因此它可能会输出计数而忽略您的设置,并且您需要在每次调用后检查/重置它以确保它是您想要的(有关如何使用@@OPTIONS 进行检查,请参阅 Artashes 的回答)。

  • @Mark 您可能对 [`FMTONLY`](https://docs.microsoft.com/en-US/sql/t-sql/statements/set-fmtonly-transact-sql) 感兴趣 (2认同)