Открыть сервис

NULL-значение

NULL-значение (от лат. nullus — никакой, ничтожный) — в информатике и системах управления базами данных (СУБД) специальное значение (маркер), указывающее на отсутствие данных, неприменимость атрибута или неизвестное значение. NULL не является числом, строкой или каким-либо другим типом данных; это состояние, которое означает, что значение ячейки не определено или не существует. Концепция NULL была введена Эдгаром Коддом, автором реляционной модели данных, в 1970 году как средство представления «неизвестных» или «отсутствующих» данных.

История и происхождение

Понятие NULL возникло в контексте реляционной теории баз данных. В 1970 году Эдгар Кодд в своей работе «A Relational Model of Data for Large Shared Data Banks» предложил использовать NULL для обозначения отсутствующих данных, чтобы отличать их от нуля или пустой строки. В 1979 году Кодд уточнил концепцию, выделив два типа NULL: «отсутствующее значение, которое не применимо» (например, рост человека, не имеющего ног) и «отсутствующее значение, которое неизвестно» (например, рост человека, который не был измерен). Однако на практике большинство СУБД реализуют только один тип NULL, не различая эти случаи.

В 1980-х годах NULL был включён в стандарт SQL (Structured Query Language), что сделало его обязательным элементом реляционных баз данных. Несмотря на критику со стороны некоторых математиков и программистов (в частности, из-за трёхзначной логики, которую он вводит), NULL остаётся фундаментальной частью современных СУБД, таких как MySQL, PostgreSQL, Oracle Database, Microsoft SQL Server и других.

Логика и трёхзначная логика

NULL вводит в SQL так называемую трёхзначную логику (three-valued logic, 3VL), где истинность логического выражения может принимать три значения: TRUE (истина), FALSE (ложь) и UNKNOWN (неизвестно). Это связано с тем, что сравнение с NULL (например, x = NULL) не даёт ни TRUE, ни FALSE, а возвращает UNKNOWN, поскольку NULL не является конкретным значением.

Правила трёхзначной логики:

  • NULL = NULL → UNKNOWN (даже два NULL не равны друг другу, так как оба неизвестны).
  • NULL <> NULL → UNKNOWN.
  • NULL > 5 → UNKNOWN.
  • NULL + 5 → NULL.
  • NULL AND TRUE → UNKNOWN.
  • NULL OR TRUE → TRUE (так как TRUE достаточно для истинности).
  • NULL AND FALSE → FALSE (так как FALSE достаточно для ложности).
  • NOT NULL → UNKNOWN.

Для проверки на NULL в SQL используются специальные операторы IS NULL и IS NOT NULL, а не обычное сравнение. Например, SELECT * FROM users WHERE name IS NULL вернёт строки, где поле name не заполнено.

Использование в базах данных

В реляционных базах данных NULL используется для обозначения отсутствия данных в ячейке таблицы. Это может быть связано с несколькими причинами:

  • Неизвестное значение: например, дата рождения сотрудника, которая не была записана.
  • Неприменимое значение: например, поле «отчество» для человека, у которого его нет.
  • Отсутствие данных: например, поле «зарплата» для временного работника, который ещё не получил расчёт.

Ограничения и поведение:

  • NULL не может быть использован в первичных ключах (PRIMARY KEY) — столбец, объявленный первичным ключом, должен содержать только уникальные и не-NULL значения.
  • В индексах NULL обычно игнорируется (в зависимости от СУБД), но может быть включён в составной индекс.
  • При агрегатных функциях (SUM, AVG, COUNT, MAX, MIN) NULL-значения игнорируются, за исключением COUNT(*), который считает все строки, включая те, где есть NULL.
  • При объединении таблиц (JOIN) NULL-значения не участвуют в равенстве, если не используются специальные операторы.

Проблемы и критика

Концепция NULL подвергается критике по нескольким причинам:

1. Трёхзначная логика

Трёхзначная логика усложняет написание корректных запросов. Например, условие WHERE x = 1 OR x <> 1 не вернёт строки, где x равно NULL, так как оба сравнения дают UNKNOWN. Это может приводить к неожиданным результатам, особенно для новичков.

2. Неоднозначность

NULL не различает «неизвестное» и «неприменимое» значение, что может быть проблемой в семантическом моделировании данных. Например, поле «дата смерти» для живого человека и для человека, чья дата смерти неизвестна, будет одинаково NULL, хотя это разные ситуации.

3. Производительность

Использование NULL может снижать производительность запросов, так как СУБД требует дополнительных проверок. Индексы на столбцах с NULL могут быть менее эффективными.

4. Альтернативные подходы

Некоторые системы (например, NoSQL-базы данных, такие как MongoDB) не используют NULL, а вместо этого просто не включают поле в документ, если оно отсутствует. В реляционных базах данных альтернативой является использование значений-заглушек (например, 0, пустая строка, -1), но это может искажать данные.

Особенности в различных СУБД

Разные СУБД по-разному обрабатывают NULL:

  • MySQL: NULL в индексах может быть включён, но не участвует в уникальных ограничениях (несколько NULL допускаются в уникальном индексе).
  • PostgreSQL: NULL обрабатывается строго по стандарту SQL, но есть расширения, такие как NULLS FIRST и NULLS LAST в сортировке.
  • Oracle Database: NULL в сортировке по умолчанию считается больше любого другого значения (при сортировке по возрастанию NULL идут последними).
  • Microsoft SQL Server: NULL в сортировке по умолчанию считается меньше любого другого значения (при сортировке по возрастанию NULL идут первыми).
  • SQLite: NULL обрабатывается как значение, которое меньше любого другого (при сортировке по возрастанию NULL идут первыми).

Использование в языках программирования

Понятие NULL также широко используется в языках программирования, хотя его реализация отличается от SQL:

  • C/C++: NULLмакрос, обычно определяемый как (void*)0 или 0, используется для указателей, не указывающих на объект.
  • Java: nullлитерал, обозначающий отсутствие ссылки на объект. Попытка вызова метода у null приводит к исключению NullPointerException.
  • Python: None — объект-синглтон, обозначающий отсутствие значения. Используется в функциях, возвращающих ничего, или как значение по умолчанию.
  • JavaScript: null — примитивное значение, обозначающее отсутствие объекта. Также есть undefined, которое обозначает неопределённое значение.
  • C#: null — ссылка, не указывающая на объект. В последних версиях языка введены nullable-типы (например, int?), которые могут принимать null.
  • Rust: Option<T> — перечисление, которое может быть Some(T) или None, что позволяет избежать null-указателей.

Интересные факты

  • В 1965 году Тони Хоар, создатель языка ALGOL W, назвал введение NULL в языках программирования своей «миллиардной ошибкой», имея в виду ущерб от ошибок, связанных с null-указателями.
  • В SQL есть функция COALESCE, которая возвращает первое не-NULL значение из списка аргументов. Например, COALESCE(NULL, NULL, 5, NULL) вернёт 5.
  • В некоторых СУБД (например, Oracle) пустая строка ('') считается NULL, что может вызывать путаницу.
  • NULL не участвует в арифметических операциях: любое выражение, содержащее NULL, возвращает NULL (например, 5 + NULL = NULL).

Источники

  • Эдгар Кодд, «A Relational Model of Data for Large Shared Data Banks», 1970.
  • Стандарт SQL:2016 (ISO/IEC 9075:2016).
  • Тони Хоар, «Null References: The Billion Dollar Mistake», 2009.
  • Документация MySQL, PostgreSQL, Oracle Database, Microsoft SQL Server.
  • Книга «SQL for Dummies», 8-е издание, Аллен Тейлор.

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →