0Pricing
SQL Interview Prep · Урок

IS NULL, IS NOT NULL и безопасное сравнение с NULL

Правильно проверяйте NULL и используйте безопасные для NULL операторы в разных диалектах.

«IS NULL, IS NOT NULL и безопасное сравнение с NULL» — бесплатный урок SQL Interview Prep на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения SQL Interview Prep, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс SQL Interview Prep содержит 4 уроков всего.

Правильная проверка на NULL

В предыдущем уроке было доказано, что для поиска NULL нельзя использовать =. Как же проверять их на самом деле? С помощью специальных условий IS NULL и IS NOT NULL.

Это единственный корректный и переносимый способ проверить наличие отсутствующих значений, и на собеседовании у Вас всегда забракуют col = NULL.

В этом уроке рассматриваются IS NULL, IS NOT NULL, семейство IS DISTINCT FROM и зависящие от диалекта операторы сравнения на равенство с безопасной обработкой NULL. Знание различий между СУБД — сильный признак высокого уровня.

IS NULL и IS NOT NULL

IS NULL возвращает TRUE, когда значение равно NULL, и FALSE в противном случае. Важно, что это условие никогда не возвращает UNKNOWN, поэтому его безопасно использовать непосредственно в WHERE.

IS NOT NULL — его точное логическое дополнение: TRUE для любого фактического значения и FALSE для NULL.

Эти условия — основные инструменты обработки NULL. Они входят в стандарт SQL и одинаково работают в MySQL, Postgres, SQL Server, Oracle и SQLite.

-- Find employees with no recorded bonus
SELECT name FROM employees WHERE bonus IS NULL;

-- Find employees that do have a bonus
SELECT name FROM employees WHERE bonus IS NOT NULL;

Почему col = NULL всегда неверно

Гарантированная ловушка на собеседовании: кандидат пишет WHERE bonus = NULL, ожидая найти бонусы, которых нет. Запрос возвращает ноль строк.

Вспомните трёхзначную логику: bonus = NULL даёт UNKNOWN для каждой строки, в том числе для строк со значением NULL, поскольку неизвестное значение ни с чем нельзя считать равным. WHERE сохраняет только TRUE, поэтому ничего не совпадает.

Некоторые базы данных в нестандартных режимах незаметно переписывают = NULL в IS NULL, но никогда не полагайтесь на это. Всегда явно записывайте IS NULL.

-- WRONG: returns zero rows, bonus = NULL is UNKNOWN for all
SELECT name FROM employees WHERE bonus = NULL;

-- RIGHT:
SELECT name FROM employees WHERE bonus IS NULL;

Подсчёт значений NULL и не-NULL

Распространённая задача аналитика — проверка качества данных: насколько заполнен столбец? Объедините IS NULL с COUNT, чтобы вывести количество отсутствующих значений.

Обратите внимание на различие: COUNT(*) считает каждую строку, а COUNT(bonus) — только бонусы, не равные NULL. Разница между ними равна количеству NULL; к этому факту мы вернёмся в уроке об агрегатах.

SELECT
  COUNT(*)                                AS total_rows,
  COUNT(bonus)                            AS with_bonus,
  COUNT(*) - COUNT(bonus)                 AS missing_bonus,
  SUM(CASE WHEN bonus IS NULL THEN 1 ELSE 0 END) AS missing_check
FROM employees;

Какую проблему решает безопасное для NULL сравнение на равенство

Предположим, Вы хотите сопоставить два столбца и считать совпадением случай, когда оба значения равны NULL. Обычное a = b не подходит: когда оба значения равны NULL, результатом становится UNKNOWN, поэтому пара исключается, хотя интуитивно значения кажутся «одинаковыми».

Это возникает при сравнении старой строки с новой для обнаружения изменений или при соединении по необязательным столбцам. Вам нужно сравнение, при котором NULL = NULL даёт TRUE, а NULL и значение дают FALSE. Именно это и обеспечивает безопасное для NULL сравнение на равенство.

-- Goal: change-detection where two NULLs count as equal
-- Plain equality fails when both sides are NULL:
--   NULL = NULL -> UNKNOWN (treated as not-equal)
SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note = n.note;  -- misses rows where both notes are NULL

IS DISTINCT FROM (стандартный SQL)

Стандартное ANSI-сравнение с безопасной обработкой NULL — это IS DISTINCT FROM и его обратная форма IS NOT DISTINCT FROM. Они поддерживаются в Postgres, SQL Server (начиная с версии 2022) и других СУБД.

  • a IS NOT DISTINCT FROM b означает «равно; NULL = NULL считается равенством».
  • a IS DISTINCT FROM b означает «отличается; NULL считается обычным значением».

Эти условия всегда возвращают TRUE или FALSE, но никогда не UNKNOWN, поэтому безопасны везде, где требуется условие.

-- TRUE when notes match, including both NULL
SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note IS NOT DISTINCT FROM n.note;

-- TRUE when notes differ (NULL vs value counts as different)
SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note IS DISTINCT FROM n.note;

Оператор <=> в MySQL

В MySQL есть компактный оператор сравнения с безопасной обработкой NULL, записываемый как <=> (оператор «космический корабль»).

a <=> b возвращает 1 (TRUE), если обе стороны равны или обе имеют значение NULL, и 0 (FALSE) в противном случае. Это эквивалент IS NOT DISTINCT FROM в MySQL.

