Чи нулі в реляційній базі даних добре? [зачинено]


76

Існує думка, що нульові значення не можна допускати до реляційної бази даних. Тобто атрибут (стовпець) таблиці не повинен допускати нульових значень. Виходячи з передумов розробки програмного забезпечення, я справді цього не розумію. Здається, якщо значення null є дійсним у контексті атрибута, то це слід дозволити. Це дуже часто зустрічається в Java, де посилання на об'єкти часто є нульовими. Не маючи великого досвіду роботи з базами даних, мені цікаво, чи я щось тут не пропускаю.


технічно в СУБД розмовляти нуль не є значенням; це відсутність значення, наприклад, невідомо
Метт Рогіш

25
Існує школа думок, що схеми теж повинні бути повністю нормалізовані. Жодна школа ніколи не закінчила реальний світ. :)
Кріс Ное,

Якщо ми не повинні використовувати NULL, чому СУБД дозволяють нам взагалі використовувати NULL? У NULL немає нічого поганого, якщо ви знаєте, як з ними боротися. Створення окремих таблиць для зберігання стовпців із нульовими значеннями в кожному сценарії є надто хибним.
Пт0zenFyr

3
Нульові значення є артефактом імпедансу між СУБД та реальністю. Вони є масовим системним рухом для подолання цього імпедансу. Рішення не полягає у відмові від нулів, що є недоцільним у контексті СУБД. Рішення - нові види баз даних.
Бред Томас

По суті, імпеданс знаходиться між caos (реальністю) та потягом людини до семантики. Enteties, структури, типи або що завгодно, всі вони можуть змінитися. Майте справу з поліморфною природою будь-якого типу - майте справу з нулями.
Тесон,

Відповіді:


71

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

Це зусилля, щоб переконатися, що всі дані є дійсними та оціненими.

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

-Адам


1
Ви не можете бути в першій нормальній формі з нульовими стовпцями. Одне посилання, яке чітко про це заявляє, - це en.wikipedia.org/wiki/Database_normalization#First_normal_form "Простіше кажучи, таблиця з унікальним ключем і без будь-яких стовпців, що допускають обнулення, знаходиться в 1NF."
Адам Девіс,

4
Список літератури: CJ Date досить добре відомий у реляційних базах даних. Він є головним прихильником "нулів, які вважаються шкідливими", наприклад, див. Тут dcs.warwick.ac.uk/~hugh/TTM/Missing-info-without-nulls.pdf
MarkJ

7
Отже, якщо у вас є таблиця користувачів та стовпець дня народження, які не є обов’язковими, а всі інші стовпці є, ви створюєте таблицю днів народження? Це звучить по-справжньому безглуздо. = |
ANeves вважає, що SE є злим

2
@sr pt - Так, це нерозумно. Існує рівновага між дотриманням належних практик нормалізації та розумністю проектування баз даних. На обох кінцях є крайнощі - база даних може бути занадто нормалізованою.
Адам Девіс,

8
Мені справді цікаво, коли база даних нормалізується? Реляційний дизайн не може містити нульових значень, якщо розріджений шаблон таблиці усуває нульові значення і зберігає базу даних суто реляційною, в чому проблема? Люди згадують про об’єднання, але я б оскаржив це поняття, оскільки для відношення з двома кортежами майже нічого не потрібно для об’єднання в базову таблицю, навіть при надзвичайно великих навантаженнях. Звичайно, вплив це лише на проектну продуктивність? Люди не нормалізують бази даних, оскільки в якийсь момент стає набагато складніше проектувати та запитувати. Хоча ці зусилля слід вдосконалити, а не порушувати принципи взаємовідносин.
npeterson

40

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

  • Значення "Нічого" або "Порожній набір"
  • Немає значення, яке має сенс для цього поля.
  • Значення невідоме.
  • Значення ще не введено.
  • Значення - це порожній рядок (для баз даних, які не розрізняють нулі та порожні рядки).
  • Деякі специфічні значення програми (наприклад, "Якщо значення є нульовим, тоді використовуйте значення за замовчуванням.")
  • Сталася помилка, через що поле мало нульове значення, коли воно насправді не повинно.

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


