Применение null

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

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 23 июн 2006, 11:39

Ivan_Pisarevsky писал(а):Почему народ упорно не желает юзать внешние таблицы?
из-за нуллов?

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

Сообщение WildSery » 23 июн 2006, 11:43

если в таблице есть null - значит, БД плохо спроектирована :)

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

Сообщение Ivan_Pisarevsky » 23 июн 2006, 11:43

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

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

Сообщение CyberMax » 23 июн 2006, 11:51

WildSery писал(а):если в таблице есть null - значит, БД плохо спроектирована :)
:lol: :lol: :lol:. Ржунимагу. В мемориз. Однозначно.

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

Сообщение WildSery » 23 июн 2006, 12:49

CyberMax писал(а):Ржунимагу. В мемориз. Однозначно.
Это сарказм? Тогда обоснуйте крайнюю необходимость поля со значением null.

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

Сообщение Merlin » 23 июн 2006, 17:27

Вапервых, нулл - это не значение. Вавтарых - элементарно, Ватсон. Дата события, которое есчо не наступило.

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

Сообщение WildSery » 23 июн 2006, 18:15

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

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

CREATE TABLE EVENTS (
    ID          INTEGER NOT NULL,
    EVENT_DATE  DATE NOT NULL);

CREATE TABLE TABLE1 (
    ID       INTEGER NOT NULL,
    ...
    EVENTID  INTEGER NOT NULL DEFAULT 0);
Примечание - в таблице EVENTS нет и не будет записей с ID=0.
Дату можно получить, поискав в EVENTS, и если записи нет - вот вам и "ещё не наступило".

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

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

Вот тока не нада меня учить ни хорошим манерам, ни проектированию, лана? Я ничего не придумываю, а отражаю реальную действительность как она есть. А база - она вообще ничего не знает, не её ума дело - что-либо знать. Ну и прикинь теперь элементарные запросы с использованием этой искусственной кочерги 1:1. Везде совершенно лишний и ненужный левый джойн, отнюдь производительности не прибавлящий, особенно на фильтрациях и сортировках по этому полю. Особенно если учесть, что в хорошей базе среднестатистический запрос и так цепляет 10-15 таблиц, а этот лефт ещё попотеешь впихнуть в цепочку иннеров чтоб не сбить оптимизатор с толку и получить оптимальную последовательность соединений. 1:1 из-за одного атрибута - нонсенс, если речь не о длинном варчаре, конечно. На каждый датный атрибут по таблице - это сильный ход, ничего не скажешь :)

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

Сообщение CyberMax » 25 июн 2006, 13:27

WildSery писал(а):Это сарказм? Тогда обоснуйте крайнюю необходимость поля со значением null.
Это не сарказм. Я реально посмеялся.
Камрад Merlin правильно расписал. Добавлю свою толику.
Такая простая вещь, как журнал регистрации каких-нибудь заявок. У меня, например, в одном 5 (пять) timestamp'ов, из которых not null только один - дата регистрации. Остальные заполняются по мере ее обработки. Джойн тут совершенно неуместен, так же как и строковый тип (увеличенный размер записи), плюс проблема с сортировкой и отбором.
P.S. Не хотел разводить тут оффтоп, но пришлось. Поэтому буду благодарен, если ты в отдельной теме в разделе, например, "Пятница", проведешь мастер-класс, как писать базы твоим стилем. Со скриптами реальных баз данных.

CCB
Сообщения: 35
Зарегистрирован: 20 июн 2006, 14:06

Сообщение CCB » 26 июн 2006, 10:06

ну тада и я свою каплю капну по поводу полей timestamp...
вапще-то любое событие длицца определенный промежуток времени, так что по-хорошему, для события нужно предусматривать два поля timestamp, что-то типа - RunEvent и EndEvent...

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

Сообщение Ivan_Pisarevsky » 26 июн 2006, 10:20

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

Например у меня в таблице заголовков накладнух есть поле "примечание", которое в 90% пустует и я его со спокойной совестью храню в виде "нулл", а бывает туда надо что-нидь вписать, зачем сюда еще какое-то педали в виде доп таблиц?

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

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

Сообщение WildSery » 26 июн 2006, 11:43

Я вовсе не так категоричен, как вам могло показаться, а всего лишь поиронизировал над суждением, что внешние таблицы из-за null неюзабельны. И в моей базе тоже есть null. И даже много где :wink:
Есть и даты далёким будущим, т.к. промежутки удобно выбирать по вывернутому условию, типа where :date_val between datestart and dateend
Например у меня в таблице заголовков накладнух есть поле "примечание", которое в 90% пустует и я его со спокойной совестью храню в виде "нулл", а бывает туда надо что-нидь вписать
По-моему, неудачный пример. Чем вас пустая строка вместо null не устроила?

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

Сообщение Ivan_Pisarevsky » 26 июн 2006, 13:19

WildSery писал(а):Я вовсе не так категоричен, как вам могло показаться, а всего лишь поиронизировал над суждением, что внешние таблицы из-за null неюзабельны.
Все нормально юзабельно, просто надо помнить о нуллах и не забыть их адекватно обработать, простейший рецепт выше есть.
WildSery писал(а):По-моему, неудачный пример. Чем вас пустая строка вместо null не устроила?
Это вполне адекватный пример когда не стоит уделять столько внимания нуллам, они мне не мешают и аллергией я не страдаю. В этом конкретном случае нуллы можно и искоренить, только выгода от этого никак трудозатрат не окупит, потому как выгода эфемерна от этого. :)

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

Сообщение Merlin » 26 июн 2006, 13:49

