
В SQL Server каждая инструкция INSERT, UPDATE, DELETE по умолчанию возвращает клиенту сообщение с количеством затронутых строк. Эти сообщения не видны в результирующем наборе данных, но передаются по сетевому соединению и обрабатываются драйвером клиента. В простых запросах это почти незаметно, однако при выполнении хранимых процедур с десятками операторов суммарное число таких сообщений быстро растет.
Команда SET NOCOUNT ON отключает отправку этих служебных сообщений. Сервер продолжает выполнять все операции и изменять данные, но клиент получает только те результаты, которые действительно запрошены – наборы строк, выходные параметры и коды возврата. Это поведение особенно заметно при вызове процедур из приложений, где лишние сообщения могут замедлять обработку или вызывать ошибки парсинга результатов.
На практике SET NOCOUNT ON чаще всего размещают в начале хранимых процедур и триггеров. Это снижает объем передаваемых данных и упрощает взаимодействие с ORM, ADO.NET и другими слоями доступа к данным, которые ожидают строго определённую структуру ответа. При этом важно понимать, что команда не влияет на сами запросы и не меняет логику изменения данных.
Использование SET NOCOUNT ON требует осознанного подхода. В сценариях отладки или при ручном выполнении скриптов информация о количестве затронутых строк может быть полезной. Поэтому решение о включении команды должно учитывать тип нагрузки, способ вызова кода и требования клиента к результатам выполнения.
Как SET NOCOUNT ON влияет на сообщения о количестве затронутых строк

При стандартных настройках SQL Server после выполнения каждой инструкции изменения данных отправляет клиенту сообщение вида (N rows affected). Такие сообщения формируются для каждого INSERT, UPDATE, DELETE и даже для промежуточных операций внутри хранимых процедур. Они не входят в результирующий набор, но передаются как отдельные служебные пакеты.
Команда SET NOCOUNT ON отключает генерацию и отправку этих сообщений. Сервер продолжает подсчитывать количество затронутых строк внутри механизма выполнения, но клиент их не получает. В результате при вызове процедуры, содержащей, например, 20 операторов изменения данных, вместо 20 служебных сообщений передается только итоговый результат, который явно возвращен запросами или выходными параметрами.
Это поведение напрямую влияет на взаимодействие с клиентскими библиотеками. В ADO.NET, JDBC и ODBC каждое сообщение о количестве строк может обрабатываться как отдельное событие, что увеличивает число операций чтения из соединения. При включенном SET NOCOUNT ON драйверу не требуется разбирать эти сообщения, что упрощает обработку ответа.
Следует учитывать, что отключение сообщений лишает клиента возможности автоматически узнать число затронутых строк через стандартные механизмы. Если это значение требуется приложению, его следует возвращать явно – через SELECT @@ROWCOUNT, выходной параметр процедуры или возвращаемое значение. Такой подход делает контракт между SQL Server и клиентом предсказуемым и контролируемым.
Причины включения SET NOCOUNT ON в хранимых процедурах
Хранимые процедуры часто содержат цепочки операций изменения данных, временные таблицы и служебные запросы. При стандартных настройках каждый такой оператор порождает сообщение о количестве затронутых строк. В процедурах с десятками шагов это приводит к потоку служебных сообщений, которые не несут полезной нагрузки для вызывающего кода.
Включение SET NOCOUNT ON позволяет сократить число передаваемых по соединению пакетов. Для приложений с частыми вызовами процедур это снижает нагрузку на сетевой канал и уменьшает время обработки ответа на стороне клиента, особенно при высокой конкуренции соединений.
Еще одна причина связана с корректной работой клиентских библиотек и ORM. Некоторые фреймворки ожидают строго определённую последовательность результирующих наборов. Сообщения о количестве строк могут восприниматься как дополнительные результаты, что приводит к ошибкам чтения данных или необходимости писать обходной код.
Практика включения SET NOCOUNT ON упрощает контракт процедуры: клиент получает только те данные, которые явно возвращены через SELECT, выходные параметры или код возврата. Если приложению требуется число изменённых строк, его удобнее вернуть отдельным запросом или параметром, чем полагаться на неявные служебные сообщения.
Поэтому SET NOCOUNT ON обычно размещают в начале тела процедуры и считают частью стандартного шаблона серверного кода, особенно в системах с активным использованием хранимых процедур как API уровня базы данных.
Влияние SET NOCOUNT ON на сетевой трафик между SQL Server и клиентом