1
Влучне зауваження. Це добре в налаштуваннях багаторівневої бази даних / програми, хоча це дозволяє програмі інтерпретувати, що означає null. Я впевнений, що DBA хотіли б мати його інакше. :)
Matias Nino,

4
Ціле число також не має чітко визначеного значення. Але ніщо не заважає вам додати такий за допомогою документації.
Джонатан Аллен

1
Інше значення - "На жаль, у моєму процесі не вдалося заповнити поле із запланованим значенням". Для полів, які є FK до набору перерахованих значень, можна додати подання NULL до цієї первинної таблиці. За допомогою цієї техніки ви все ще можете дозволити концепцію "немає даних", але будьте явними щодо цього
6eorge Jetson

1
+1, оскільки це відомий аргумент проти нульових значень у схемах баз даних, оприлюднений CJ Date (я не обов'язково з цим погоджуюсь), наприклад, його книга Вступ до систем баз даних
MarkJ,

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

28

Це залежить.

Поки ви розумієте, чому ви дозволяєте NULLs в базі даних ( вибір потрібно робити на основі кожного стовпця ) І те, як ви будете їх інтерпретувати, ігнорувати чи поводитись іншим чином, вони в порядку.

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

З іншого боку, якщо ви не дозволяєте NULL s і маєте спеціальні зарезервовані значення для певних випадків (замість прапорів), як -1 для кількості дітей, коли це насправді невідомо, вам доведеться звертатися до них подібним чином, у умови конвенцій, документація тощо.

Тож, врешті-решт, питання повинні вирішуватись із домовленостями, документацією та послідовністю.

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

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

Це нагадує, як повторювані рядки можна усунути, додавши стовпець потужності, тоді як це теоретично вирішує проблему відсутності унікального ключа, на практиці, що часом неможливо - наприклад, у великомасштабних даних. Тоді пуристи швидше пропонують замість цього замість ПК, проте думка про те, що безглуздий сурогат може утворювати частину кортежу (рядка) у відношенні (таблиці), смішна з точки зору реляційної теорії.


27

Нульові маркери в порядку. Дійсно, вони є.


технічно в СУБД, нуль не є значенням; це відсутність значення, наприклад, невідомо
Метт Рогіш

1
Виправлено. Швидка поїздка до Вікіпедії вказує, що NULL - це "маркер", а не значення.
Патрік МакЕлхейні,

1
як і більшість функцій будь-чого, нулі є прекрасними, лише якщо ви знаєте, як ними користуватися. Пам'ятайте, що для кожного рядка * кожного стовпця, що вмикає NULL, потрібен ще один біт.
dvb

46
Без пояснень ця відповідь може стати марною, якщо хтось інший висловить протилежну думку. Наприклад, якщо хтось опублікує претензію на кшталт "Нульові маркери не відповідають дійсності. Дійсно, ні." , як ця відповідь допоможе читачеві вибрати дві протилежні думки? Розглянемо редагування ІНГ його, щоб краще відповідати Як відповідати рекомендаціям
комар

Це не пояснює, що таке "маркер". (І набагато простіше чітко і правильно звертатися до нульової семантики, просто використовуючи той факт, що null - це значення, яке обробляється спеціально синтаксисом та операторами SQL
ритміка

20

Існує кілька різних заперечень проти використання NULL. Деякі заперечення засновані на теорії баз даних. Теоретично немає різниці між теорією та практикою. На практиці існує.

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

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

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

Дані не можуть бути відсутніми в місці з різних причин. Ось декілька:

  1. Дані в цьому контексті не застосовуються. наприклад, ім'я дружини / дружини самотньої особи.

  2. Користувач форми введення даних залишив поле порожнім, і програма не вимагає введення в поле.

  3. Дані копіюються в базу даних з іншої бази даних або файлу, і у джерелі відсутні дані.

  4. Існує необов’язковий зв’язок, закодований у зовнішньому ключі.

  5. Порожній рядок зберігався в базі даних Oracle.

Ось декілька вказівок щодо того, коли слід уникати НУЛЬ:

Якщо в процесі нормального очікуваного програмування, запитувачам доводиться писати багато ISNULL, NV, COALESCE або подібного коду, щоб замінити дійсне значення NULL. Іноді заміну краще робити під час зберігання, якщо те, що зберігається, є "реальністю".

Якщо підрахунки, ймовірно, будуть вимкнені, оскільки підраховано рядки, що містять NULL. Часто цього можна уникнути, просто вибравши count (MyField) замість count (*).

Ось одне місце, де ти, голі, краще звикнеш до NULLS і програмуєш відповідно: щоразу, коли ти починаєш використовувати зовнішні об’єднання, такі як LEFT JOIN та RIGHT JOIN. Вся суть позаду зовнішнього об’єднання, на відміну від внутрішнього, полягає в отриманні рядків, коли відсутні відповідні дані. Відсутні дані будуть вказані як NULLS.

Моя суть: не відкидайте теорію, не розуміючи її. Але дізнайтеся, коли відходити від теорії, а також як дотримуватися її.


Чи можете ви детальніше сказати "Існує необов’язковий зв’язок, закодований у зовнішньому ключі". будь ласка?
pingu

Можливо, гіпотетичний приклад може допомогти. Існує таблиця "Людина" з одним рядком на людину. Перший стовпець - "id", і він використовується як первинний ключ. Є стовпець під назвою "Ідентифікатор дружини". Коли є подружжя, він містить зовнішній ключ, який посилається на Person.id подружжя. Коли немає подружжя, воно містить НУЛЬ.
Уолтер Мітті

Дякуємо за оперативне роз'яснення! Чи можу я зробити тонке коригування вашого прикладу, щоб перевірити, чи буде воно все ще допустимим використанням NULL? Стіл людини з полем занять. Дійсним заняттям може бути "Священик" або "Черниця", так що для них Ідентифікатор Подружжя завжди буде НУЛЬНИМ. Коротше кажучи, чи дійсно все-таки використовувати NULL, коли не всі записи можуть мати значення, що не NULL?
pingu

1
Ваша справа виходить за рамки початкового питання. Можливо, ви захочете дослідити "четверту нормальну форму"
Уолтер Мітті

18

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

Якщо щось "не існує", вам слід використовувати NULL замість порожнього рядка або іншого виду прапора.


2
"Ви повинні бути обережними, встановлюючи для клавіш значення null ...." Стовпець первинного ключа ніколи не може мати значення NULL. Будь-який стовпець, який є частиною первинного ключа, ніколи не може мати значення NULL.
Taptronic

Більш-менш підтримуючи те, що ви сказали для акценту. ;-)
Taptronic 02

4
"Якщо щось" не існує ", вам слід використовувати NULL замість порожнього рядка або іншого типу прапора." Це повторюється
Боб Пробст,

8
Якщо чогось не вистачає, у якійсь таблиці повинен бути відсутній рядок. "NULL" - це не "відсутність", "NULL" - "будь-що". Це несе повторення.
Константин

2
Якщо чогось не вистачає, у якійсь таблиці повинен бути відсутній рядок. "NULL" - це не "відсутність", "NULL" - "будь-що". Це несе повторення. (повторення)
simon

12

Замість того, щоб писати всі випуски NULL, і тристат проти логічної логіки тощо - я запропоную цю помірковану пораду:

  1. Не дозволяйте NULL у ваших стовпцях, доки ви не додасте магічне значення для представлення відсутніх або неповних даних.

  2. Оскільки ви задаєте це запитання, ви повинні бути дуже обережними у підході до NULL. Тут багато неочевидних підводних каменів. Якщо ви сумніваєтесь, не використовуйте NULL.


9

Існує ще одна альтернатива використанню "N / A" або "N / K" або порожнього рядка - окрема таблиця.

Наприклад, якщо ми можемо чи не знати номер телефону клієнта:

CREATE TABLE Customer (ID int PRIMARY KEY, Name varchar(100) NOT NULL, Address varchar(200) NOT NULL);
CREATE TABLE CustomerPhone (ID int PRIMARY KEY, Phone varchar(20) NOT NULL, CONSTRAINT FK_CustomerPhone_Customer FOREIGN KEY (ID) REFERENCES Customer (ID));

Якщо ми не знаємо телефонний номер, ми просто не додаємо рядок до другої таблиці.


8

Я б сказав, що Nulls неодмінно слід використовувати. Не існує іншого правильного способу представити відсутність даних. Наприклад, було б неправильно використовувати порожній рядок для представлення відсутнього рядка адреси, або було б неправильно використовувати 0 для представлення відсутнього елемента даних про вік. Оскільки і порожній рядок, і 0 - це дані. Нуль - найкращий спосіб представити такий сценарій.


1
"Нуль - найкращий спосіб представити такий сценарій." Я не погоджуюсь. Враховуючи (ім'я_ім'я, середнє_ініціал, прізвище), що означає NULL у середньому_ініціалі? Не зрозуміло; або ми не знаємо, або його не існує. NULL не повідомляє нам, який саме.
Дейв

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

Ви можете мати таблицю адрес і не мати там нічого для посилання на таблицю Особи. Мені це подобається більше.
Джо Філіпс,

1
Неправда, що "не існує іншого правильного способу представити відсутність даних". Дійсно, згідно реляційної алгебри, використання нулів є неправильним. Правильним способом є наявність окремих таблиць для кожного необов’язкового поля, як пропонує Кейд. Як зазначали інші, це швидко стає громіздким.
Dour High Arch

2
В Oracle порожній рядок насправді НУЛЬ :)
Каміло Діас Репка

