Применение null

Модераторы: kdv, CyberMax

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 26 июн 2006, 15:49

Признаюсь в категоричности. Плюньте в меня за это :wink: А руководства пишут тоже люди. Разные люди с разным мнением.
CyberMax писал(а):а. Просто значение. Null необходим, если это, например, номер корпуса, количество квартир в доме, количество этажей. Их не может быть 0, а именно либо незаполненно либо больше 0.
Null вы всё равно будете дополнительно обрабатывать, прежде чем показать юзеру. Поэтому 0 вполне сойдёт. Многие гриды нули умеют скрывать, думаете, зря?
в. Ссылка на деталь-таблицу. Например, на диспетчера, мастера, слесаря. Может быть не заполнено вообще. Ссылка на запись с "пустым" работником не применима, так как работник НЕ УКАЗАН и работник ПУСТОЙ - две разные вещи.
Вы сами ответили - записи с кодом 0 и 1 - "Не указан" и "Пустой". А null будет скорее указывать на нецелостность данных.
3. Символьный тип. Поле примечания, поле телефона, ФИО и прочее.
В чём отличие от пустой строки?
Где надо - я ставлю ограничение Not Null, где не надо - не ставлю
Вы хотите сказать, что где не обойтись - ставите NN, а в остальных нет. А я наоборот, не ставлю NN где null необходим, а в остальных - ставлю.

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 26 июн 2006, 16:03

WildSery писал(а):Null вы всё равно будете дополнительно обрабатывать, прежде чем показать юзеру. Поэтому 0 вполне сойдёт. Многие гриды нули умеют скрывать, думаете, зря?
Иногда отображаю 0, иногда - пустоту. В зависимости от того, что что будет логичней для конкретного поля.
Вы сами ответили - записи с кодом 0 и 1 - "Не указан" и "Пустой". А null будет скорее указывать на нецелостность данных.
Я писал про внешний ключ. А это означает, что содержимое поля должно быть среди primary key внешней таблицы. При чем тут 0 и 1?
В чём отличие от пустой строки?
В том, что Null - это нет значения, а пустая строка - это строка нулевой длины.
Вы хотите сказать, что где не обойтись - ставите NN, а в остальных нет. А я наоборот, не ставлю NN где null необходим, а в остальных - ставлю.
Я хотел сказать
Где надо - я ставлю ограничение Not Null, где не надо - не ставлю.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 26 июн 2006, 16:29

Я писал про внешний ключ. А это означает, что содержимое поля должно быть среди primary key внешней таблицы. При чем тут 0 и 1?
Вы писали про "Ссылка на деталь-таблицу", не обязательно она должна быть с FK. И я говорю про значения PK в таблице значений. Запись с id=0 и id=1. Соответственно, будет не null, а 0, и ссылается на конкретную запись "Нет значения".
В том, что Null - это нет значения, а пустая строка - это строка нулевой длины.
Это отличие на уровне БД, а данные отражают значения из реального мира. Вы в бумажной записной книжке в поле Ф.И.О. тоже null рисуете, если не указано?
Я хотел сказать
Сформулирую вопрос по-другому. А там, где нет прямой необходимости ни в том, ни другом, вы что ставите?

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 26 июн 2006, 17:16

WildSery писал(а):Вы писали про "Ссылка на деталь-таблицу", не обязательно она должна быть с FK.
А как же ссылочная целостность? :shock:
WildSery писал(а):И я говорю про значения PK в таблице значений. Запись с id=0 и id=1. Соответственно, будет не null, а 0, и ссылается на конкретную запись "Нет значения".
1. Вы в курсе, что id=0 неприменим при джойне?
2. Нет записей "Нет значения". Таковыми могут быть только поля. И как мне делать отбор по ней? Считать, что запись, означающая "нет значения", всегда имеет id=1? А если там есть еще логическое разделение и таковых записей может быть несколько?
Это отличие на уровне БД, а данные отражают значения из реального мира. Вы в бумажной записной книжке в поле Ф.И.О. тоже null рисуете, если не указано?
Между прочим, Null и пустая строка отображаются одинаково - как пустая строка. Так что в ЗК на самом деле стоит Null, только он выглядит как '' :D.
Сформулирую вопрос по-другому. А там, где нет прямой необходимости ни в том, ни другом, вы что ставите?
Нет такого понятия "прямая необходимость". Если бизнес-логика не допускает null в поле, ставится ограничение not null, иначе не ставится. Это же элементарное True/False. Тут нет значения "может быть". Обратное тоже верно: если бизнес-логика допускает null в поле, то ограничение не ставится.

P.S. Короче, читай книжки. Запарился уже писать. Время полночь, а я тут объясняю базовые вещи :x.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 26 июн 2006, 18:03

