Стандартное использование «Z» вместо NULL для представления отсутствующих данных? - PullRequest
76 голосов
/ 10 июля 2011

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

Другой подрядчик проекта твердо убежден в том, что «NULL для меня не существует; я никогда не использую NULL, и никто другой не должен, ни одна из сторон аргумента». Однако меня смущает то, что, поскольку команда подрядчика признает разницу между «отсутствующим / никогда не введенным» и «преднамеренно пустым или указанным пользователем как неизвестный», они используют один символ «Z» в своем коде и хранимых процедурах для обозначают «отсутствует / никогда не вводится» с тем же значением, что и NULL, в остальной части базы данных.

Хотя наш общий клиент попросил изменить это, и я поддержал этот запрос, команда называет это «стандартной практикой» среди администраторов баз данных, гораздо более продвинутых, чем я; они не хотят переходить на NULL, основываясь только на моем невежественном запросе. Итак, кто-нибудь может помочь мне преодолеть мое невежество? Есть ли среди экспертов по SQL какой-либо стандарт или небольшая группа людей, или даже один громкий голос, который выступает за использование Z вместо NULL?

Обновление

У меня есть ответ от подрядчика, чтобы добавить. Вот что он сказал, когда клиент попросил удалить специальные значения, чтобы разрешить NULL в столбцах без данных:

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

Значение NULL в строке [VARCHAR] никогда не требуется, поскольку пустая (нулевая длина) строка предоставляет точно такую ​​же информацию.

Значение NULL в целочисленном поле (например, значение идентификатора) может обрабатываться с использованием значения, которое никогда не встречается в данных (например, -1 для целочисленного поля IDENTITY).

Значение NULL в поле даты может легко вызвать осложнения в вычислениях даты. Например, в логике, которая вычисляет разницу между датами, например разницу в днях между [RecoveryDate] и [OnsetDate], логика будет взорвана, если одна или обе даты равны NULL - если для обеих дат не сделано явное допущение быть NULL. Это дополнительная работа и дополнительная обработка. Если для [RecoveryDate] и [OnsetDate] (например, «1/1/1900») используются даты «по умолчанию» или «местозаполнитель», математические вычисления могут показывать «необычные» значения - но логика дат не будет взорвана.

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

За 15 лет работы в качестве администратора базы данных я решил, что лучше всего избегать значений NULL, где это возможно.

Кажется, это подтверждает в основном негативную реакцию на этот вопрос. Вместо применения принятого подхода 6NF для проектирования NULL, используются специальные значения, чтобы «избегать NULL, где это возможно». Я оставил этот вопрос без предубеждений, и я рад, что узнал больше о дебатах «NULLs полезны / NULLs являются злом», но теперь мне вполне удобно называть подход «особыми ценностями» полной бессмыслицей.

пустая (нулевая длина) строка предоставляет точно такую ​​же информацию.

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

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

Да, но эти ошибки были сделаны тысячи раз тысячами разработчиков, и уроки и предостережения о том, как избежать этих ошибок, известны и задокументированы.Как уже упоминалось здесь: независимо от того, принимаете вы или отклоняете NULL, представление пропущенных значений является решенной проблемой .Нет необходимости изобретать новое решение только потому, что разработчики продолжают допускать легко преодолеваемые (и легко идентифицируемые) ошибки.


В качестве сноски: я был DBEи разработчик более 20 лет (что, безусловно, достаточно для меня, чтобы узнать разницу между инженером базы данных и администратором базы данных).На протяжении всей моей карьеры я всегда был в лагере «NULLs полезны», хотя я знал, что несколько очень умных людей не согласились.Я чрезвычайно скептически относился к подходу «особых ценностей», но не достаточно хорошо разбирался в учениях «Как избежать NULL правильного пути», чтобы занять твердую позицию.Я всегда люблю узнавать что-то новое, и у меня еще есть чему поучиться через 20 лет.Спасибо всем, кто помог сделать это обсуждение полезным.

Ответы [ 8 ]

104 голосов
/ 10 июля 2011

Уволить вашего подрядчика.