8

Не недооцінюйте складність, яку ви створюєте, зробивши поле NULLable. Наприклад, таке речення, де виглядає так, що воно буде відповідати всім рядкам (біти можуть бути лише 1 або 0, так?)

where bitfield in (1,0)

Але якщо бітове поле має значення NULLable, воно пропустить деякі. Або візьміть такий запит:

select * from mytable
where id not in (select id from excludetable)

Тепер, якщо виключається містить нуль та 1, це означає:

select * from mytable
where id <> NULL and id <> 1

Але "id <> NULL" є хибним для будь-якого значення id, тому це ніколи не поверне жодних рядків. Це охоплює навіть досвідчених розробників баз даних surpise.

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


Помилки та сюрпризи неминучі при програмуванні. З мого досвіду, суворе уникання NULL призводить до набагато складніших конструкцій баз даних з набагато більшою кількістю таблиць. Дозвіл NULL, коли це необхідно, порівняно менш складний і схильний до помилок.
Сем Уоткінс,

6

Це величезна банка глистів, оскільки NULL може означати так багато речей:

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

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

Це також балончик для хробаків, оскільки синтаксис SQL, необхідний для їх пошуку, відрізняється від синтаксису ненульових значень, до них важко приєднатися, і вони, як правило, не входять до записів індексу.

