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

Ловушка NULL и NOT IN в SQL: как не потерять строки

Коротко

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

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

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

В SQL NULL не является пустой строкой или нулём. Это специальный маркер, который означает отсутствие известного значения. Из-за этого любое сравнение с NULL возвращает не TRUE и не FALSE, а третье логическое состояние — UNKNOWN.

Именно здесь кроется ловушка: в результирующий набор попадают только те строки, для которых условие WHERE вернуло TRUE. Строки с UNKNOWN — то есть строки, где значение равно NULL, — тихо отфильтровываются.

Как ведёт себя NOT IN при наличии NULL

Рассмотрим три сценария для условия city NOT IN ('Москва'):

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

Таким образом, если в колонке city есть строки со значением NULL, они будут потеряны — без ошибки и без предупреждения. Это классическая скрытая ошибка в аналитических запросах.

Как правильно обработать NULL в условии фильтрации

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

  • WHERE city NOT IN ('Москва') OR city IS NULL

Конструкция IS NULL явно возвращает TRUE для строк с неизвестным значением, поэтому они включаются в результат. Заметьте: проверять NULL через = NULL или != NULL бессмысленно — оба выражения вернут UNKNOWN.

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

  • При написании NOT IN всегда спрашивайте себя: могут ли в этой колонке быть NULL?
  • Если да — добавляйте OR <column> IS NULL к условию фильтрации.
  • Альтернатива — использовать NOT EXISTS или LEFT JOIN / IS NULL, которые ведут себя предсказуемо при наличии NULL.
  • При ревью SQL-запросов коллег обращайте внимание на NOT IN с колонками, допускающими NULL — это частый источник тихих багов в отчётах.

Вывод

NOT IN с NULL — одна из самых коварных ловушек SQL именно потому, что она не вызывает ошибки. Результат просто оказывается неполным, а найти причину без знания трёхзначной логики SQL бывает непросто. Зная правило «NULL = UNKNOWN», эту ошибку легко предотвратить.

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

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

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

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

Добавьте явную проверку: WHERE column NOT IN (...) OR column IS NULL. Конструкция IS NULL возвращает TRUE для NULL-значений и позволяет включить такие строки в результат.

Чем отличаются NOT IN и NOT EXISTS при работе с NULL?+

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

Можно ли сравнивать с NULL через = или !=?+

Нет. Выражения column = NULL и column != NULL всегда возвращают UNKNOWN, а не TRUE или FALSE. Для проверки на NULL используйте только IS NULL или IS NOT NULL.

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