Разберите ситуацию: UPDATE выбрал строку условием, но присвоил ей уже имеющееся значение. Считается ли она затронутой?
На логическом уровне строка считается найденной условием UPDATE и участвует в операции, даже если новое значение равно старому. Однако число строк, возвращаемое клиенту как «затронуто», зависит от СУБД, драйвера и настроек: оно может означать число совпавших строк или только число фактически изменённых.
SQL описывает изменение набора строк, выбранного предикатом, а не последовательность ручных присваиваний каждой строке. Поэтому условие UPDATE отвечает на вопрос, какие строки входят в целевой набор, а присваивание — какое состояние они должны получить.
Различие между найденными и реально изменившимися строками стало важно для прикладных программ: им нужно понимать, существовала ли строка, была ли изменена запись и следует ли считать операцию успешной.
Если приложение трактует нулевое число затронутых строк как ошибку, оно может неверно обработать успешный UPDATE, который установил уже имевшееся значение. Обратная ошибка тоже возможна: программа примет число совпавших строк за число записей, в которых действительно изменились данные.
Это особенно существенно при реализации оптимистической блокировки, аудита, синхронизации и проверки существования записи. Одного общего предположения о смысле счётчика строк недостаточно.
Сначала СУБД применяет условие WHERE и формирует набор строк-кандидатов. Каждая такая строка является целью UPDATE. Затем для неё вычисляются новые значения и проверяются ограничения, триггеры и другие правила конкретной СУБД.
Если вычисленное значение совпадает с прежним, логический набор строк всё равно не меняется: строка была выбрана оператором. Но физическая запись диска может не переписываться, а индексные и журнальные операции могут быть оптимизированы. Это не меняет логического смысла условия UPDATE.
В этом примере строка с идентификатором 1 соответствует WHERE. Поэтому она является строкой, обработанной UPDATE, хотя итоговое значение state осталось прежним.
Точный результат счётчика нужно проверять по документации используемой СУБД и драйвера. Например, разные режимы клиента могут считать либо совпавшие с WHERE строки, либо только строки, в которых значение действительно изменилось.
Для надёжной бизнес-логики не следует без проверки переносить семантику row count между СУБД. Если важно отличить отсутствие строки от отсутствия изменения, обычно отдельно используют условие существования, возвращаемые значения через RETURNING или явную проверку прежнего значения — с учётом конкуренции и транзакционной изоляции.
Сервис обновляет статус заказа и считает операцию успешной только при ненулевом количестве затронутых строк. Повторный запрос для уже установленного статуса в одной СУБД сообщает одну строку, а в другой конфигурации клиент сообщает ноль. Сервис ошибочно считает заказ отсутствующим и повторяет обработку.
Вариант с трактовкой любого ненулевого row count как фактического изменения прост, но зависит от конкретной платформы. Вариант с безусловным повторным SELECT надёжнее для диагностики, но добавляет запрос и может дать несогласованный результат без корректной транзакции.
Практичное решение — явно определить требуемую семантику: «строка существует», «значение изменилось» или «операция выполнила попытку обновления». Для проверки результата изменения следует использовать поддерживаемый СУБД механизм возврата изменённых строк либо условие, включающее отличие нового значения от старого. Это устраняет неоднозначность и делает поведение сервиса переносимым.
Нет. Ноль может означать отсутствие совпадения с WHERE или то, что используемый клиент считает только фактически изменившиеся строки. Для доказательства отсутствия записи нужна согласованная проверка в той же транзакции или механизм возврата результата UPDATE.
Это зависит от типа триггера и СУБД. Триггер, срабатывающий на событие UPDATE, обычно ориентируется на факт выполнения операции над выбранной строкой, а не только на отличие значений. Поэтому нельзя автоматически считать, что одинаковое старое и новое значение исключает запуск триггера.
Обычное сравнение через знак равенства или неравенства может дать UNKNOWN при NULL. Для корректной проверки изменения нужно использовать средство сравнения, учитывающее NULL, доступное в конкретной СУБД, либо явно обработать варианты NULL. Иначе часть реальных изменений или неизменившихся строк будет классифицирована неверно.