Через колишню причину ви збираєтеся виявити випадки, коли нуль не уникнути.

Через останню причину ви все-таки повинні зробити все, щоб мінімізувати їх кількість.

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


Хороший аргумент для дозволу зарезервованих значень для стовпців поза межами нормального діапазону стовпця. Це дозволило б нам мати різноманітну гнучкість самодокументування в дизайні стовпців з такими константами, як перелічення, що представляють "НЕВІДОМЕ", "НІ ДАТИ СМЕРТІ" тощо без нескінченних обмежень та прапорів.
Кейд Ру

1
NULL означає лише одне: "ми не маємо цих даних". Якщо для цього вам потрібні більш докладні пояснення (а це, як правило, НЕ потрібно), ви можете додати більше стовпців, щоб пояснити це.
Сем Воткінс,

@SamWatkins Я думаю, що ми маємо на увазі "підлі" по-різному.
Девід Олдрідж,

6

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

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

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

  • Нулі можуть випасти з рахунку, що може бути не семантикою, яку ви бажаєте.

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

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

  • Необов’язкові відносини, де об’єднаний об’єкт може бути присутнім, а може і не бути. Null - це єдиний спосіб представити необов’язкові відносини в стовпці зовнішнього ключа.

  • Стовпці, які, можливо, ви хочете використовувати для нульового значення, щоб відпасти від рахунків.

  • Необов’язкові числові (наприклад, валюти) значення, які можуть бути або не бути. Немає ефективного значення заповнювача для "не записано" в системах числення (особливо там, де нуль є законним значенням), тому нуль насправді є єдиним хорошим способом зробити це.