Каждое сообщение о количестве затронутых строк передается от SQL Server клиенту как отдельная служебная информация поверх TDS-протокола. Даже при отсутствии результирующих наборов данных сервер формирует и отправляет пакеты с текстом статуса после выполнения каждого оператора изменения данных.
При включенном SET NOCOUNT ON SQL Server прекращает отправку этих сообщений. Это напрямую отражается на объеме сетевого трафика, особенно в следующих сценариях:
- хранимые процедуры с большим числом INSERT, UPDATE и DELETE;
- циклы и курсоры, выполняющие операции построчно;
- высокочастотные вызовы процедур из приложений;
- триггеры, срабатывающие при массовых изменениях данных.
Например, процедура из 30 операторов изменения данных без SET NOCOUNT ON сформирует 30 служебных сообщений. При сотнях вызовов в секунду это приводит к тысячам лишних пакетов, которые проходят через сетевой стек, обрабатываются драйвером и увеличивают задержку ответа.
Сокращение служебного трафика особенно заметно при удалённом подключении к серверу баз данных или при использовании SQL Server в контейнерах и облачных средах, где задержки и пропускная способность сети играют значимую роль. В таких условиях лишние сообщения становятся измеримым фактором нагрузки.
Практическая рекомендация заключается в следующем:
- включать SET NOCOUNT ON во всех процедурах и триггерах, вызываемых из приложений;
- оставлять его отключённым только в скриптах, где сообщения о количестве строк используются вручную;
- возвращать необходимые числовые показатели явно, а не через служебные сообщения.
Такой подход позволяет контролировать структуру ответа SQL Server и уменьшать объем передаваемых данных без изменения логики запросов.
Использование SET NOCOUNT ON при работе с триггерами

Триггеры в SQL Server выполняются неявно в рамках операций INSERT, UPDATE и DELETE. Любой оператор изменения данных внутри триггера по умолчанию формирует сообщение о количестве затронутых строк, которое добавляется к ответу основной команды.
При отсутствии SET NOCOUNT ON клиентское приложение может получить дополнительные служебные сообщения, не ожидая их. Это особенно критично для кода, который анализирует количество затронутых строк после выполнения DML-операции и предполагает, что оно относится только к исходному запросу.
Включение SET NOCOUNT ON в теле триггера решает несколько практических задач:
- предотвращает искажение значения rows affected, возвращаемого клиенту;
- исключает передачу лишних сообщений при массовых изменениях данных;
- снижает нагрузку на драйверы, обрабатывающие ответы SQL Server;
- делает поведение DML-операций предсказуемым для вызывающего кода.
Особое внимание стоит уделять триггерам, которые:
- выполняют дополнительные UPDATE или INSERT в другие таблицы;
- используют временные таблицы или табличные переменные;
- срабатывают при пакетных операциях с большим числом строк.
Практика размещения SET NOCOUNT ON первой строкой внутри триггера считается стандартом. Это гарантирует, что ни одна внутренняя операция не повлияет на сообщения, возвращаемые основным запросом, и упрощает диагностику проблем на уровне приложения.
Если триггеру необходимо передать информацию о количестве обработанных строк, её следует возвращать через логирование, служебные таблицы или отдельные запросы, а не через стандартные сообщения SQL Server.
Поведение SET NOCOUNT ON при вложенных процедурах и батчах