Если на собеседовании Вас спрашивают именно о сравнении с безопасной обработкой NULL в MySQL, это будет идиоматичный ответ.

-- MySQL: 1 when both equal or both NULL
SELECT (NULL <=> NULL) AS both_null,   -- 1
       (NULL <=> 5)    AS null_vs_val, -- 0
       (5 <=> 5)       AS val_eq;      -- 1

SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note <=> n.note;

Шпаргалка по различиям между диалектами

Интервьюеры ценят кандидатов, которые знают границы переносимости. Вот таблица сравнений с защитой от NULL:

  • ANSI / Postgres / SQL Server 2022+: IS NOT DISTINCT FROM
  • MySQL / MariaDB: <=>
  • SQLite: IS и IS NOT работают как сравнение на равенство с защитой от NULL
  • Oracle: нативного оператора нет; его можно имитировать с помощью DECODE(a, b, 1, 0) = 1 или приёмов с COALESCE

Если вы не уверены, какая СУБД используется, примените показанную далее переносимую ручную форму.

-- SQLite NULL-safe equality
SELECT * FROM t WHERE a IS b;      -- TRUE when both NULL
SELECT * FROM t WHERE a IS NOT b;  -- complement

Переносимое ручное сравнение с защитой от NULL

Если нативный оператор недоступен, сравнение с защитой от NULL можно построить из базовых операций. Переносимый шаблон объединяет обычное сравнение на равенство с явным условием для случая, когда оба значения равны NULL.

Читайте это так: «они равны, OR оба отсутствуют». Это работает в любой СУБД, поэтому это отличный ответ, когда интервьюер не уточняет диалект.

SELECT *
FROM old_t o JOIN new_t n ON o.id = n.id
WHERE (o.note = n.note)
   OR (o.note IS NULL AND n.note IS NULL);

-- Alternative using COALESCE with a sentinel that
-- cannot occur in real data:
-- WHERE COALESCE(o.note, '##NULL##') = COALESCE(n.note, '##NULL##')

Более подробный пример: ключи JOIN с защитой от NULL

Типичная ловушка: соединение по ключу, допускающему NULL. Если region может быть равен NULL с обеих сторон, обычное соединение по равенству незаметно исключает такие пары, потому что NULL = NULL даёт UNKNOWN.

Если бизнес-правило гласит: «строки без региона всё равно должны сопоставляться с другими строками без региона», условие соединения нужно сделать безопасным для NULL. На собеседовании озвучьте это допущение, а затем выберите оператор, соответствующий СУБД.

-- Postgres / ANSI: match including both-NULL regions
SELECT a.id, b.id
FROM table_a a
JOIN table_b b
  ON a.region IS NOT DISTINCT FROM b.region;

-- MySQL equivalent: ON a.region <=> b.region

Основные тезисы для собеседования

Чтобы уверенно отвечать на любой вопрос о проверке NULL:

  • Всегда используйте IS NULL / IS NOT NULL; никогда не используйте = NULL.
  • Эти предикаты возвращают только TRUE или FALSE, поэтому безопасны в WHERE.
  • Для сопоставления «NULL равен NULL» используйте IS NOT DISTINCT FROM (ANSI) или <=> (MySQL).
  • Укажите, для какого диалекта пишется запрос; если вы не уверены, предложите переносимый вариант с условием OR.

Упоминание стандартного и поставляемого разработчиком оператора демонстрирует широту знаний, которую отмечают специалисты по первичному отбору.

Быстрая проверка

Выберите правильное сравнение с защитой от NULL.

Итоги

Теперь вы умеете правильно проверять NULL:

  • IS NULL / IS NOT NULL — единственные корректные переносимые проверки NULL; они никогда не возвращают UNKNOWN.
  • col = NULL всегда возвращает ноль строк; это классическая ловушка на собеседовании.
  • Сравнение с защитой от NULL считает два значения NULL равными: IS NOT DISTINCT FROM (ANSI/Postgres), <=> (MySQL), IS (SQLite).
  • Если подходящего оператора нет, используйте (a = b) OR (a IS NULL AND b IS NULL).

Далее: замена NULL значениями по умолчанию с помощью COALESCE, NULLIF и функций конкретных СУБД, таких как ISNULL.

Часто задаваемые вопросы

Урок «IS NULL, IS NOT NULL и безопасное сравнение с NULL» бесплатный?

Да — полный текст урока «IS NULL, IS NOT NULL и безопасное сравнение с NULL» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс SQL Interview Prep, подпишись на CoddyKit PRO. Курс SQL Interview Prep содержит 4 уроков всего.

Чему я научусь в уроке «IS NULL, IS NOT NULL и безопасное сравнение с NULL»?

Правильно проверяйте NULL и используйте безопасные для NULL операторы в разных диалектах. Ты практикуешь SQL Interview Prep с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать SQL Interview Prep?

Предыдущий опыт не требуется. SQL Interview Prep на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «IS NULL, IS NOT NULL и безопасное сравнение с NULL»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке SQL Interview Prep?

Да. Каждый урок SQL Interview Prep включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Трёхзначная логика и UNKNOWN
  2. IS NULL, IS NOT NULL и безопасное сравнение с NULL
  3. COALESCE, NULLIF и ISNULL
  4. NULL в агрегатах, объединениях и DISTINCT
← Назад к SQL Interview Prep