Что такое null значение
SQL Значение NULL
Что такое значение NULL?
Если поле в таблице является необязательным, то можно вставить новую запись или обновить запись без добавления значения в это поле. Затем поле будет сохранено с значением NULL.
Как проверить наличие NULL значений?
Вместо этого нам придется использовать оператор IS NULL и IS NOT NULL.
Синтаксис IS NULL
Синтаксис IS NOT NULL
Демо база данных
Ниже приведен выбор из таблицы «Customers» в образце базы данных Northwind:
CustomerID | CustomerName | ContactName | Address | City | PostalCode | Country |
---|---|---|---|---|---|---|
1 |
Оператор IS NULL
Оператор IS NULL используется для проверки пустых значений (NULL).
В следующем SQL файле перечислены все клиенты с значением NULL в поле «Address»:
Пример
Совет: Всегда используйте значение NULL для поиска значений NULL.
Оператор IS NOT NULL
Оператор IS NOT NULL используется для проверки непустых значений (NOT NULL).
В следующем SQL файле перечислены все клиенты со значением в поле «Address»:
NULL (SQL)
NULL в Системах управления базами данных (СУБД) — специальное значение (псевдозначение), которое может быть записано в поле таблицы базы данных (БД). NULL соответствует понятию «пустое поле», то есть «поле, не содержащее никакого значения». Введено для того, чтобы различать в полях БД пустые (визуально не отображаемые) значения (например, строку нулевой длины) и отсутствующие значения (когда в поле не записано вообще никакого значения, даже пустого).
NULL означает отсутствие, неизвестность информации. Значение NULL не является значением в полном смысле слова: по определению оно означает отсутствие значения и не принадлежит ни одному типу данных. Поэтому NULL не равно ни логическому значению FALSE, ни пустой строке, ни нулю. При сравнении NULL с любым значением будет получен результат NULL, а не FALSE и не 0. Более того, NULL не равно NULL!
Содержание
Необходимость NULL в реляционных БД
Использование NULL в БД
В БД, поддерживающих понятие NULL, для поля таблицы при описании определяется, может ли оно быть пустым. Если да, то в это поле можно не записывать никакого значения, и это поле будет иметь значение NULL. Также можно и явно записать в такое поле значение NULL.
Как правило, СУБД не разрешает значение NULL для полей, являющихся частью первичного ключа таблицы. В полях внешних ключей, напротив, NULL допускается. Наличие NULL в поле внешнего ключа может трактоваться как признак отсутствия связанной записи, и для такого внешнего ключа не требуется исполнение правил ссылочной целостности, обязательных для любого другого значения внешнего ключа.
Операции с NULL
Поскольку NULL не является, в общем смысле, значением, использование его в арифметических, строковых, логических и других операциях, строго говоря, некорректно. Тем не менее, большинство СУБД поддерживают такие операции, но вводят для них специальные правила:
Кроме того, могут существовать специальные системные функции для удобного преобразования NULL к определённым значениям, например, в Oracle имеется системная функция NVL, которая возвращает значение своего параметра, если он не NULL, или значение по умолчанию, если операнд — NULL. В стандарте SQL-92 определены две функции: NULLIF и COALESCE, поэтому их использование является более предпочтительным (если конкретная СУБД их реализует).
Null, великий и ужасный
Именно так и никак иначе: null в C# — однозначно ошибочное решение, бездумно скопированное из более ранних языков.
Этот ящик Пандоры был открыт еще при создании языка ALGOL W великим Хоаром, который позднее назвал собственную идею ошибкой на миллиард долларов.
Лучшая историческая альтернатива
Разумеется, она была, причем очевидная по современным меркам
Самое трагичное, что все это не было откровением и даже новинкой уже к моменту проектирования первой версии языка. Увы, тогда матерых функциональщиков в команде Хейлсберга не было.
Лекарства для текущей реальности
Хотя прогноз очень серьезный, летального исхода можно избежать за счет применения различных практик и инструментов. Способы и их особенности пронумерованы для удобства ссылок.
Явные проверки на null в операторе if. Очень прямолинейный способ с массой серьезных недостатков.
Атрибут NotNull. Немного упрощает использование явных проверок
Паттерн проектирования Null object. Очень хороший способ, но с ограниченной сферой применения.
Конвенция о возврате живых объектов по умолчанию. Очень просто и эффективно.
Любой метод или свойство, для которых явно не заявлена возможность возвращать null, должны всегда предоставлять полноценный объект. Для поддержания достаточно выработки хорошей привычки, например, посредством ревью кода.
Конвенция о стандартных способах явно указать что свойство или метод может вернуть null: например, префикс Try или суффикс OrDefault в имени метода. Органичное дополнение к возврату полноценных объектов по умолчанию. Достоинства и недостатки те же.
Атрибут CanBeNull. Добрый антипод-близнец атрибута NotNull.
Операторы C# (тернарный, Элвиса, coalesce)
Тип Optional. Позволяет явно поддержать отсутствие объекта.
Монада Maybe. LINQ для удобной обработки случаев как наличия, так и отсутствия объекта.
Пакет Fody/NullGuard. Автоматические проверки на null на стероидах.
Ссылочные типы без возможности присвоения null (если добавят в одну из будущих версий C#)
Итоги
Буду краток — все выводы в таблице:
Настоятельная рекомендация | Антипаттерн | На ваш вкус и потребности |
---|---|---|
4, 5, 7, 11, 12 (когда и если будет реализовано) | 1, 2 | 3, 6, 8, 9, 10 |
На предвосхищение ООП через 20 лет не претендую, но дополнениям и критике буду очень рад.
Обновление
добавил примеры кода к утопической альтернативе.
Оригинал статьи этой статьи впервые был опубликован в блоге автора @KevinMarquette. Группа разработчиков PowerShell благодарит Кевина за то, что он поделился с нами этими материалами. Читайте его блог — PowerShellExplained.com.
Что означает NULL
Значение NULL можно считать неизвестным или пустым значением. Переменная имеет значение NULL, пока ей не присвоено значение или объект. Это важный момент, так как некоторые команды требуют значения и возвращают ошибку, если значением является NULL.
$null в PowerShell
$null — это автоматическая переменная в PowerShell, используемая для представления значения NULL. Ее можно назначать переменным и использовать в сравнениях, а также в качестве заполнителя для значения NULL в коллекции.
В строках
Это одна из причин, по которой я предпочитаю заключать переменные в скобки при их использовании в сообщениях журнала. Если значение находится в конце строки, это также помогает обнаружить границы значений переменных.
В числовом уравнении
Вместо коллекции
Вместо объекта
Метод в выражении со значением NULL
Взгляните на следующий пример и постарайтесь предсказать результаты:
PSScriptAnalyzer и VSCode
Поскольку VS Code также использует правила PSScriptAnalyser, в редакторе такие фрагменты кода выделяются и считаются проблемой.
Простая проверка if
Но это еще не все. На самом деле строка значит следующее:
Ниже приведен более полный пример этой инструкции.
Несколько дней назад я столкнулся с этой проблемой при рефакторинге кода. В нем присутствовала базовая проверка такого типа.
$null.Count
[PSCustomObject] Count
Выполнение этого примера в Windows PowerShell 5.1 и PowerShell 6.0 дает разные результаты.
Пустое значение NULL
Pipeline
foreach
Оператор foreach начал так работать с версии PowerShell 3.0. Если у вас предыдущая версия, такой режим работы в ней не поддерживается. Это одно из важных отличий, которое необходимо учитывать при обратном портировании кода для совместимости с версией 2.0.
Типы значений
Параметры функции
Общепринято использовать строго типизированные значения в параметрах функций. Обычно мы стараемся определять типы параметров, даже если не собираемся определять типы других переменных в скриптах. Возможно, вы сами строго типизировали переменные в функциях, даже не осознавая этого.
IsNotNullOrEmpty
Я часто так делаю, когда знаю, что тип значения должен быть строкой.
Сценарий без результатов
У меня выработалась привычка инициализировать все переменные перед их использованием. В других языках это обязательно. В начале функции или цикла foreach я определяю все используемые значения.
Вот сценарий, который я советую вам внимательно изучить. Это пример ошибки, которую я однажды выявлял.
Проблемы с областью действия
Если взять тот же пример Do-something и удалить из него цикл, то код будет таким:
Out-Null
Сводка
Заметка про NULL
Основные положения
Для удобства сделаем процедуру, печатающую состояние булевого параметра:
и включим опцию печати сообщений на консоль:
Привычные операторы сравнения пасуют перед NULLом:
Сравнение с NULLом
Соответственно, IS NOT NULL действует наоборот: вернёт истину, если значение операнда отлично от NULLа и ложь, если он является NULLом:
DECODE идёт против системы:
Пример с составными индексами находится в параграфе про индексы.
Логические операции и NULL
В большинстве случаев неизвестный результат обрабатывается как ЛОЖЬ :
Отрицание неизвестности даёт неизвестность:
Операторы IN и NOT IN
Для начала сделаем несколько предварительных действий. Для тестов создадим таблицу T с одним числовым столбцом A и четырьмя строками: 1, 2, 3 и NULL
Включим трассировку запроса (для этого надо обладать ролью PLUSTRACE ).
В листингах от трассировки оставлена только часть filter, чтобы показать, во что разворачиваются указанные в запросе условия.
Предварительные действия закончены, давайте теперь поработаем с операторами. Попробуем выбрать все записи, которые входят в набор (1, 2, NULL) :
Попробуем теперь с NOT IN :
Вообще ни одной записи! Давайте разберёмся, почему тройка не попала в результаты запроса. Посчитаем вручную фильтр, который применила СУБД, для случая A=3 :
Из-за особенностей трёхзначной логики NOT IN вообще не дружит с NULLами: как только NULL попал в условия отбора, данных не ждите.
NULL и пустая строка
Здесь Oracle отходит от стандарта ANSI SQL и провозглашает эквивалентность NULLа и пустой строки. Это, пожалуй, одна из наиболее спорных фич, которая время от времени рождает многостраничные обсуждения с переходом на личности, поливанием друг друга фекалиями и прочими непременными атрибутами жёстких споров. Судя по документации, Oracle и сам бы не прочь изменить эту ситуацию (там сказано, что хоть сейчас пустая строка и обрабатывается как NULL, в будущих релизах это может измениться), но на сегодняшний день под эту СУБД написано такое колоссальное количество кода, что взять и поменять поведение системы вряд ли реально. Тем более, говорить об этом они начали как минимум с седьмой версии СУБД (1992-1996 годы), а сейчас уже двенадцатая на подходе.
NULL и пустая строка эквивалентны:
непременный атрибут жёсткого спора:
Длина пустой строки не определена:
Сравнение с пустой строкой невозможно:
Критики подхода, предлагаемого Ораклом, говорят о том, что пустая строка не обязательно обозначает неизвестность. Например, менеджер по продажам заполняет карточку клиента. Он может указать его контактный телефон (555-123456), может указать, что он неизвестен (NULL), а может и указать, что контактный телефон отсутствует (пустая строка). С оракловым способом хранения пустых строк реализовать последний вариант будет проблемно. С точки зрения семантики довод правильный, но у меня на него всегда возникает вопрос, полного ответа на который я так и не получил: как менеджер введёт в поле «телефон» пустую строку и как он в дальнейшем отличит его от NULLа? Варианты, конечно, есть, но всё-таки…
Вообще-то, если говорить про PL/SQL, то где-то глубоко внутри его движка пустая строка и NULL различаются. Один из способов увидеть это связан с тем, что ассоциативные коллекции позволяют сохранить элемент с индексом » (пустая строка), но не позволяют сохранить элемент с индексом NULL:
Использовать такие финты ушами на практике не стоит. Во избежание проблем лучше усвоить правило из доки: пустая строка и NULL в оракле неразличимы.
Математика NULLа
Этот маленький абзац писался пятничным вечером под пиво, на фоне пятничного РЕН-ТВшного фильма. Переписывать его лень, уж извините.
Очевидно, что мы ничем не сможем помочь Коле: неизвестное количество любовников Маши до замужества сводит все расчёты к одному значению — неизвестно. Oracle, хоть и назвался оракулом, в этом вопросе уходит не дальше, чем участники битвы экстрасенсов: он даёт очевидные ответы только на очевидные вопросы. Хотя, надо признать, что Oracle гораздо честнее: в случае с Колей он не будет заниматься психоанализом и сразу скажет: «я не знаю»:
С конкатенацией дела обстоят по другому: вы можете добавить NULL к строке и это её не изменит. Такая вот политика двойных стандартов.
NULL и агрегатные функции
Таблица с данными. Используется ниже много раз:
Пустые значения игнорируются агрегатами:
Набор данных только из NULLов:
Пустой набор данных:
NULL в OLAP
Удобная фишка sqlplus: при выводе данных заменяет NULL на указанную строку:
Проверяем дуализм NULLа в многомерном кубе: