Стандартне використання 'Z' замість NULL для представлення відсутніх даних?


76

Поза аргументом про те, чи слід коли-небудь використовувати NULL чи ні: я відповідаю за існуючу базу даних, яка використовує NULL, щоб означати "відсутні або ніколи не введені" дані. Він відрізняється від порожнього рядка, що означає "користувач встановив це значення, і він вибрав" порожній "."

Інший підрядник проекту твердо висловлюється з аргументу "Сторінка NULL не існує для мене; я ніколи не використовую NULL, і ніхто інший не повинен". Однак мене бентежить те, що оскільки команда підрядника ДОЗНАЄ різницю між "зниклим / ніколи не введеним" та "навмисно порожнім або вказаним користувачем як невідомим", вони використовують один символ "Z" у коді та збережені процедури для представляють "відсутній / ніколи не введений" з тим самим значенням, що NULL, у всій іншій базі даних.

Незважаючи на те, що наш спільний клієнт просив це змінити, і я підтримав цей запит, команда називає це «стандартною практикою» серед адміністраторів баз даних, набагато просунутих, ніж я; вони неохоче змінюють використання NULL на основі лише мого необізнаного запиту. Отже, чи може хтось допомогти мені подолати своє незнання? Чи існує якийсь стандартний або невелика група осіб, або навіть єдиний гучний голос серед експертів з SQL, який виступає за вживання "Z" замість NULL?

Оновлення

У мене є відповідь від підрядника, щоб додати. Ось що він сказав, коли клієнт попросив видалити спеціальні значення, щоб дозволити NULL у стовпцях без даних:

В основному, я розробив базу даних, щоб уникати NULL, коли це можливо. Ось обґрунтування:

НУЛЬ у полі [VARCHAR] рядка ніколи не є необхідним, оскільки порожній рядок (нульової довжини) надає точно ту саму інформацію.

З НУЛОМ у цілочисельному полі (наприклад, значенням ID) можна обробити, використовуючи значення, яке ніколи не зустрічається в даних (наприклад, -1 для цілого поля ІДЕНТИЧНОСТІ).

НУЛЬ у полі дати може легко спричинити ускладнення під час обчислення дати. Наприклад, у логіці, яка обчислює різницю дат, таку як різниця в днях між [RecoveryDate] та [OnsetDate], логіка підірветься, якщо одна або обидві дати NULL - якщо явно не враховано обидві дати будучи НУЛЬНИМ. Це додаткова робота та додаткова керованість. Якщо для [RecoveryDate] та [OnsetDate] використовуються дати "за замовчуванням" або "заповнювач" (наприклад, "1/1/1900"), математичні розрахунки можуть показувати "незвичні" значення, але логіка дати не підірветься.

Обробка NULL традиційно є областю, де розробники допускають помилки в збережених процедурах.

За свої 15 років роботи в DBA я вважав, що найкраще уникати НУЛЬ, де це можливо.

Здається, це підтверджує переважно негативну реакцію на це питання. Замість того, щоб застосовувати прийнятий підхід 6NF до проектування NULL, використовуються спеціальні значення, щоб "уникати NULL, де це можливо". Я розмістив це запитання з відкритою душею, і я радий, що дізнався більше про дискусію "НУЛІ корисні / НУЛІ - це зло", але зараз мені цілком зручно називати підхід "особливих цінностей" повною нісенітницею.

порожній рядок (нульової довжини) подає точно таку ж інформацію.

Ні, це не так; в існуючій базі даних, яку ми модифікуємо, NULL означає "ніколи не вводився", а порожній рядок означає "введено як порожній".

Обробка NULL традиційно є областю, де розробники допускають помилки в збережених процедурах.

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


Як виноска: я працюю DBE і розробником більше 20 років (що, безумовно, достатньо часу, щоб я знав різницю між інженером та адміністратором бази даних). Протягом своєї кар’єри я завжди був у таборі "НУЛІ корисні", хоча я знав, що кілька дуже розумних людей не погодились. Я вкрай скептично ставився до підходу "особливих цінностей", але недостатньо добре обізнаний з науковцями "Як уникнути НУЛИ правильним шляхом", щоб твердо висловитись. Я завжди люблю вчитися новим речам - і мені ще доведеться багато чому навчитися після 20 років. Дякуємо всім, хто сприяв тому, щоб зробити це корисною дискусією.


60
NULL існує, щоб увімкнути трійкову логіку , необхідну для збереження цілісності посилань за відсутності повної інформації - я б назвав повну і повну BS будь-якого проголошеного експерта з БД, який категорично проти них!
Горді

17
Ніколи не чув про таку практику.
Calvin Allen

14
Чи запропонував підрядник сурогатне NULL для числових даних?
Andriy M

14
@Andriy: Це легко вирішити, усі експерти зберігають номери в полях символів і при необхідності додають (із Z-перевірками!). О, почекайте, я потрапив не на той сайт .
му занадто коротке

12
Я підозрюю, що свого часу цей підрядник намагався виконати WHERE Column = NULLі був збентежений, чому він не дав результатів.
Mike Caron

Відповіді:


104

Звільніть свого підрядника.