Деякі приклади місць, де ви можете уникати використання нулів, оскільки вони, ймовірно, можуть спричинити незначні помилки.

  • Значення "Not Recorded" у кодових полях з FK проти таблиці посилань. Використовуйте значення заповнювача, щоб ви (або якийсь випадковий бізнес-аналітик пішов по шляху) ненавмисно не викидали рядки з наборів результатів, виконуючи запит до бази даних.

  • Поля опису, де нічого не введено - ''для цього чудово працює нульовий рядок ( ). Це економить необхідність розглядати нулі як особливий випадок.

  • Необов’язкові стовпці у системі звітності або сховища даних. У цій ситуації складіть рядок із заповнювачем для параметра «Не записано» у вимірі та приєднайтеся до цього. Це спрощує запити та чудово грає із спеціальними інструментами звітування.

Знову ж таки, книга Челька - це хороша обробка даної теми.


5

Найкраще знати про звичайні форми - це те, що вони є путівниками, і до них не слід дотримуватися завзято. Коли світ наукових кіл стикається з реальним світом, ви рідко зустрічаєте багато вцілілих воїнів ацедемії.

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

Як друг любить говорити: "Нехай ідеальне не буде ворогом добра". Подумайте, Вольтер також сказав це. 8)


1
Влучне зауваження. Я не можу порахувати, скільки разів мені доводилося битися з DBA, тому що вони хотіли пожертвувати продуктивністю та взяти на себе ще кілька шарів накладних витрат заради драконівської нормалізації.
Matias Nino,

4

Відповідно до суворої реляційної алгебри, нулі не потрібні. Однак для будь-якого практичного проекту вони потрібні.

По-перше, багато реальних даних невідомі або не застосовуються, і нулі добре реалізують цю поведінку. По-друге, вони роблять погляди та зовнішні об’єднання набагато практичнішими.


3

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

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

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


3

Для бази даних null перекладається як "Я не маю значення для цього". Що означає, що (що цікаво), логічний стовпець, що допускає нульові значення, є цілком прийнятним і з’являється у багатьох схемах баз даних. На відміну від цього, якщо у вашому коді є логічне значення, яке може мати значення "true", "false" або "undefined", ви, швидше за все, побачите, як ваш код рано чи пізно завершується на thedailywtf :)

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


Для цього випадку я використав би логічний об’єкт.
James AN Stauffer

Для створення thedailywtf.com вам також знадобиться значення FileNotFound ;-)
kurosch

3

З нулями може бути важко працювати, але в деяких випадках вони мають сенс.

Припустимо, у вас є таблиця рахунків-фактур із стовпцем "PaidDate", що має значення дати. Що ви вводите в цю графу до сплати рахунку (якщо ви заздалегідь не знаєте, коли він буде сплачений)? Це не може бути порожній рядок, оскільки це не допустима дата. Немає сенсу давати йому довільну дату (наприклад, 1/1/1900), оскільки ця дата просто невірна. Здається, єдиним розумним значенням є NULL, оскільки воно не має значення.

Робота з нулями в базі даних має кілька проблем, але бази даних добре справляються з ними. Справжні проблеми полягають у тому, що ви завантажуєте нулі з бази даних у код програми. Тут я переконався, що справи складніші. Наприклад, у .NET дата в сильно набраному наборі даних (що імітує структуру БД) є типом значення і не може бути нульовою. Тож вам доведеться будувати обхідні шляхи.

Уникайте нульових значень, коли можете, але не виключайте їх, оскільки вони мають дійсне використання.


У мене не було б таблиці рахунків-фактур зі стовпцем "PaidDate", саме через проблему NULL. Натомість у мене були б таблиці "рахунок-фактура", "кредиторська заборгованість" та "дебіторська заборгованість" із зовнішнім ключем, що пов’язує рахунки-фактури з кредиторською заборгованістю. Це також вирішує проблему, коли рахунок-фактура оплачується кількома частинами.
benjismith

