SQL18 января 2026 г.1.79K

Ловушка NULL и NOT IN в SQL: почему пропадают строки

Коротко

В SQL NULL означает «неизвестно», а не «пусто». Из-за этого строки с NULL молча выпадают из результата при использовании NOT IN — и это одна из самых распространённых скрытых ошибок в запросах.

Одна из самых коварных ловушек в SQL связана с оператором NOT IN и значением NULL. На первый взгляд поведение кажется очевидным, но на практике строки с NULL тихо исчезают из результата — без единой ошибки и без предупреждения.

NULL — это не «пусто», это «неизвестно»

Ключ к пониманию проблемы — семантика NULL в SQL. NULL не равен пустой строке, нулю или какому-либо другому значению. NULL означает «значение неизвестно». Из этого вытекает трёхзначная логика SQL: результат логического выражения может быть не только TRUE или FALSE, но и UNKNOWN.

Что происходит при сравнении с NULL

Рассмотрим, как SQL вычисляет выражение NOT IN для разных значений поля city:

  • 'Москва' NOT IN ('Москва') → FALSE — значение найдено в списке, условие не выполняется
  • 'Питер' NOT IN ('Москва') → TRUE — значение не найдено, условие выполняется
  • NULL NOT IN ('Москва') → UNKNOWN — сравнение с неизвестным значением даёт неизвестный результат

В результирующую выборку попадают только строки, для которых условие WHERE вернуло TRUE. Строки с результатом FALSE и UNKNOWN одинаково отсекаются. Именно поэтому строки, где city IS NULL, молча исчезают из результата.

Как сохранить строки с NULL в выборке

Если нужно, чтобы строки с NULL также попадали в результат, необходимо явно обработать этот случай в условии WHERE:

  • Добавьте OR city IS NULL к условию фильтрации
  • Например: WHERE city NOT IN ('Москва') OR city IS NULL
  • Альтернативно — используйте NOT EXISTS с подзапросом: он корректно обрабатывает NULL без дополнительных условий

Что сделать на практике

  • Перед использованием NOT IN проверьте, может ли соответствующий столбец содержать NULL.
  • Если NULL допустим — всегда добавляйте явную проверку OR column IS NULL.
  • При работе с подзапросами в NOT IN убедитесь, что подзапрос не возвращает NULL — иначе вся выборка может оказаться пустой.
  • Рассмотрите замену NOT IN на NOT EXISTS: последний более предсказуем при наличии NULL.

Вывод

Трёхзначная логика SQL (TRUE / FALSE / UNKNOWN) — не баг, а архитектурная особенность стандарта. Понимание того, как NULL влияет на результаты фильтрации, позволяет избежать трудноуловимых ошибок в аналитических запросах и дашбордах, которые строятся на их основе.

Частые вопросы

Почему NOT IN не возвращает строки с NULL?+

Потому что сравнение любого значения с NULL даёт результат UNKNOWN, а не TRUE. В WHERE-условии проходят только строки с результатом TRUE, поэтому строки с NULL молча отсекаются.

Как включить NULL в результат при использовании NOT IN?+

Добавьте явное условие: WHERE column NOT IN (...) OR column IS NULL. Это гарантирует, что строки с NULL не будут потеряны.

Чем NOT EXISTS лучше NOT IN при наличии NULL?+

NOT EXISTS проверяет факт существования строки в подзапросе и корректно обрабатывает NULL без дополнительных условий. NOT IN с подзапросом, возвращающим хотя бы один NULL, вернёт пустой результат.

Что такое трёхзначная логика в SQL?+

Это логическая система, в которой булево выражение может принимать три значения: TRUE, FALSE или UNKNOWN. UNKNOWN возникает всякий раз, когда в сравнении участвует NULL.

329👍7
Читать оригинал в Telegram
Там можно оставить реакцию и написать комментарий
✈️ Открыть
🥰
Валерия Смирнова
Senior BI-аналитик в Авито · @mozzalerra
Сотрудничество →