受到这个问题的启发,关于SET NOCOUNT有不同的观点…

我们应该使用SET NOCOUNT ON SQL Server吗?如果不是,为什么不是?

它的作用编辑6,2011年7月22日

它在任何DML之后抑制“受影响的xx行”消息。这是一个结果集,当发送时,客户端必须处理它。它很小,但可测量(见下面的答案)

对于触发器等,客户端将收到多个“受影响的xx行”,这将导致一些orm, MS Access, JPA等的各种错误(见下面的编辑)

背景:

一般公认的最佳实践(我认为直到这个问题)是在SQL Server的触发器和存储过程中使用SET NOCOUNT ON。我们到处使用它,快速谷歌显示大量的SQL Server mvp也同意。

MSDN说这会破坏。net SQLDataAdapter。

现在,这对我来说意味着SQLDataAdapter仅限于完全简单的CRUD处理,因为它期望匹配“受影响的n行”消息。所以,我不能用:

IF EXISTS以避免重复(没有行影响消息)注意:谨慎使用 WHERE不存在(行数比预期的少 过滤掉琐碎的更新(例如没有数据实际变化) 在之前进行任何表访问(例如日志记录) 隐藏复杂性或去规范化 等

在这个问题中marc_s(谁知道他的SQL东西)说不要使用它。这与我的想法不同(我认为自己在SQL方面也有一定的能力)。

我可能遗漏了一些东西(尽管指出显而易见的事实),但你们怎么看?

注意:我已经好几年没有看到这个错误了,因为我现在不使用SQLDataAdapter。

评论和问题后的编辑:

编辑:更多想法…

我们有多个客户端:一个可能使用c# SQLDataAdaptor,另一个可能使用来自Java的nHibernate。这些可以通过SET NOCOUNT ON以不同的方式受到影响。

如果您将存储的proc视为方法,那么假定某些内部处理以某种方式为您自己的目的是不合适的(反模式)。

编辑2:一个触发中断nHibernate问题,其中SET NOCOUNT ON不能设置

(不,它不是这个的副本)

编辑3:更多信息,感谢我的MVP同事

KB 240882,在SQL 2000和更早的版本上导致断开连接的问题 性能增益演示

编辑4:2011年5月13日

打破linq2 SQL太当没有指定?

编辑5:14 2011年6月

打破JPA,存储过程与表变量:JPA 2.0支持SQL Server表变量吗?

编辑6:15 2011年8月

SSMS“编辑行”数据网格需要SET NOCOUNT ON:用GROUP BY更新触发器

编辑7: 07 Mar 2013

更深入的细节来自@RemusRusanu: SET NOCOUNT ON真的有这么大的性能差异吗


当前回答

SET NOCOUNT ON甚至允许像这样访问受影响的行:

SET NOCOUNT ON

DECLARE @test TABLE (ID int)

INSERT INTO @test
VALUES (1),(2),(3)

DECLARE @affectedRows int = -99  

DELETE top (1)
  FROM @test
SET @affectedRows = @@rowcount

SELECT @affectedRows as affectedRows

结果

affectedRows 1

消息

命令执行成功。 完成时间:2020-06-18T16:20:16.9686874+02:00

其他回答

关于破坏NHibernate的触发器,我有第一手的经验。基本上,当NH执行UPDATE时,它预计受影响的行数是一定的。通过将SET NOCOUNT ON添加到触发器,您可以获得NH期望的行数,从而解决问题。所以,如果你使用NH,我绝对建议关闭触发器。

至于在SPs中的使用,这是个人喜好的问题。我总是关闭行计数,但话说回来,这两种方法都没有真正有力的论据。

另一方面,您应该真正考虑远离基于sp的体系结构,这样您甚至不会遇到这个问题。

SET NOCOUNT ON甚至允许像这样访问受影响的行:

SET NOCOUNT ON

DECLARE @test TABLE (ID int)

INSERT INTO @test
VALUES (1),(2),(3)

DECLARE @affectedRows int = -99  

DELETE top (1)
  FROM @test
SET @affectedRows = @@rowcount

SELECT @affectedRows as affectedRows

结果

affectedRows 1

消息

命令执行成功。 完成时间:2020-06-18T16:20:16.9686874+02:00

SET NOCOUNT ON-将显示“Command(s) completed successfully”。 SET NOCOUNT OFF-它将显示”(No。受影响的行)”。

我不知道如何在客户端和SQL之间测试SET NOCOUNT ON,所以我测试了其他SET命令的类似行为“SET TRANSACTION ISOLATION LEVEL READ unimcommitted”

我从我的连接发送了一个命令,改变SQL的默认行为(READ COMMITTED),它被更改为下一个命令。 当我在存储过程中更改ISOLATION级别时,它不会更改下一个命令的连接行为。

目前的结论,

在存储过程中更改设置不会更改连接默认设置。 通过使用ADOCOnnection发送命令更改设置将更改默认行为。

我认为这与其他SET命令相关,如“SET NOCOUNT ON”

我知道这是个很老的问题。只是更新一下。

使用“SET NOCOUNT ON”的最佳方法是将其作为SP中的第一个语句,并在最后一个SELECT语句之前再次将其设置为OFF。