Добре, серйозно, це не стандартна практика. Це можна побачити просто тому, що всі СУБД, з якими я коли-небудь працював, реалізують 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 більше не надавати дані, які все ще є дійсними
  • Ви щойно створили свою власну помилку тисячоліття
  • тощо

Це еквівалентно реформуванню абстракцій таким чином, що всі властивості завжди можуть мати дійсні значення. Він помітно відрізняється від неявного кодування конкретного значення у довільно обрані значення.

Все-таки звільнити підрядника.


21
+1 від мене; spot on: "Я б насправді стверджував, що використання" Z "або будь-якого іншого власника місця гірше. Вам все одно потрібен код для перевірки на" Z ". Але ви також повинні задокументувати, що" Z "не означає" Z ", це означає щось інше ".
Mitch Wheat

20
Нам потрібна особлива цінність - не NULL, оскільки NULL - це зло - для представлення відсутніх даних. Щось, що відрізняється від усіх інших цінностей, можливо, навіть від нього самого (оскільки дві невідомі не можна ототожнювати просто тому, що вони невідомі). Деякі стовпці, очевидно, не мали б сенсу для цього значення, і тому це повинно бути заборонено. Щоб полегшити ситуацію, нам потрібні спеціальні оператори, такі як НЕВІДОМИЙ або НЕВІДОМИЙ.
Mike Caron

5
Підрядники часто мають хороші поради з глибокого досвіду, але те, що це іноді трапляється, не означає, що вам доведеться йти за вівцями через рекомендовану небезпечну скелю. Повідомте їх про те, що ви є господарем та власником бази даних: розробка буде такою, як зазначено: виконуйте дії або помріть.
wallyk

2
Якщо користувач вводить Z, то, очевидно, ви зберігаєте ZZ. Якщо вони потрапляють у ZZ, ви зберігаєте ZZZ тощо. Для цього потрібно, щоб усі ваші стовпці були на один символ більшими, але це не повинно бути проблемою.
Час. Owens

2
+1 від мене загалом - але особливо для редагування, де може мати сенс використовувати значення постів забору для діапазонів дат (мінімальна дата / максимальна дата) через те, скільки коду він може зберегти - особливо якщо вам доводиться порівнювати / перевіряти для перекриття в діапазонах дат. У цих випадках мінімальна дата означає "з тих пір", а максимальна дата означає "до назавжди", що відрізняється від NULL, що означає "не впевнений" або "все одно".
Джоел Браун,

26

Це легко одна з найдивніших думок, які я коли-небудь чув. Використання магічного значення для подання "немає даних", а не 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 як дійсне значення? Скажімо, ви зберігаєте чиюсь середню букву? Чи буде Захарій Зонкас зв’язаний з тими людьми, у яких немає середнього ініціалу? Або ваш підрядник придумає ще одне магічне значення для цього?

Уникайте магічних значень, які вимагають реалізації функцій бази даних у коді, з якою база даних уже повністю здатна обробляти. Це вирішена і добре зрозуміла проблема, і може бути, просто ваш підрядник ніколи не перекручував поняття NULL і тому уникає його використання.


22

Якщо домен дозволяє відсутні значення, тоді використання NULL для представлення „невизначеного” цілком нормально (для цього воно існує). Єдиним недоліком є ​​те, що код, який споживає дані, повинен бути записаний для перевірки на NULL. Так я завжди робив.

Я ніколи не чув (або не бачив на практиці) використання «Z» для представлення відсутніх даних. Щодо "підрядник називає це як" стандартну практику "серед баз даних", чи може він надати деякі докази цього твердження? Як згадував @Dems, вам також потрібно задокументувати, що "Z" не означає "Z": як щодо MiddleInitialстовпця?

Як і Аарон Алтон та багато інших, я вважаю, що значення NULL є невід'ємною частиною проектування баз даних, і їх слід використовувати там, де це доречно.


3
Я думаю, що ключовим тут є "Якщо домен дозволяє відсутні значення ..." Мені здається, що є час і місце, щоб відстоювати використання NULL, а також час і місце, щоб їх уникати, і для цього потрібна певна мудрість щоб знати різницю. У мене іноді виникає відчуття, що коли молодший DBE / DBA читає застереження на зразок: "Значення NULL можуть спричинити несподівані результати у запитах та обчисленнях, якщо ви не враховуєте їх поведінку", його реакція ривка полягає в позначенні всього використання NULL як погано. Коли він стає релігійною думкою, він залишається з ним на всю його кар’єру.
Борис Миколайович

1
Забуття речення WHERE на DELETE або UPDATE може завдати шкоди вашій базі даних => ніколи їх не використовувати. Або отримайте дані з першого разу, або відкрийте таблицю в редакторі та зробіть це самостійно.
MatBailie

Крім того, зауважте, що OUTER приєднується до NULL, тому його не слід використовувати. Так само, ЗВІТИ.
MatBailie

3
Z використовується для представлення часового поясу GMT у деяких стандартах.
Ерік Робертсон,

2
@ Ерік, це ще одна причина не вживати Z, щоб означати "немає значення".
Борис Миколайович

17