В SQL Server команда SET NOCOUNT ON действует на уровне текущей сессии и сохраняется внутри хранимой процедуры или батча до явного изменения на SET NOCOUNT OFF. При вызове вложенной процедуры, если в ней не указано явное включение или отключение NOCOUNT, будет применяться текущее состояние, установленное внешней процедурой или батчем.
Например, если внешняя процедура содержит SET NOCOUNT ON, а вызываемая внутренняя процедура не меняет эту настройку, сообщения о количестве затронутых строк внутри внутренней процедуры не отправляются клиенту. Это позволяет контролировать поток служебных сообщений на всех уровнях вложенности без необходимости модифицировать каждый отдельный запрос.
Особенности поведения в батчах:
- Внутри одного батча SET NOCOUNT ON влияет на все последующие операторы изменения данных.
- Если батч содержит несколько процедур и скриптов, включение NOCOUNT в начале батча подавляет сообщения для всех операторов, пока не встретится SET NOCOUNT OFF.
- При использовании GO разделители создают новый батч, поэтому настройки NOCOUNT не сохраняются между батчами автоматически.
Рекомендации по применению в вложенных процедурах и батчах:
- Включать SET NOCOUNT ON в начале каждой процедуры, если требуется подавление сообщений.
- Не полагаться на состояние внешнего вызова для внутренних процедур в критичных сценариях передачи данных.
- Явно отключать NOCOUNT только в тех местах, где необходимо вернуть количество затронутых строк клиенту.
Такой подход обеспечивает предсказуемое поведение как при последовательном выполнении операций, так и при сложных вложенных вызовах процедур и батчей.
Отличия результата выполнения запросов с SET NOCOUNT ON и OFF

При SET NOCOUNT OFF после каждого оператора INSERT, UPDATE, DELETE SQL Server отправляет сообщение вида (N rows affected). Эти сообщения передаются клиенту отдельно от результирующих наборов данных и могут быть обработаны драйвером или приложением как дополнительный результат.
При SET NOCOUNT ON сообщения о количестве затронутых строк не отправляются. Клиент получает только те данные, которые явно возвращены запросами или выходными параметрами. Результат выполнения логически не изменяется, изменяются только служебные уведомления.
Конкретные отличия в поведении:
- С SET NOCOUNT OFF драйверы ADO.NET и ODBC могут создавать дополнительные события RowsAffected после каждого DML-оператора.
- С SET NOCOUNT ON количество затронутых строк необходимо получать вручную через SELECT @@ROWCOUNT или выходные параметры, если оно нужно приложению.
- При пакетных операциях с множеством операторов включение NOCOUNT снижает количество служебных сообщений, ускоряя обработку ответа клиентом.
- Отладка и логирование напрямую зависят от выбранного режима: OFF удобно для ручного анализа количества изменённых строк, ON – для оптимизированной передачи данных.
Рекомендация: использовать SET NOCOUNT ON в процедурах и триггерах, где клиенту важны только возвращаемые данные, а сообщения о количестве строк не нужны, и оставлять OFF только для сценариев анализа изменений в ходе отладки или тестирования.
Когда SET NOCOUNT ON мешает отладке и анализу выполнения
Использование SET NOCOUNT ON подавляет сообщения о количестве затронутых строк, что влияет на традиционные методы отладки. Информация о RowsAffected больше не доступна напрямую в клиентских инструментах, таких как SQL Server Management Studio, Profiler или ADO.NET события.
Проблемы возникают в следующих случаях:
- необходимо проверить точное число обновленных или удаленных строк после выполнения DML-операций;
- логирование промежуточных шагов процедуры для аудита или диагностики;
- анализ производительности, где количество обработанных строк используется для выявления узких мест;
- отладка вложенных процедур, когда требуется пошаговый контроль выполнения каждого оператора.
В таких сценариях отключение NOCOUNT (SET NOCOUNT OFF) позволяет:
- наблюдать за сообщениями о количестве затронутых строк в SSMS Messages или Profiler;
- автоматически получать RowsAffected в клиентских приложениях для проверки корректности операций;
- упростить диагностику ошибок, связанных с непредвиденными изменениями данных.
Рекомендация: включать SET NOCOUNT ON для продуктивного кода и оптимизации передачи данных, но временно отключать его в средах тестирования или при отладке, чтобы сохранить доступ к количеству затронутых строк и облегчить анализ выполнения процедур.
Рекомендации по включению SET NOCOUNT ON в существующем коде