1. Вы в курсе, что id=0 неприменим при джойне?
явно видно, что вы, двое, разговариваете на разных языках или пользуетесь разными терминами.
2. Нет записей "Нет значения". Таковыми могут быть только поля. И как мне делать отбор по ней? Считать, что запись, означающая "нет значения", всегда имеет id=1? А если там есть еще логическое разделение и таковых записей может быть несколько?
насчет "логического разделения" это уже перебор. WildSery ведет речь о том, что null в FK считается "нехорошим", и заменяется на дополнительную запись в справочнике с идентификатором 0, -1 и т.д. В результате наоборот, пропадает необходимость в outer join если требуется вытащить заказы "неизвестных клиентов" или что-то вроде.

Короче, см. "Введение в системы баз данных" Дейта, глава 19 "Отсутствующая информация", конкретно со страницы 749 в восьмом издании.
"...
Наконец, следует отметить, что "необходимости" разрешить присутствие неопределенных значений (NULL) во внешних ключах вполне можно избежать за счет соответствующего проектирования базы данных [19.19]. Еще раз обратимся к примеру с отделами и сотрудниками. Возможна ситуация, когда некоторые сотрудники действительно не относятся ни к одному из отделов. Но тогда, как уже предполагалось в конце предыдущего раздела, логичнее было бы не включать атрибут номера отдела DEPT# в переменную отношения EMP, а создать отдельную переменную отношения (скажем) ED с атрибутами EMP# и DELPT#, предназначенную для представления того факта, что указанный сотрудник работает в данном отделе..."

и дальше, в разделе 19.5
"Таким образом, внешнее соединение предназначено для решения весьма важной проблемы, заключающейся в потере информации при внутреннем соединени. Некоторые авторы высказывают мнение, что система должна обеспечивать прямую и явную поддержку внешних соединений, вместо того чтобы требовать от пользователя при формировании запроса прибегать к различным ухищрениям для достижения желаемого результата. В частности, в [6.2] приведено мнение о том, что внешние соединения должны быть неотъемлемой частью реляционной модели. Тем не менее, в этой книге автор не поддерживает эту позицию, в частности, по приведенным ниже причинам:
- Прежде всего, безусловно, операция внешнего соединения использует неопределенные значения (NULL), а автор настоящей книги всегда выступает против этого по целому ряду описанных ранее основательных причин.
- ...
- Наконец, уже было высказано мнение о том, что атрибуты со значениями в виде отношений представляют собой альтернативный подход, позволяющий радикально устранить все эти проблемы. Такой подход исключает необходимость использования неопределенных значений (NULL) и операций внешнего соединения и в целом, по мнению автора, представляет собой более изящное решение (не гноворя уже о том, что это - реляционное решение, которое не приводит к нарушению реляционной модели. ..."

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

Тьфу, извините, надо было и дальше поцитировать. Раздел 19.6
"Как показано выше, введение неопределенных значений (NULL) приводит к разрушению реляционной модели, которая великолепно обходилась без них в течение десяти лет с момента ее создания в 1969 году и вплоть до введения этих значений в 1979 году.
Теперь предположим, как показано в разделе 19.4, что понятие неопределенных значений в контексте представления отсутствующей информации заменено понятием специальных значений. Следует отметить, что в реальном мире мы обычно пользуемся именно специальными значениями. Например, специальное значение "?" используется для обозначения количества рабочих часов для некоторого сотрудника, если его фактическое значение по какой-либо причине неизвестно. Таким образом, общая идея заключается в том, чтобы просто применять подходящее специальное значение, отличное от всех обычных значений атрибута, во всех тех случаях, когда обычное значение не может использоваться. Обратите внимание, что это специальное значение обязательно должно принадлежать к соответствующему типу.
..."

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 26 июн 2006, 19:34

CyberMax писал(а): в своем генераторе запросов сделал функцию шаблона коалески и забыл про null :). Запросы, правда, здоровые получаются :(, особенно когда строка адреса собирается...
И про индексы тоже забыл, если коалеска в where. А ранее вместо неё непрерывный Or Is [Not] Null везде. Я как-то с Дейтом больше согласен, чем с Еленой.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 26 июн 2006, 19:36

WildSery писал(а): то null кроме как для дат, ни для чего неприменим. С null вы расставляете грабли для себя - вычисления, конкатенация, индексы, агрегаты...
Хоть в общем и целом стою на сходных позициях - но агрегатам-то он чем не угодил?

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 26 июн 2006, 19:42

Ivan_Pisarevsky писал(а): Тут можно много спорить, но сделано осмысленно, в результате скорость выборок и простота запросов на хорошом уровне. Все просто и убойно, как двуствольный дробовик, и никаких мега процедур для копошения в этих датах не применяется. :)
Тут вот какая штука. Из-за этого ты во всех запросах типа "с такого-то числа и по сегодня" вынужден либо задавать правую границу, либо добавлять And <> SuperDate, про что думать не нужно в случае нулла в неслучившихся датах. Точно так же, как с другими типами как раз из-за нуллов вынужден всё время поминить о том что он и ничему не равен и ничему не неравен и тоже писать лишний текст, что ведёт за собой проблемы с использованием индексов.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 26 июн 2006, 20:19