Навіть якщо вам якось вдасться пояснити всім своїм нинішнім і майбутнім розробникам та адміністраторам баз даних про "Z" замість NULL, і навіть якщо вони все ідеально кодують, ви все одно заплутаєте оптимізатор, оскільки він не знатиме, що ви це приготували .

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

Це все одно, що керівник вирішує: "Носіння краватки погано впливає на продуктивність, тому ми всі будемо носити на шиї малярський скотч. Проблему вирішено".


10
+1 лише для фрази "Використання спеціального значення для представлення NULL (що вже є спеціальним значенням для представлення NULL)". . .
Mike Sherrill 'Cat Recall'

Я думав, що краватка-метелик - це саме це, краватка на шиї, яку замінили малярською стрічкою, яка вважалася більш доречною для цього випадку ...
Soren

9

Я ніколи не чув про широко розповсюджене використання 'Z'в якості заміни NULL.

(До речі, я б не особливо хотів співпрацювати з підрядником, який в очі вам говорить, що вони та інші "просунуті" спеціалісти з управління справами набагато краще обізнані та кращі за вас.)

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

Як би ваш підрядник інтерпретував дані з останнього рядка?

Можливо, він вибрав би інше "магічне значення" у цій таблиці, щоб уникнути зіткнення з реальними даними 'Z'? Це означає, що вам доведеться запам’ятати кілька магічних значень, а також те, яке з них використовується де ... як це краще, ніж мати лише один магічний маркер NULL, і пам’ятати тризначні логічні правила (та підводні камені), які з ним пов’язані? NULLпринаймні стандартизований, на відміну від підрядника 'Z'.

Я не особливо люблю NULLжодне, але бездумно замінюючи його фактичним значенням (або ще гірше, кількома фактичними значеннями) скрізь майже напевно гірше, ніж NULL.

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


4

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

Я не чув про те, щоб використовувати Z як "стандартну практику" як значення заповнювача замість нулів, але я думаю, що ваш підрядник посилається на концепцію вартових вартостей загалом, які іноді використовуються при розробці баз даних. Однак набагато більш поширеним і гнучким способом уникнути нульових значень без використання "фіктивних" даних є просто їх проектування. Розкладіть таблицю таким чином, щоб кожен тип факту реєструвався в таблиці, яка не має "зайвих", неуточнених атрибутів.


1
Я думаю, що підрядник буквально означає використовувати «Z» для «не знаю».
wallyk

На жаль, @wallyk в основному правильний: це не академічна чи теоретична дискусія; Оскільки я сам розробник, я пройшов код і збережені процедури. Підрядник використовує буквальний символ 'Z' для відсутніх / невведених значень. (Значення, які насправді є "невідомими, але відповіли", ніколи не мають значення NULL навіть у поточному дизайні бази даних; обидва використовують порожній рядок для текстових полів або символ "U" для випадаючих списків, щоб вказати, що користувач відповів на запитання і відповідь була "не знаю".)
Борис Миколайович

@dportas - Я усвідомлюю, що правильний дизайн бази даних не вимагає використання нулів, але оскільки я перебуваю в розділі "Є час і місце використовувати NULL, якщо ви знаєте, як це зробити правильно", основною метою Питання полягало в тому, щоб зрозуміти, чи використання «Z» в хорошому дизайні бази даних кимось із табору «NoNULL» було або стандартним, загальним, або пропагандуваним кимось.
Борис Миколайович

3

У відповідь на коментарі підрядників

  • Порожній рядок <> NULL
  • Порожній рядок вимагає 2 байтів пам'яті + зсув зчитування
  • NULL використовує null bitmap = швидше
  • ІДЕНТИФІКАЦІЯ не завжди починається з 1 (навіщо витрачати половину свого діапазону?)

Вся концепція недолікова, як і більшість інших відповідей тут


4
Хоча; Наскільки я пам'ятаю, порожній рядок є NULL в Oracle.
MatBailie

1

Хоча я ніколи не бачив 'Z' як магічне значення для представлення нуля, я бачив, що 'X' використовувався для позначення поля, яке не було заповнене. Тим не менш, я бачив це лише в одному місці, і мій інтерфейс для нього була не база даних, а скоріше XML-файл ... тому я не був би готовий використовувати цей аргумент як звичайну практику.

Зауважте, що ми маємо обробляти «Х» спеціально, і, як згадував Демс, ми маємо це документувати, і людей це бентежило. На наш захист це нав'язує нам зовнішній постачальник, а не те, що ми приготували самі!


Це було б дуже заплутано для баз даних, які зберігають виділені прапорці, позначені полем символу "X", а не позначеним "(пробіл). Я сподіваюся, що антиматерія та матерія не змішуються в одній базі даних ...
wallyk

Я думаю, що це не набрало жодних голосів, оскільки це не пов’язано безпосередньо з початковим питанням щодо проектування бази даних, але я принаймні повинен сказати, що навіть ця „дотична” відповідь лише підкреслює абсурдність підходу підрядника. (Крім того, я думаю, що "Відсутність голосів" відтепер слід замінити на "Z".)
Борис Миколайович

Єдина відповідь на питання.
Піндатюх
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.