NULL в SQL: что это значит и чем отличается от пустой строки в MySQL

NULL в SQL означает, что значения нет или оно неизвестно. Пустая строка устроена иначе: это значение длиной ноль символов.

Показываем на запросах к MySQL 8.0, как искать NULL, чем он отличается от пустой строки и где ломает NOT IN, AVG и уникальные индексы.

Статью написал:
Ваня Буявец, продюсер, основатель Checkroi
Ваня Буявец
Основатель Checkroi, продюсер, эксперт в выборе онлайн-курсов
Все 2924 статьи автора Подписаться на Телеграм-канал
Одобрено экспертом:
Наташа Буявец, основатель Checkroi, эксперт по онлайн-курсам
Наташа Буявец
Основательница Checkroi, продюсер Youtube-каналов, эксперт по онлайн-курсам
Все 3578 экспертных мнений Подписаться на Телеграм-канал
Обложка: NULL в SQL: что это значит и чем отличается от пустой строки в MySQL

NULL в SQL означает, что значения в ячейке нет: его не знают или оно к этой строке не относится. Пустая строка '' устроена иначе. Это настоящее значение, в котором ноль символов.

Отсюда главное правило: NULL ищут через IS NULL, знак равенства тут не работает. Запрос WHERE phone = NULL не вернёт ни одной строки, даже если пустых телефонов в таблице сотни. Если вы только начинаете писать запросы, сначала загляните в обзор языка SQL и того, зачем его учить.

Все примеры ниже мы запускали на MySQL 8.0 с настройками по умолчанию. Вывод в блоках кода скопирован из консоли без правок.

CheckroiCheckroiПодборка курсов по SQL416 курсов • 40 школСравните цены, школы, программу и найдите выгодные предложения по обучениюСравнить→

Что значит NULL в базе данных

Рой разбирает таблицу с пустыми ячейками в базе данных

В стандарте SQL значение NULL читается как «неизвестно». Поэтому сравнение с ним возвращает третий логический результат, UNKNOWN: ни «да», ни «нет». Так логику описывает справка Microsoft о NULL и UNKNOWN в Transact-SQL. MySQL рассуждает так же, только в выводе показывает этот третий результат как NULL.

Сравните три похожих на вид значения:

Что в ячейке Что это значит Пример в анкете клиента Как найти
NULL значения нет или оно неизвестно телефон у клиента не спрашивали IS NULL
'' строка есть, но в ней ноль символов отчества нет, поле оставили пустым = ''
0 обычное число на бонусном счёте ноль баллов = 0

Для отчёта это разные факты. «Телефон не спрашивали» и «отчества нет» нельзя смешивать, и база хранит их по-разному.

NULL как тип данных

Отдельного типа под NULL в MySQL нет. Это значение, которое может лежать в столбце любого типа: INT, VARCHAR, DATE. Запрещает его только пометка NOT NULL в описании столбца, а без неё столбец по умолчанию принимает NULL.

Такие вопросы часто задают на первом техническом интервью, наравне с JOIN и группировкой. Чем ещё проверяют новичков, видно по разбору собеседования на аналитика данных.

Что значит null в программировании

Слово null есть почти в каждом языке. Везде оно значит «здесь ничего нет», но детали различаются:

  • JavaScript. null программист ставит сам, чтобы явно показать пустоту. undefined означает, что переменной ещё ничего не присвоили. Описание есть в глоссарии MDN. Сюрприз для новичков: typeof null возвращает "object", а null == undefined даёт true.
  • Python. Вместо null здесь объект None, и проверяют его оператором is: if value is None. Почему здесь нужен именно is, объясняет статья про операторы в Python.
  • Java и C#. null означает пустую ссылку: переменная никуда не указывает. Вызов метода через такую ссылку в Java падает с ошибкой NullPointerException.

Когда программа читает строку из базы, NULL превращается в null своего языка. В Python это прямо записано в стандарте драйверов баз данных PEP 249: NULL из SQL приходит как None. Пустая строка при этом так и остаётся пустой строкой.

Проверка if not value в Python пропускает и None, и ''. Это удобно, но разница между «не спрашивали» и «пусто» в этот момент теряется.

Если вы пишете фронтенд, тему null и undefined стоит закрыть сразу, она всплывает с первых задач. С чего начать JavaScript, мы разбирали в статье о том, зачем новичку учить JavaScript.

Канал основателя Checkroi Вани Буявца3 700 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединиться

Чем NULL отличается от пустой строки в MySQL