Я був би радий NULL PaidDate, немає сенсу додавати додаткові таблиці, якщо бізнес-вимоги їх не заслуговують, але це лише приклад .. Ось ще один: стовпець Nullable ExpiryDate для сторінок в системі управління вмістом. Як зазначив Джим, додавати довільну дату немає сенсу.
Нік

3

Я думаю, ви плутаєте концептуальне моделювання даних із фізичним моделюванням даних.

У CDM, якщо об’єкт має необов’язкове поле, слід підтипувати об’єкт і створити новий об’єкт, коли це поле не є нульовим. Це теорія МЧР

У фізичному світі ми робимо всілякі компроміси для реального світу. У реальному світі НУЛІ є більш ніж чудовими, вони дуже важливі


3

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

Врешті-решт, я думаю, що використання null має бути продуманим (а не за замовчуванням), щоб уникнути деяких припущень, перелічених у відповідях вище, особливо там, де NULL можна вважати "нічим" або "порожнім", "невідомим 'або' значення ще не введено '.


2

Одна проблема, якщо ви використовуєте базу даних Oracle. Якщо ви збережете порожній рядок у стовпці типу CHAR, тоді Oracle примусить значення NULL без запиту. Тож уникнути значень NULL у рядкових стовпцях в Oracle може бути досить складно.

Якщо ви використовуєте значення NULL, навчіться використовувати команду SQL COALESCE, особливо зі значеннями рядків. Потім ви можете запобігти передаванню значень NULL на вашу мову програмування. Наприклад, уявіть людину, яка має Ім'я, Ім'я та Ім'я, але Ви хочете повернути одне поле;

  SELECT FullName = COALESCE(FirstName + ' ', '') + COALESCE(MiddleName+ ' ', '') + COALESCE(FamilyName, '') FROM Person

Якщо ви не використовуєте COALESCE, якщо будь-який стовпець містить значення NULL, ви отримуєте NULL .


2

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

У реальному світі денормалізація та деякі порушення моделі є нормальними. Але загалом нульові показники є показником того, що вам слід уважніше розглянути свій загальний дизайн.

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


правда, моя реляційна алгебра / числення трохи іржава, але я хотів би побачити посилання на твердження про „нулі є незаконними в реляційній математиці” ...
Стівен А. Лоу,

Нулі не є "незаконними", але вони є непотрібними, тому що результуюча тернальна логіка може бути зведена до однозначної логіки. Слід визнати, що "можна звести до" не є "легко замінити на".
Dour High Arch

2

НУЛОВІ породи. Якби в деяких випадках це не було необхідним, SQL не мав би IS NULL і IS NOT NULL як окремих операторів. NULL - це корінь концептуального універсалу, все інше НЕ NULL. Використовуйте NULL вільно, коли можливо, що значення даних може бути відсутнім, але не пропущеним. Значення за замовчуванням можуть компенсувати NULL, лише якщо вони постійно абсолютно правильні. Наприклад, якщо у мене є однобітове поле "IsReady", можливо, цілком логічно, щоб це поле мало значення за замовчуванням false і NULL не дозволялося, але це неявно стверджує, що ми знаємощо все, що не готове, а насправді ми можемо не мати таких знань. Швидше за все, у сценарії робочого процесу той, хто вирішує, готовий чи ні, просто ще не мав можливості висловити свою думку, тому дефолт за замовчуванням насправді може бути небезпечним, змушуючи його пропустити рішення, яке, здається, було зроблено, але насправді було лише дефолтним.

як осторонь, і стосовно посилання на приклад середнього початкового, мій батько не мав по батькові, тому його середній ініціал буде NULL - не пустий, пробіл чи зірочка - за винятком армії, де його середнім початковим символом був NMI = Без середнього Початковий. Наскільки це було безглуздо?


2