При добавлении SET NOCOUNT ON в существующие хранимые процедуры и триггеры важно учитывать влияние на возвращаемые данные и клиентские приложения. Основные шаги включают аудит кода, тестирование и постепенное внедрение изменений.
Следующие рекомендации помогают безопасно внедрить NOCOUNT:
| Шаг | Описание |
|---|---|
| Аудит кода | Определите процедуры и триггеры, которые возвращают сообщения о количестве строк и влияют на клиентские приложения или отчёты. |
| Тестирование | В отдельной среде включите SET NOCOUNT ON и проверьте корректность работы клиентских запросов, ORM и обработку выходных параметров. |
| Пошаговое внедрение | Сначала включайте NOCOUNT в менее критичных процедурах, постепенно охватывая остальные, чтобы минимизировать риск ошибок. |
| Возврат необходимой информации | Если приложению требуется количество изменённых строк, добавляйте явный SELECT @@ROWCOUNT или выходной параметр вместо полагания на служебные сообщения. |
| Документирование изменений | Фиксируйте, где включен NOCOUNT, чтобы последующие разработчики понимали, что сообщения о количестве строк подавлены. |
Такой подход обеспечивает контроль над поведением процедур, снижает сетевой трафик и исключает непредвиденные ошибки в клиентских приложениях при сохранении предсказуемого взаимодействия с базой данных.
Вопрос-ответ:
Что именно делает команда SET NOCOUNT ON в SQL Server?
Команда SET NOCOUNT ON отключает отправку клиенту сообщений о количестве затронутых строк после выполнения операторов INSERT, UPDATE и DELETE. Сервер продолжает выполнять все операции и подсчитывать строки, но информация о количестве изменённых записей не передаётся. Это уменьшает количество служебных сообщений, что особенно заметно при вызове хранимых процедур с большим числом операторов.
Почему рекомендуется включать SET NOCOUNT ON в триггерах?
Триггеры выполняются автоматически при изменении данных и часто содержат дополнительные DML-операторы. Если NOCOUNT отключён, каждый оператор внутри триггера отправляет сообщение о количестве строк, что может исказить значение rows affected для основного запроса. Включение SET NOCOUNT ON предотвращает лишние сообщения и делает поведение DML-операций предсказуемым для клиента и драйвера.
Влияет ли SET NOCOUNT ON на результат выборки данных в SELECT?
Нет, SET NOCOUNT ON не изменяет результаты запросов SELECT. Все выборки, возвращаемые таблицы, представления или выходные параметры, остаются доступными клиенту. Команда лишь подавляет служебные сообщения о количестве строк, которые сервер обычно отправляет после выполнения операторов изменения данных, но не трогает сами наборы данных.
Как использовать SET NOCOUNT ON при вложенных хранимых процедурах?
Если внешняя процедура включает SET NOCOUNT ON, вложенные процедуры унаследуют это состояние, если внутри них не встречается явная команда изменения. Рекомендуется ставить NOCOUNT в начале каждой процедуры, чтобы гарантировать подавление лишних сообщений независимо от вызова извне. Если требуется вернуть количество затронутых строк, лучше использовать SELECT @@ROWCOUNT или выходной параметр, а не полагаться на сообщения SQL Server.
Может ли включение SET NOCOUNT ON вызвать проблемы при отладке?
Да, отключение сообщений о количестве строк делает недоступными стандартные значения RowsAffected в инструментах отладки и профилирования. Это усложняет контроль изменений в тестовых процедурах и при пошаговом анализе операций. Чтобы сохранять информацию для анализа, в средах тестирования рекомендуется временно использовать SET NOCOUNT OFF, а в продуктивных процедурах включать ON для уменьшения служебного трафика.
Как SET NOCOUNT ON влияет на производительность при массовых операциях?
Команда SET NOCOUNT ON отключает отправку сообщений о количестве затронутых строк, что уменьшает объем служебного трафика между сервером и клиентом. При массовых вставках, обновлениях или удалениях это сокращает количество пакетов, обрабатываемых драйвером, и снижает задержки. Реальный эффект заметен в процедурах с десятками или сотнями операторов, где каждое сообщение о количестве строк создаёт лишнюю нагрузку на сетевое соединение и клиентскую библиотеку.
Когда не стоит использовать SET NOCOUNT ON в существующих процедурах?
Не рекомендуется включать SET NOCOUNT ON, если клиентским приложениям или инструментам отладки необходимо автоматически получать количество затронутых строк через стандартные механизмы RowsAffected. Это актуально при пошаговой отладке процедур, анализе ошибок или логировании изменений. В таких случаях отключение NOCOUNT позволяет видеть точное число обновлённых или удалённых записей без дополнительного кода для явного подсчета.