Ладно, серьезно, это не стандартная практика.Это можно увидеть просто потому, что все СУБД, с которыми я когда-либо работал, реализуют NULL, логику для NULL, учитывают NULL во внешних ключах, имеют различное поведение для NULL в COUNT и т. Д. И т. Д.

Я бы на самом делеутверждают, что использование «Z» или любого другого заполнителя хуже.Вам все еще требуется код для проверки на «Z».Но вам также нужно документировать, что «Z» не означает «Z», это означает что-то еще.И вы должны убедиться, что такая документация прочитана.И что произойдет, если «Z» когда-нибудь станет действительным фрагментом данных?(Например, поле для начального?)

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


РЕДАКТИРОВАТЬ

Естьслучаи, когда использование альтернативы NULL допустимо по моему мнению.Но только там, где это уменьшает код, а не создает особые случаи, требующие учета.

Я использовал это, например, для данных с привязкой к дате.Если данные действительны между начальной датой и конечной датой, код можно упростить, не имея значений NULL.Вместо этого начальную дату NULL можно заменить на «01 января 1900 года», а конечную дату NULL можно заменить на «31 декабря 2079 года».

Это все еще может изменить поведение по сравнению с тем, что можно ожидать, и поэтомуследует использовать с осторожностью:

  • WHERE end-date IS NULL больше не дает данных, которые все еще действительны
  • Вы только что создали свою собственную ошибку тысячелетия
  • и т. д.

Это эквивалентно реформированию абстракции, так что все свойства всегда могут иметь допустимые значения.Он заметно отличается от неявного кодирования конкретного значения в произвольно выбранные значения.

Тем не менее, увольняйте подрядчика.

26 голосов
/ 10 июля 2011

Это легко одно из самых странных мнений, которые я когда-либо слышал.Использование магического значения для представления «нет данных» вместо NULL означает, что каждый фрагмент кода, который у вас есть, должен будет постобработать результаты, чтобы учесть / отбросить значения «без данных» / «Z».

NULL особенный из-за способа, которым база данных обрабатывает его в запросах.Например, возьмем эти два простых запроса:

select * from mytable where name = 'bob';
select * from mytable where name != 'bob';

Если name когда-либо равен NULL, он, очевидно, не будет отображаться в результатах первого запроса.Что еще более важно, он также не будет отображаться во втором запросе результатов.NULL не соответствует ничему, кроме явного поиска NULL, например:

select * from mytable where name is NULL;

И что происходит, когда данные могут иметь Z в качестве допустимого значения?Допустим, вы храните чью-то среднюю букву?Будет ли Zachary Z Zonkas смешиваться с людьми без среднего начального?Или ваш подрядчик придумает еще одно магическое значение для обработки этого?

Избегайте магических значений, которые требуют от вас реализации функций базы данных в коде, который база данных уже полностью способна обрабатывать.Это решаемая и хорошо понятая проблема, и может случиться так, что ваш подрядчик никогда не понимал понятие NULL и поэтому избегает его использования.

22 голосов
/ 10 июля 2011

Если домен допускает пропущенные значения, тогда использование NULL для представления 'undefined' вполне нормально (для этого он и существует).Единственным недостатком является то, что код, который потребляет данные, должен быть написан для проверки на NULL.Я всегда так делал.

Я никогда не слышал (или видел на практике) об использовании Z для представления отсутствующих данных.Что касается «подрядчик называет это« стандартной практикой »среди администраторов баз данных», может ли он предоставить некоторые доказательства этого утверждения?Как упоминалось в @Dems, вам также необходимо документально подтвердить, что «Z» не означает «Z»: как насчет MiddleInitial столбца?

Как Аарона Алтона и многих другихполагать, что значения NULL являются неотъемлемой частью проектирования базы данных и должны использоваться там, где это необходимо.

17 голосов
/ 10 июля 2011

Даже если вам как-то удастся объяснить всем вашим нынешним и будущим разработчикам и администраторам баз данных «Z» вместо NULL, и даже если они все прекрасно кодируют, вы все равно запутаете оптимизатор, поскольку он не будет знать,готово.