Начнём со сравнения. Знак = с NULL всегда даёт NULL, даже если сравнить NULL с самим собой:

SELECT NULL = NULL, NULL IS NULL, NULL <=> NULL, '' = '', '' IS NULL;

+-------------+--------------+---------------+---------+------------+
| NULL = NULL | NULL IS NULL | NULL <=> NULL | '' = '' | '' IS NULL |
+-------------+--------------+---------------+---------+------------+
|        NULL |            1 |             1 |       1 |          0 |
+-------------+--------------+---------------+---------+------------+

Оператор <=> в MySQL называется NULL-безопасным равенством: два NULL для него равны. Остальные различия видно на функциях и индексах.

Что проверяем NULL Пустая строка ''
LENGTH() NULL 0
CONCAT('Иван', …) NULL, пропадает весь результат «Иван»
COUNT(столбец) не считается считается
уникальный индекс повторов сколько угодно второе '' даёт ошибку
ORDER BY … ASC в самом начале сразу после NULL, перед любым текстом
GROUP BY все NULL в одной группе все '' в одной группе

Строку с уникальным индексом стоит запомнить отдельно. Мы создали таблицу contacts с уникальным полем email и записали туда по два одинаковых значения:

INSERT INTO contacts (email) VALUES (NULL), (NULL);   -- обе строки записаны
INSERT INTO contacts (email) VALUES (''), ('');
ERROR 1062 (23000): Duplicate entry '' for key 'contacts.uq_email'

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

Порядок сортировки и группировку MySQL описывает в разделе Working with NULL Values. Сайт документации dev.mysql.com из России сейчас открывается страницей с ошибкой, поэтому все правила выше мы проверили запросами. Русский перевод тех же правил есть в старом руководстве на mysql.ru.

Запросы для поиска пустых значений

Возьмём учебную таблицу users. У Бориса и Глеба телефон NULL, у Веры пустая строка:

SELECT id, name, phone FROM users ORDER BY phone, id;

+----+-------+--------------+
| id | name  | phone        |
+----+-------+--------------+
|  2 | Борис | NULL         |
|  4 | Глеб  | NULL         |
|  3 | Вера  |              |
|  1 | Анна  | +79001112233 |
+----+-------+--------------+

Четыре запроса закрывают почти все задачи. Если таких запросов в работе становится всё больше, загляните в подборку курсов по SQL.

-- только NULL: Борис и Глеб
SELECT id, name FROM users WHERE phone IS NULL;

-- только пустые строки: Вера
SELECT id, name FROM users WHERE phone = '';

-- и то и другое: Борис, Вера, Глеб
SELECT id, name FROM users WHERE phone IS NULL OR phone = '';

-- то же короче: NULLIF превращает '' в NULL
SELECT id, name FROM users WHERE NULLIF(phone, '') IS NULL;

Чтобы заменить NULL на понятный текст или ноль при выводе, есть три функции:

  • IFNULL(x, y) возвращает y, если x равен NULL. Работает в MySQL, принимает два аргумента.
  • COALESCE(x, y, z…) возвращает первый аргумент, который не NULL. Это стандарт SQL, он есть и в PostgreSQL, и в SQL Server.
  • NULLIF(a, b) возвращает NULL, если a и b равны. Удобна, чтобы пустую строку считать отсутствием значения.
SELECT name,
       COALESCE(NULLIF(phone, ''), 'нет телефона') AS phone,
       IFNULL(bonus, 0) AS bonus
FROM users;

+-------+--------------+-------+
| name  | phone        | bonus |
+-------+--------------+-------+
| Анна  | +79001112233 |   100 |
| Борис | нет телефона |     0 |
| Вера  | нет телефона |    50 |
| Глеб  | нет телефона |     0 |
+-------+--------------+-------+

Без NULLIF Вера осталась бы с пустым телефоном. COALESCE('', 'замена') и IFNULL('', 'замена') возвращают пустую строку: для них '' полноценное значение.

Запросы удобно гонять в DBeaver на копии базы. Как его подключить, описано в инструкции по подключению к базе в DBeaver. В PostgreSQL вместо <=> пишут IS NOT DISTINCT FROM, синтаксис есть в русской документации Postgres Pro.

Подводные камни в запросах

Рой с лупой находит ошибку в SQL-запросе

Ошибки с NULL не выдают сообщений. Запрос отрабатывает, просто в результате не хватает строк или цифра получается другая. Вот пять случаев, которые встречаются чаще всего.

«Не равно» теряет строки с NULL