Хоча технічно NULL є нормальним як значення поля, на них досить часто нарікають. Залежно від того, як дані записуються у вашу базу даних, можливо (і загальноприйняте) отримати в полі порожнє значення рядка на відміну від NULL. Отже, будь-який запит, який містить це поле як частина речення WHERE, повинен обробляти обидва сценарії, які є непотрібними натисканнями клавіш.


2

null означає відсутність значення, тоді як 0 ні, якщо ви бачите 0, ви не знаєте значення, якщо бачите нуль, знаєте, що це відсутнє значення

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


2

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

Тільки для того, щоб сказати, як ви можете мати ім’я, по батькові, прізвище для кожної людини. (Ім'я та прізвище не є обов’язковими, тоді в такому випадку для вас є NULL) та як ви можете мати факс, діловий телефон, офісний телефон для всіх у списку блогів.

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

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

Дякую Навіну


2

Моя суперечлива думка того часу - за замовчуванням дозволити NULL у стовпцях бази даних було, мабуть, найгіршим загальновизнаним дизайнерським рішенням у всіх землях RDBM. Кожен постачальник робить це, і це неправильно. NULL добре в певних, конкретних, добре продуманих випадках, але думка про те, що вам потрібно явно заборонити NULL для кожного стовпця, робить недбале обнулення більш поширеним, ніж це повинно бути.


1

Особисто я вважаю, що нулі слід використовувати лише тоді, коли ви використовуєте поле як зовнішній ключ до іншої таблиці, що символізує те, що цей запис не пов’язує ні з чим в іншій таблиці. Крім цього, я вважаю, що нульові значення насправді дуже клопітні при програмуванні логіки програми. Оскільки для більшості типів даних у більшості мов програмування немає прямого представлення нульової бази даних, це в кінцевому підсумку створює багато програмного коду для розв’язання значення цих нульових значень. Коли БД стикається з нульовим цілим числом і намагається, наприклад, додати до нього значення 1 (він же нуль + 1), база даних поверне нуль, оскільки саме так визначається логіка. Однак, коли мова програмування намагається додати нуль та 1, вона зазвичай видає виняток. Отже, ваш код в кінці завалений перевірками, що робити, коли значення дорівнює нулю,


моя мова чудова з нульовими примітивами :)
TheSoftwareJedi

1

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

У всій простоті визначте NULL і дотримуйтесь його. Я використовую це, щоб означати "значення в цьому полі на даний момент невідоме". Це означає, що і ТІЛЬКИ що. Якщо це потрібно, щоб це також означало щось інше, тоді вам слід переглянути свою модель даних.


0

Все зводиться до нормалізації порівняно з простотою використання та проблемами продуктивності.

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

Виберіть c.id, c.lastname, ....... від замовника c ліворуч приєднатися до customerphonenumber cpn на c.id = cpn.customerid ліво приєднатися до customomeraddress ca на c.id = ca.customerid ліво приєднатися customerphonenumber2 cpn2 на c. id = cpn2.customerid тощо, тощо тощо


0

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

Але що нульове середнє значення ? Ось і тертя. Це "не має значення", але існує десяток різних причин, чому там може не бути значення, і "нуль" не дає вам жодної підказки, що це означає в цьому випадку. (Ще не встановлено, не застосовується до цього екземпляру, не застосовується до цього типу, невідомо, невідомо, не знайдено, помилка, помилка програми, ...)

Це дуже часто зустрічається в Java, де посилання на об'єкти часто є нульовими.

Існує школа думок, яка каже, що нульові посилання там теж погані . Така ж проблема: що робить нульові середнє ?

IIRC, Java має як "нульовий", так і "неініціалізований" (хоча для останнього немає синтаксису). Тож Гослінг зрозумів глупоту використання "нуль" для будь-якого виду "ніякої цінності". Але чому зупинятися лише на двох ?


Нуль означає будь-яке значення null, визначене як для цього атрибута. Наприклад, я міг би визначити нульове друге ім'я як відсутнє ім'я. Але значення null має бути визначене. Це те саме, що і будь-яке інше значення. Використовуючи аргумент "що це означає", будь-яке значення є хибним. Якщо я бачу поле int, ну що означає 3? Ну ви перевіряєте документацію і бачите, що таке кодування.
Стів Куо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.