set nocount on 抑制的是每条 select、insert、update、delete 执行后返回的“(5 行受影响)”类 done_in_proc 状态消息,而非结果集本身;它不影响 @@rowcount 更新,但可避免客户端误将行计数当作结果集解析,显著减少网络流量并提升性能。

SET NOCOUNT ON 会抑制哪些消息?
它抑制的是每条 SELECT、INSERT、UPDATE、DELETE 执行后返回的 (5 行受影响) 这类 DONE_IN_PROC 状态消息,不是结果集本身。这些消息在 SQL Server Management Studio(SSMS)的“消息”选项卡里可见,但在客户端程序中会被当作额外的结果集处理。
不加 SET NOCOUNT ON 容易踩什么坑?
常见错误现象包括:
- ADO.NET 中调用
SqlCommand.ExecuteNonQuery()却抛出InvalidOperationException: There is already an open data reader associated with this command—— 因为多出来的行计数消息被误判为未读完的结果集 - Entity Framework 执行存储过程后报
Invalid operation. The connection is closed.或无法映射返回值,本质是框架试图消费所有结果集,却被冗余的 DONE_IN_PROC 消息干扰 - SSIS 包执行存储过程时出现“结果集不匹配”警告,或数据流任务意外中断
- Power BI / Reporting Services 刷新报表时报“无法识别多个结果集”,尤其当存储过程含循环或多个 DML 语句时
SET NOCOUNT ON 对 @@ROWCOUNT 和逻辑有影响吗?
没有影响。即使开了 SET NOCOUNT ON,@@ROWCOUNT 依然准确更新,所有业务逻辑判断(比如 IF @@ROWCOUNT = 0 RAISERROR)照常工作。真正被屏蔽的只是发给客户端的那条文本消息,不是行数统计本身。
实操建议:
- 始终把
SET NOCOUNT ON放在存储过程BEGIN后第一行 - 不必配对写
SET NOCOUNT OFF—— 该设置作用域仅限当前批处理,退出存储过程即自动失效,强行加OFF反而可能干扰调用方上下文 - 触发器里也建议加,因为触发器隐式运行在用户语句上下文中,不加容易让外层应用收到意料之外的行计数
什么时候不该开 SET NOCOUNT ON?
极少数情况:客户端明确依赖每条语句的行数反馈做流程控制(例如某些老 VB6 或 Delphi 应用用 RecordsAffected 做分支),或者调试时需要快速确认某步 DML 是否生效。但这类场景应优先改造客户端逻辑,而非妥协服务端性能。
真正容易被忽略的是:它对性能的影响不在 CPU 或磁盘,而在 TDS 协议层——每条 DONE_IN_PROC 消息都是一次独立的网络帧发送。一个含 20 次 UPDATE 的循环,就多发 20 次小包,高并发下积少成多。











