Лыцарь пичальнава образа - Про NULL или "как примирить ся с реальностью". [entries|archive|friends|userinfo]
silly_sad

[ userinfo | ljr userinfo ]
[ archive | journal archive ]

Про NULL или "как примирить ся с реальностью". [Mar. 4th, 2010|10:56 am]
Previous Entry Add to Memories Tell A Friend Next Entry
[Tags|]

Попросили меня написать про NULLы.
Пишу.

NULLы -- (ктоб сомневался!) зло.
А вот не мешало бы и посомневаться!

Но сомневайтесь вы там сами, а тут будет сплошной конструктив.
Нулы нам даны свыше и с ними надо как-то жить, (даже если мы их очень не хотим) они всё равно будут пролазить СКВОЗЬ все наши операции (как "нескажу что").

Итак самый надёжный подход (чтобы избежать конфуза) позапрещать их во всех полях куда руки достанут.
И вот в этот момент (когда вы пишете "NOT NULL") вас в какой-то мемент посетит острое ощущение отрезания полезной конечности и вопрос: "вот в этом партикулярном месте, что означал нулл в реале?"

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

Но есть и исключения:

1.
Первейшее это ссылочная целостность.
Если у вас связь между таблицами необязательная то никто кроме нула не сможет выразить её отсутсвие (так чтобы при этом Foreign Key продолжал работать).
Например у вас в таблице валяются деревья. Каким хреном представить их корни?
Некоторые юные борцы с нулами предлают делать в корешке петельку. Не надо так делать, индексу будет трудненько понять чего вы хотите (когда пытаетесь выбрать "все корни"). Ну и лишний маленький геморройчик в рекурсивных функциях над деревом.

Кроме того бывают связи N:0, даже не пытайтесь отрицать их существование.

2.
Null чудесно расширяет тип BOOLEAN когда вам вдруг (а это бывает нередко) мало двух значений, а 256 много, а трёх достаточно.
Ну грубый отфонарный пример, если вы просили юзера указать требование к бинарному свойству. Он может потребовать одно из двух значений либо отказаться от требования. Отказ от требования запишите в виде нула.

3.
Null бывает очень полезен в числовых полях. Если у вас есть сущности с неким исключительным смыслом, отличным от смысла сущностей с любым числовым значением.
Реальнейший пример:
Вы продаёте услуги (среди которых есть безплатные). И эти безплатные ничем не отдичаются от платных кроме цены. Ну цена == 0 и слава Богу.
А (кроме услуг с ценой) у вас есть ещё и Demo-услуги (которые (хотя и безплатные) от всех прочих отличаются очень сильно: даёте вы их юзеру один раз и заказать их обычным путём нельзя и ещё куча всяких ограничений)
Вот их цену и надо обозначить нулом и не ебсти себе мозг пуританством. При написании приложения станет видно как естественно такой нулл ведёт себя при вычислении. (Может быть именно так видели светлое будущее нула его родители?!)

4.
Null может банально ускорить вам вычисления с наворочеными типами.
Например есть у вас HSTORE (для которого в вашем приложении допустимо пустое значение), вам будет проще сравнить всё поле с нулом нежели лезть внутырь. Я предлагаю заменять в этом случае пустые значения на null.
Впрочем тут всё очень неоднозначно, но направление мысли я указал вам верное.

(Таким образом чётко очертив границы прикладной осмысленности нулов в партикулярном приложении) вы суживаете и обозначаете ихний ареал обитания и тем избавляете себя от сюрпризов (особенно от самого главного сюрприза со строковой катенацией: "я просто хочу посмотреть на эту запись") и от слишком большого нагромождения coalesce().

5.
Null может показывать непринадлежность к классификации.
Предположим у вас есть таблица, распадающаяся на классы эквивалентности. Вы принадлежность классу обозначили целочисленным полем. Равно -- в одном классе. Не равно -- в разных классах. Хуле! Отношение эквивалентности!
Но вдруг эта таблица у вас допускает внеклассовые записи? В будете каждому изобретать уникальный номер класса? -- это работа. А вдруг вам надо отличать внеклассовые записи от классов с одним элементом???? ААА? Заведёте себе специальный номер класса для внеклассовых записей? Тогда они все войдут в один класс (что будет просто НЕПРАВДА) зачем вам неправда в собственной базе.
И только нулл не равен никому!

6.
Null может показать исключение из сортировки.
Если вы завели суррогатное поле для принудительной сортировки записей, а ваше правило сортировки имеет исключения, то вот оно место для нульных значений.

В прочем для полноты ощущений от прелести нула нехватает одной страшной вещи:
трёх веточного IFа и модификатора для WHERE (который бы говорил: "treat NULL as true")
(кто здесь думает (что он лучше меня считает до двух)? улыбнитесь, вы ошибаетесь)

Для любознательных:
Самого Оракла НУЛЬНОЕ ЗНАЧЕНИЕ В СТРОКОВОМ ПОЛЕ ТОЖДЕСТВЕННО ПУСТОЙ СТРОКЕ.
(Если немного подумать) то мотивы такого решения станут вам понятны и дело не только в реализации (вспомните с каким наслаждением вы отрезали нулы от строковых полей!)
Но каким Особенным Адом, Адом Кромешным, Адом НЕИЗБЫВНЫМ, САТАНИНСКИМ АДОМ! это решение оборачивается на практике!
Попробуйте мысленно вычислить:
'abc' || ''
coalesce('','abc') --в Оракле эта функцея называицца nvl()
'abc' || NULL
insert into t (unique_text_field) select NULL;
insert into t (unique_text_field) select '';

Адовость в том (что без ЭКСПЕРИМЕНТА на эти вопросы ответить нельзя)!
Впрочем сейчас прибегут защитники Оракла и скажут (что надо читать Великие Сакральные Труды Руководителей Сертифицированных Курсов чтобы не задавать неудобных идиотских вопросов).
LinkLeave a comment

Comments:
[User Picture]
From:[info]vitus-wagner.livejournal.com
Date:March 4th, 2010 - 10:07 am
(Link)
Проблема NULL-а в том, что он один. А должно их быть два -
"NOT KNOWN" и "NOT APPLICABLE". Пример - цвет волос человека, которого ты никогда не видел без шляпы - "NOT KNOWN". Если сильно приспичит - можно попросить его предъявить то, что у него под шляпой. Цвет волос человека, про которого известно, что он лыс, как коленка - "NOT APPLICABLE".

Кстати, цена у демо-услуги именно "NOT APPLICABLE". А "NOT KNOWN" она у услуги, которая в базу уже попала, потому что под нее инфраструктуру делать надо, но менеджеры еще не договорились за сколько продавать.

From:[info]silly_sad
Date:March 4th, 2010 - 10:13 am
(Link)
да! это заставляет задумацца.

а я там проапдэйтил пост ещё двумя пунктами
[User Picture]
From:[info]vitus-wagner.livejournal.com
Date:March 4th, 2010 - 10:43 am
(Link)
Кстати, при сортировке два значения NOT KNOWN не равны друг другу (потому что мы не знаем, что там на самом деле), а два NOT APPLICABLE имеет смысл считать равными. Потому что все объекты лишенные признак, по котором проводится классификация, имеет смысл помещать в один класс.

Ну и понятно, что результат сравнения NOT KNOWN с любым другим значением "а хрен его знает" (как сейчас с NULL-ом) а NOT APPLICABLE - "не равно".