Хотим всех, кто не из Москвы. У Веры город не указан, и она пропадает из результата:

SELECT id, name, city FROM users WHERE city <> 'Москва';

+----+-------+--------+
| id | name  | city   |
+----+-------+--------+
|  2 | Борис | Казань |
+----+-------+--------+

Решение: добавить OR city IS NULL или написать WHERE NOT (city <=> 'Москва'). Оба варианта вернут Бориса и Веру.

NOT IN с NULL в списке возвращает пустоту

В таблице orders два заказа: один от Анны, у второго user_id не заполнен. Ищем тех, кто ничего не заказывал:

SELECT name FROM users WHERE id NOT IN (SELECT user_id FROM orders);
Empty set

Ни одной строки, хотя Борис, Вера и Глеб заказов не делали. Для MySQL «id не равен NULL» означает «неизвестно», поэтому ни одна строка не проходит фильтр.

Решение: NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id) или условие WHERE user_id IS NOT NULL внутри подзапроса. Оба вернут троих.

Арифметика и склейка строк превращаются в NULL

  • bonus + 10 у Бориса и Глеба даёт NULL. Ожидаемых 10 баллов не будет.
  • CONCAT('Иван', NULL) возвращает NULL целиком. CONCAT_WS(' ', 'Иван', NULL, 'Петров') пропускает NULL и выдаёт «Иван Петров».

Решение: оборачивать столбцы в IFNULL до вычислений, а ФИО собирать через CONCAT_WS.

AVG делит не на то число

SELECT COUNT(*), COUNT(bonus), SUM(bonus), AVG(bonus), AVG(IFNULL(bonus, 0)) FROM users;

+----------+--------------+------------+------------+-----------------------+
| COUNT(*) | COUNT(bonus) | SUM(bonus) | AVG(bonus) | AVG(IFNULL(bonus, 0)) |
+----------+--------------+------------+------------+-----------------------+
|        4 |            2 |        150 |    75.0000 |               37.5000 |
+----------+--------------+------------+------------+-----------------------+

Агрегатные функции пропускают NULL. AVG(bonus) делит 150 только на двух клиентов с бонусами. Если NULL у вас значит «ноль баллов», правильный ответ 37,5, и получить его можно только через IFNULL.

LEFT JOIN превращается в обычный

Условие на правую таблицу в WHERE отсекает строки, где LEFT JOIN подставил NULL. Такие условия переносят в ON. Пример с заказами разобран в статье о задачах по SQL на собеседовании.

Пустая строка, NOT NULL и строгий режим

MySQL 8.0 по умолчанию работает в строгом режиме STRICT_TRANS_TABLES. В нём пустую строку нельзя записать в числовой столбец, а NULL нельзя записать в столбец с NOT NULL:

INSERT INTO t (amount, note) VALUES ('', 'тест');
ERROR 1366 (HY000): Incorrect integer value: '' for column 'amount' at row 1

INSERT INTO t (amount, note) VALUES (5, NULL);
ERROR 1048 (23000): Column 'note' cannot be null

Если строгий режим выключен, картина другая. Тогда '' в числовом столбце молча превращается в 0, и MySQL выдаёт только предупреждение. Мы проверили это, сбросив sql_mode в сессии: в таблицу записался ноль. Какие флаги за что отвечают, расписано в разделе Server SQL Modes (тот же сайт dev.mysql.com, из России открывается с ошибкой).

Ещё один нюанс касается пробелов. Строка из трёх пробелов равна пустой строке или нет, зависит от сопоставления (collation) столбца:

Сопоставление Результат ' ' = ''
utf8mb4_0900_ai_ci, по умолчанию в MySQL 8.0 0, пробелы считаются символами
utf8mb4_unicode_ci, встречается в базах, созданных до MySQL 8.0 1, пробелы в конце игнорируются

Если поле заполняют люди через форму, сравнивайте TRIM(поле) = ''. Так запрос одинаково сработает на любом сопоставлении.

Ваня БуявецКанал основателя Checkroi Вани БуявцаЗабирайте промпты и обучение по нейросетям в моём Телеграм-каналеБольше 3 700 человек уже применяют Claude Code, ChatGPT и другие нейросети в работе, учёбе, бизнесе и жизниПерейти в канал

Что хранить в пустом поле при проектировании таблицы

Схема таблицы базы данных на маркерной доске

Ориентиры такие:

Ситуация Что хранить Почему
значение неизвестно: телефон, дата увольнения, рейтинг NULL явная проверка IS NULL, честные COUNT и AVG
необязательное уникальное поле: почта, ИНН NULL уникальный индекс пропускает повторы NULL
внешний ключ без связи NULL пустую строку база будет искать в родительской таблице и не найдёт
числа и даты NULL в строгом режиме '' туда не запишется
текст, где «пусто» и «не спрашивали» для вас одно и то же '' и NOT NULL DEFAULT '' одна проверка = '' вместо двух

Главное, одна договорённость на столбец. Проблемы начинаются, когда в одном поле живут и NULL, и пустые строки: тогда каждый отчёт обязан проверять оба варианта, и рано или поздно кто-то забудет. Если так уже вышло, приведите поле к одному виду. Команда UPDATE users SET phone = NULL WHERE phone = '' в нашей таблице перевела телефон Веры в NULL, и IS NULL стал находить всех троих.

Отдельно об Oracle. Там пустая строка и NULL одно и то же: документация Oracle прямо пишет, что значение нулевой длины считается null, и советует не полагаться на это в будущем. При переносе базы из Oracle в MySQL или PostgreSQL проверки на IS NULL перестают ловить пустые строки, их надо пересмотреть.

В PostgreSQL с 15-й версии уникальный индекс можно объявить как UNIQUE NULLS NOT DISTINCT. Тогда второй NULL тоже даст ошибку дубликата, как пустая строка в MySQL. Подробности в разделе об ограничениях документации Postgres Pro.

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

Где освоить SQL системно

С NULL можно разобраться за вечер, а вот уверенно писать запросы с JOIN, группировками и подзапросами учатся неделями практики на живых данных. Если SQL нужен для работы аналитиком или разработчиком, удобнее пройти курс с задачами и проверкой.

Ниже курсы из нашего каталога, все программы собраны в разделе курсов по SQL. Как выстроить обучение по месяцам, расписано в плане как стать SQL-разработчиком, а чем занят аналитик на SQL, мы разбирали в статье о профессии SQL-аналитика.

КурсШколаСтоимость со скидкойВ рассрочкуДлитель­ностьОбзор курса от Checkroi
Нейросети для рабочих задач
Перейти на сайт курса
SkillboxSkillbox31 290 ₽ - 1 месяцОбзор курса
SQL-разработчик: тариф PRO
Перейти на сайт курса
Академия ЭдюсонЭдюсон89 900 ₽7491 ₽/мес.2 месяцаОбзор курса
SQL-разработчик: тариф Базовый
Перейти на сайт курса
Академия ЭдюсонЭдюсон79 900 ₽3329 ₽/мес.3 месяцаОбзор курса
SQL для анализа данных
Перейти на сайт курса
SkillboxSkillbox50 828 ₽6203 ₽/мес.2 месяцаОбзор курса
SQL с нуляSkyproSkypro134 640 ₽5500 ₽/мес.12 месяцевОбзор курса

Больше программ — в полном каталоге курсов по SQL

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

Что значит NULL простыми словами?

NULL означает, что значения в ячейке нет: его не знают или оно к этой строке не относится. Это отметка об отсутствии данных, а не число и не текст.

NULL и 0 это одно и то же?

Нет. Ноль это обычное число, с ним работают арифметика и сравнение. С NULL любая арифметика даёт NULL: NULL + 10 вернёт NULL, а не 10.

Почему запрос WHERE поле = NULL ничего не находит?

Сравнение с NULL через знак равенства возвращает «неизвестно», и строка не проходит фильтр. Для поиска нужен оператор IS NULL, а в MySQL ещё NULL-безопасное равенство <=>.

Как заменить NULL на 0 или текст в MySQL?

Через IFNULL(поле, 0) или стандартную COALESCE(поле, 'нет данных'). Если пустую строку тоже нужно считать отсутствием значения, добавьте NULLIF(поле, '') внутрь.

Что лучше хранить в пустом поле: NULL или пустую строку?

Для чисел, дат, внешних ключей и необязательных уникальных полей хранят NULL. Пустую строку с NOT NULL DEFAULT '' выбирают для текста, где «пусто» и «не спрашивали» означают одно и то же. Подробнее о запросах к базе в статье о языке SQL.

Читайте Checkroi первым в Google
Добавьте Checkroi в избранные источники — и наши разборы курсов и обзоры школ будут показываться выше в вашей выдаче Google.
Оставить комментарий
0 комментариев
Форма комментария

Оставьте комментарий

Напишите, что думаете. Нам важно ваше мнение!