Хоть в общем и целом стою на сходных позициях - но агрегатам-то он чем не угодил?
кстати, видать агрегатам null не угодил как раз когда их ввели. Не знали, чего с ними делать, поэтому решили в sql-стандарте их игнорировать :)

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 27 июн 2006, 01:32

Насчет Null-ов во внешних ключах - при возможности, стараюсь их избежать. Но когда это не получается - использую. Мне больше важна понятность структуры БД, что следование Дейту. Он хоть и огромный авторитет, но слова его как догму тоже воспринимать не стоит. Именно это я и хотел сказать - не надо их бояться, а использовать осмысленно и при необходимости.

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 27 июн 2006, 12:37

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

Коллеги, вопрос-то изначальный про синхронизацию-репликацию был... :roll:

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 27 июн 2006, 14:57

Дык я уж сколько лет никому ничего не доказываю и не заставляю делать так или эдак :) Так, подкидываю пищу для ума :) Тем, у кого он есть ;)

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 27 июн 2006, 21:56

Хоть в общем и целом стою на сходных позициях - но агрегатам-то он чем не угодил?
Как уже заметил Дмитрий - любой агрегат проигнорирует строки с null как будто их вообще нет. select count(field1) from table1 покажет число записей, в которых field1 не null (в отличие от count(*), который всё сосчитает).
Хотя, в редких случаях эту особенность можно использовать :wink:
Ivan_Pisarevsky писал(а):Коллеги, вопрос-то изначальный про синхронизацию-репликацию был... :roll:
Тот вопрос давно обсудили, ветка ушла далеко. Наверное, в каком-то месте нужно обрезать и положить в общие вопросы?

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 28 июн 2006, 02:17

WildSery писал(а):Тот вопрос давно обсудили, ветка ушла далеко. Наверное, в каком-то месте нужно обрезать и положить в общие вопросы?
Да.

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 28 июн 2006, 08:15

Merlin писал(а):Так, подкидываю пищу для ума :) Тем, у кого он есть ;)
Пища для ума это ценный фрукт, спасибо. :) (эт не ирония, а совершенно искренний улыбающийся смайлик)

Zhur
Сообщения: 125
Зарегистрирован: 01 мар 2006, 18:17

Сообщение Zhur » 24 авг 2006, 22:25

А все-таки неплохая суматошка получилася. :D

SAV
Сообщения: 54
Зарегистрирован: 19 авг 2006, 17:59

Сообщение SAV » 05 дек 2006, 16:52

Да заварушка познавательная с практической стороны как кто использует и как не надо этого делать. Хотелось бы внести своё мнение, я скорее всего приму сторону тех кто за использование null там где это не противоречит структуре бд и здравому смыслу и приведу свой пример. Есть таблица логов с кучей всевозможных полей, при выполнений пользователем одного типа действий есть данные в одних полях в остальных null, при выподнении другого другие в другой комбинации и тюп.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 05 дек 2006, 19:20

SAV писал(а):Есть таблица логов с кучей всевозможных полей
Пример отстой, извини.
Если это действительно лог, а не журнал операций, то это должен быть внешний файл для читаемости вне сервера, а значит, забудь о нулах.
Если всё же журнал - то надо нормализовать, и справочник "действий" завести, а в журнале только ссылка на действие и даташтамп. Может, ещё пару полей. Но никак не "все возможные".

SAV
Сообщения: 54
Зарегистрирован: 19 авг 2006, 17:59

Сообщение SAV » 05 дек 2006, 21:49

WildSery писал(а):Пример отстой, извини.
Ну зачем так категорично 'отстой' по моему,надо рассматривать проекты в целом,что зачем и почему. Я и не настаиваю на том что это лог, пусть будет называться журналом, а справочник есть и ... эх чего это я. Я уже заводил тему про журналирование и там всё уяснил для себя.

dsd_corp
Сообщения: 8
Зарегистрирован: 12 ноя 2006, 15:32

Сообщение dsd_corp » 18 дек 2006, 16:22

CyberMax писал(а): 2. А если select * from table where (:date_in between date_beg and date_end) or (date_end is null)?
поправлю:

Код: Выделить всё

select * 
from table 
where (date_beg<=:date_in) and
      ((date_end>=:date_in) or (date_end is null))
ибо при вашем условии "or (date_end is null)" выберутся так же те незакрытые(date_end is null) записи, date_beg которых больше :date_in, т.е. во временной промежуток которых :date_in по сути не попадает.

Ответить