Ivan_Pisarevsky писал(а): Например у меня в таблице заголовков накладнух есть поле "примечание", которое в 90% пустует и я его со спокойной совестью храню в виде "нулл"
Грабельки положил. Если когда-нить возникнет потребность в конкатенации с чем-нить (скажем, комментария в накладной и в связанном счёте), придётся мудохаться с коалеской и помнить про это. Спокойней дефолт пустая строка засадить и забыть.
Ivan_Pisarevsky писал(а): А ненаступившие события я храню в виде большой даты, которая точно в ближайшую тыщу лет не наступит
А тут грабельки противоположного сорту - отсёк себе возможность искать на "больше", только диапазоном. Нулл именно в датах как раз удобен, именно потому, что в этом случае он отражает реальну действительность, данную нам в ощущениях. Есть, скажем, заказ, но он ещё не подтверждён. Событие ещё не наступило и даты подтверждения именно нет, ни под какие условия значение поля в записи не подпадает автоматически потому что значения-то и нету, в отличие от сомнительности смысла нулла в других типах. И, соответственно, в датах неудобно его отсутствие, в других типах присутствие.

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

Сообщение CyberMax » 26 июн 2006, 14:33

WildSery писал(а):Я вовсе не так категоричен, как вам могло показаться, а всего лишь поиронизировал над суждением, что внешние таблицы из-за null неюзабельны. И в моей базе тоже есть null. И даже много где :wink:
Уважаемый, вы конкретно написали:
WildSery писал(а):если в таблице есть null - значит, БД плохо спроектирована
Противоречите сами себе! В следующий раз подумайте, прежде чем ляпнуть подобное, да еще таким тоном. Дабы у читателей не вызывать сомнения в вашей дееспособности.
Merlin писал(а):Грабельки положил. Если когда-нить возникнет потребность в конкатенации с чем-нить (скажем, комментария в накладной и в связанном счёте), придётся мудохаться с коалеской и помнить про это. Спокойней дефолт пустая строка засадить и забыть.
С точки зрения облегчения своего труда - верно. А с логической - имхо, не совсем... Поэтому в своем генераторе запросов сделал функцию шаблона коалески и забыл про null :). Запросы, правда, здоровые получаются :(, особенно когда строка адреса собирается...

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

Сообщение Ivan_Pisarevsky » 26 июн 2006, 14:38

>Грабельки положил. Если когда-нить возникнет потребность в конкатенации с чем-нить (скажем, комментария в накладной и в связанном счёте)...
Скорее теоретически, на практике в данном конкретном случае - нет. Это поле ни в каких отборах, джойнах, склейках не участвует и не будет, поэтому я и забил на него. Где вероятность описаных грабель есть стараюсь сразу принять адекватные меры, например описаные тобой выше про нот нулл+дефалт значение.

>А тут грабельки противоположного сорту...
Тут можно много спорить, но сделано осмысленно, в результате скорость выборок и простота запросов на хорошом уровне. Все просто и убойно, как двуствольный дробовик, и никаких мега процедур для копошения в этих датах не применяется. :)

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

Сообщение CyberMax » 26 июн 2006, 14:54

Ivan_Pisarevsky писал(а):Тут можно много спорить, но сделано осмысленно, в результате скорость выборок и простота запросов на хорошом уровне. Все просто и убойно, как двуствольный дробовик, и никаких мега процедур для копошения в этих датах не применяется. :)
Простота запросов, говорите. Вместо 'where date_field is null' вы пишете 'where date_field = date_constant'. Ну или :somedate. Смотря на первый вариант, вы понимаете - отбор накладных, которые еще не оплачены (если это дата оплаты). Во втором варианте - действие непонятно.
Плюс есть такая вещь, как валидность даты. Если дата накладной датируется каким-нибудь 3457 годом, непонятно, это сбой или ваша та самая "магическая" дата?
"в результате скорость выборок и простота запросов на хорошом уровне". Хотите сказать, из-за отказа от Null скорость выполнения стала быстрей, чем с Null?

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

Сообщение WildSery » 26 июн 2006, 14:58

CyberMax писал(а):Противоречите сами себе! В следующий раз подумайте, прежде чем ляпнуть подобное, да еще таким тоном. Дабы у читателей не вызывать сомнения в вашей дееспособности.
Я себе не противоречу и не утверждал, что моя база спроектирована хорошо. И если уж с иронии (с которой я и утверждал, мой смайлик вы не процитировали) переходить на суровую действительность, то null кроме как для дат, ни для чего неприменим. С null вы расставляете грабли для себя - вычисления, конкатенация, индексы, агрегаты...
Кто-то тут говорил о топоре и умении им пользоваться. Им хорошо рубить. А ещё можно забить гвоздь. Но лучше молотком.
"в результате скорость выборок и простота запросов на хорошом уровне". Хотите сказать, из-за отказа от Null скорость выполнения стала быстрей, чем с Null?
Вы невнимательны. Я привёл такой пример. Если некие события в таблице хранятся диапазонами datebeg..dateend, и постоянная задача выяснить, в какой диапазон(ы) входит дата :date_in, то это элементарно выясняется запросом select * from table where :date_in between date_beg and date_end.

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

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

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

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

Сообщение CyberMax » 26 июн 2006, 15:23

WildSery писал(а):Вы невнимательны. Я привёл такой пример. Если некие события в таблице хранятся диапазонами datebeg..dateend, и постоянная задача выяснить, в какой диапазон(ы) входит дата :date_in, то это элементарно выясняется запросом select * from table where :date_in between date_beg and date_end.
1. Вообще-то я не вам это писал.
2. А если select * from table where (:date_in between date_beg and date_end) or (date_end is null)? Что логичнее.

Ответить