Коли використовувати NULL, а коли використовувати порожній рядок?


82

Мене цікавлять в основному MySQL та PostgreSQL, але ти можеш відповісти на наступне:

  • Чи є логічний сценарій, в якому було б корисно відрізнити порожній рядок від NULL?
  • Які будуть наслідки для фізичного зберігання для зберігання порожнього рядка як ...

    • НУЛЬ?
    • Порожня рядок?
    • Ще одне поле?
    • Іншим способом?

Відповіді:


67

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

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


2
+1 дуже мало дбаючих коли-небудь потрібно турбуватися про різницю швидкості / розміру використання NULLчи ні
Патрік

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

6
Видатний - NULL невідомий, порожня рядок була вказана.
ScottCher

@Larry, який вплив на продуктивність? Як продуктивність змінюється в залежності від таблиць багатьох команд проти таблиць з багатьма рядками?
Shimmy

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

25

Я не знаю про MySQL та PostgreSQL, але дозвольте мені трохи поставитися до цього.

Є одна СУБД, а саме Oracle, яка не дозволяє обирати користувачів між NULL та ''. Це наочно демонструє, що не потрібно розрізняти обидва. Є деякі дратівливі наслідки:

Ви встановите varchar2 до порожнього рядка, як це:

Update mytable set varchar_col = '';

наступне призводить до того ж результату

Update mytable set varchar_col = NULL;

Але для вибору стовпців, де значення порожнє або NULL, потрібно використовувати

select * from mytable where varchar_col is NULL;

Використання

select * from mytable where varchar_col = '';

є синтаксично правильним, але він ніколи не повертає ряд.

З іншого боку, при об'єднанні рядків в Oracle. NULL вархари трактуються як порожні рядки.

select NULL || 'abc' from DUAL;

врожайність абс . Інші СУБД повертають NULL у цих випадках.

Коли ви хочете чітко виразити, що присвоєно значення, вам доведеться використовувати щось на зразок ''.

І вам потрібно переживати, чи не обрізка не порожніх результатів у NULL

select case when ltrim(' ') is null then 'null' else 'not null' end from dual

Це робить.

Тепер дивимось на СУБД, де '' не ідентично NULL (наприклад, SQL-сервер)

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



17

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

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


7
Якщо користувач вирішив не надавати гендерну категорію, обов'язково слід зберігати "Відхилено надавати". NULL неоднозначний; це також може означати, що "клієнта не запитували", "клієнта ототожнюють із статтю, яка не в нашому списку" тощо.
Jon of All Trades

8

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

Існують також деякі відмінності щодо значень реляційної алгебри та значень NULL: NULL! = NULL, наприклад.


4
Насправді це не так, що NULL! = NULL, тому що це NULL. ;-)
Пітер Ейзентрав

1
Зауважте, що MS SQL не дотримується цього правила: кілька значень NULL порушують UNIQUEобмеження. На щастя, починаючи з 2008 року ви можете використовувати відфільтрований індекс для правильної поведінки.
Йон усіх торгів

6

Ви також можете врахувати критику Дати щодо NULL та проблеми 3VL в SQL та реляційній теорії (і критика Рубінсона щодо критики Дати, Нулів, Трицінній логіки та Неоднозначності в SQL: Критика дати дати в критиці ).

Обидва посилаються і обговорюються по довжині у пов'язаному потоці SO, Параметри для усунення стовпців NULLable з моделі БД .


4

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

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


питання стосується NULL проти порожнього рядка (у стовпці, що зводиться, IMO), а не NULL vs NOT NULL, чи не так?
Ган

частина запитання про зберігання наштовхнула мене на думку, що він може замислюватися і про Null / Not Null
Патрік

або @ будь-який інший, що стосується значення NULL проти NOT NULL, ви можете посилатися на це: dba.stackexchange.com/q/63/107
Gan

2

Довелося працювати з Oracle ( що не дозволяє вам розмежуватись ), я прийшов до такого висновку:

  • З логічного POV це не має значення. Я справді не можу придумати переконливий приклад, коли розмежування між NULL та нульовою довжиною string додає будь-яке значення в СУБД.

  • Звідси випливає: У вас є або NULLздатний стовпець, який не дозволяє нульового значення ''(рішення Oracle-ish), або NOT NULLстовпець, який дозволяє нульове значення.

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

Примітка. Щоб повернутися до мого досвіду Oracle: Скажіть, що ви хочете створити запит на запит пошуку. Якщо ви використовуєте, ''ви можете просто генерувати, WHERE columnX = <searchvalue>і це буде працювати для пошуку рівності. Якщо ви використовуєте, NULLви повинні робити WHERE columnX=<searchvalue> or (columnX is NULL and serchvalue is NULL). Ба! :-)


2

Вони також відрізняються з точки зору дизайну:

напр

CREATE TABLE t (
    id INTEGER  NOT NULL,
    name CHARACTER(40),
    CONSTRAINT t_PK PRIMARY KEY (id)
);

CREATE UNIQUE INDEX t_AK1 ON t (name);

Виглядає як:

 \d t
          Table "public.t"
 Column |     Type      | Modifiers
--------+---------------+-----------
 id     | integer       | not null
 name   | character(40) |
Indexes:
    "t_pk" PRIMARY KEY, btree (id)
    "t_ak1" UNIQUE, btree (name)

Дозволяє вставити деякі дані:

op=# insert into t(id, name ) values ( 1, 'Hello');
INSERT 0 1

op=# insert into t( id, name) values ( 2, '');
INSERT 0 1

op=# insert into t( id, name) values ( 3, '');

ERROR:  duplicate key value violates unique constraint "t_ak1"

Тепер спробуємо з null:

op=# insert into t( id, name) values (4, null );

INSERT 0 1

op=# insert into t( id, name) values (5, null);

INSERT 0 1

Це дозволено.

Soooooo: нулі не є тривіальними рядками і не зворотними.

Ура


1

Якщо говорити про теорію, то правила Кодда говорять про те, що RDBMS повинні ставитися до NULLцінностей особливим чином.

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

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