Использование специального значения для представления NULL (которое уже является специальным значением для представления NULL) приведет к перекосам в данных.Например, 1 января 1900 года произошло так много всего, что он лишил оптимизатора возможности понять фактический диапазон дат, который действительно имеет отношение к вашему приложению.

Это похоже на решение менеджера: «Ношениегалстук вреден для производительности, поэтому мы все будем носить маскирующую ленту на шеях. Проблема решена. "

9 голосов
/ 10 июля 2011

Я никогда не слышал о широко распространенном использовании 'Z' вместо NULL.

(Между прочим, я бы не особенно хотел работать с подрядчиком, который на самом деле говорит вам, что они и другие "продвинутые" администраторы баз данных намного более осведомлены и лучше вас.)

 +=================================+
 |  FavoriteLetters                |
 +=================================+
 |  Person      |  FavoriteLetter  |
 +--------------+------------------+
 |  'Anna'      |  'A'             |
 |  'Bob'       |  'B'             |
 |  'Claire'    |  'C'             |
 |  'Zaphod'    |  'Z'             |
 +---------------------------------+

Как ваш подрядчик будет интерпретировать данные из последней строки?

Возможно, он выберет другое "магическое значение" в этой таблице, чтобы избежать столкновения с реальными данными 'Z'? Это означает, что вам нужно запомнить несколько магических значений, а также, какое из них используется, где ... как это лучше, чем иметь только один магический токен NULL и необходимость помнить трехзначные логические правила (и ловушки), которые идут с этим? NULL по крайней мере стандартизирован, в отличие от 'Z' вашего * подрядчика.

Мне тоже не особо нравится NULL, но бессмысленно подставлять его фактическим значением (или, что еще хуже, несколькими фактическими значениями) везде почти определенно хуже, чем NULL.

Позвольте мне повторить мой вышеупомянутый комментарий здесь для лучшей наглядности: если вы хотите прочитать что-то серьезное и обоснованное людьми, которые против NULL, я бы порекомендовал короткую статью " Как обрабатывать недостающую информацию без использования NULL " (ссылки на PDF из Домашняя страница третьего манифеста ).

4 голосов
/ 10 июля 2011

Ничто в принципе не требует нулей для правильного проектирования базы данных.На самом деле существует множество баз данных, разработанных без использования null, и есть множество очень хороших дизайнеров баз данных и целых групп разработчиков, которые проектируют базы данных без использования null.В общем, хорошо быть осторожным при добавлении нулей в базу данных, потому что они неизбежно приводят к неправильным или неоднозначным результатам в дальнейшем.

Я не слышал об использовании Z как "стандартной практики" в качестве заполнителязначение вместо нуля, но я ожидаю, что ваш подрядчик ссылается на концепцию значений дозорного в целом, которые иногда используются при проектировании базы данных.Однако гораздо более распространенный и гибкий способ избежать нулевых значений без использования «фиктивных» данных - это просто спроектировать их.Разложите таблицу так, чтобы каждый тип факта записывался в таблицу, которая не имеет «лишних», неопределенных атрибутов.

3 голосов
/ 12 июля 2011

В ответ на комментарии подрядчиков

  • Пустая строка <> NULL
  • Пустая строка требует 2 байта памяти + чтение смещения
  • NULL использует нулевое растровое изображение = быстрее
  • IDENTITY не всегда начинается с 1 (зачем тратить половину своего диапазона?)

Вся концепция ошибочна, как и большинство других ответов здесь

1 голос
/ 10 июля 2011

Хотя я никогда не видел «Z» как магическое значение для представления нуля, я видел «X», используемый для представления поля, которое не было заполнено. Тем не менее, я видел это только в одном месте,и мой интерфейс к нему был не базой данных, а скорее файлом XML ... поэтому я не был бы готов использовать этот аргумент в качестве обычной практики.

Обратите внимание, что мы действительно должны обрабатывать 'X'и, как упоминал Демс, мы должны это задокументировать, и люди были смущены этим.В нашу защиту это навязывается нам внешним поставщиком, а не тем, что мы сами готовили!

...