Как изменится результат фильтрации, если значение столбца сравнить с NULL?
Сравнение с NULL не возвращает ни TRUE, ни FALSE: его результатом становится UNKNOWN. В фильтре WHERE сохраняются только строки, для которых условие истинно, поэтому сравнение с NULL не найдёт строки с отсутствующим значением. Для проверки NULL используют предикаты IS NULL или IS NOT NULL.
Классическая реляционная модель опирается на значения атрибутов и логические условия без специального маркера отсутствующего значения. В SQL понадобился способ представить неизвестное, неприменимое или ещё не заданное значение, поэтому был введён NULL.
Появление NULL потребовало расширить обычную двухзначную логику. В SQL результат логического выражения может быть TRUE, FALSE или UNKNOWN, что позволяет не выдавать неизвестное сравнение за доказанную истину.
Предположим, в таблице есть заказы, у части которых дата отправки ещё не известна. Если искать такие строки обычным сравнением с NULL, условие для каждой строки даст UNKNOWN, а не TRUE.
Это приводит к пустому результату или к неполному набору данных без очевидной ошибки. Похожая проблема возникает в сложных условиях с AND, OR и NOT: UNKNOWN распространяется по правилам трёхзначной логики и может изменить итог фильтрации.
Первый запрос не выбирает строки из-за результата UNKNOWN. Второй использует специальный предикат и корректно проверяет отсутствие значения.
NULL не является обычным значением, равным самому себе. Выражение сравнения столбца с NULL означает, что результат сравнения неизвестен: неизвестно, равно ли фактическое значение неизвестному значению.
В операторе WHERE проходят только строки с результатом TRUE. Строки с FALSE и UNKNOWN отбрасываются, поэтому условие с равенством NULL не выбирает даже строки, в которых столбец действительно содержит NULL.
Для проверки отсутствия значения применяют IS NULL, а для проверки наличия — IS NOT NULL. Это не обычные операции сравнения, а специальные предикаты, результат которых всегда TRUE или FALSE для каждой строки.
В трёхзначной логике UNKNOWN ведёт себя не как FALSE во всех контекстах. Например, TRUE OR UNKNOWN даёт TRUE, FALSE OR UNKNOWN даёт UNKNOWN, а TRUE AND UNKNOWN даёт UNKNOWN. Поэтому механическая замена NULL на обычное значение или бездумное добавление NOT может изменить смысл запроса.
Функция COALESCE позволяет подставить значение для дальнейших вычислений, но она не заменяет IS NULL во всех случаях. Подстановка может смешать отсутствующее значение с реальным значением по умолчанию и повлиять на группировку, сортировку или бизнес-логику.
Если столбец по смыслу обязан иметь значение, надёжнее выразить это ограничением NOT NULL. Тогда часть проблем устраняется на уровне схемы, а не исправляется в каждом запросе. Если отсутствие значения допустимо, запросы должны явно учитывать семантику NULL.
В отчёте требовалось найти клиентов, которые ещё не подтвердили электронную почту. В таблице подтверждённая дата хранилась в nullable-столбце, но разработчик применил сравнение столбца с NULL и получил пустой отчёт.
Рассматривались три варианта. Проверка через IS NULL точно выражала условие и не требовала изменения данных. COALESCE с искусственной датой выглядел короче, но мог смешать отсутствие подтверждения с настоящей датой и усложнить оптимизацию. Изменение схемы на NOT NULL было невозможно, поскольку неподтверждённые клиенты являлись допустимым состоянием.
Выбрали IS NULL, а для противоположного отчёта — IS NOT NULL. В результате запросы стали соответствовать бизнес-смыслу, а состояние отсутствующей даты не подменялось фиктивным значением.
Почему отрицание проверки NULL не равно проверке NOT NULL?
Выражение NOT с результатом UNKNOWN также даёт UNKNOWN. Поэтому отрицание сравнения с NULL не превращает его в TRUE для строк с NULL. Для проверки наличия значения нужен специальный предикат IS NOT NULL.
Как NULL влияет на условие с AND и OR?
В условии A AND B наличие UNKNOWN означает, что результат не станет TRUE, если другая часть не доказана как TRUE и UNKNOWN не может быть устранён. В условии A OR B TRUE достаточно для общего TRUE, но FALSE OR UNKNOWN остаётся UNKNOWN. На практике это означает, что добавление дополнительного фильтра может не только сузить выборку, но и исключить строки из-за неизвестного результата.
Чем отличается NULL от пустой строки или нулевого числа?
Пустая строка и ноль являются конкретными значениями, участвующими в обычных операциях сравнения. NULL означает отсутствие известного значения и подчиняется трёхзначной логике. Поэтому замена NULL на пустую строку или ноль меняет семантику данных и допустима только при явно определённом бизнес-смысле такого значения.