MySQL, краще вставити NULL або порожню рядок?


230

У мене є форма на веб-сайті, в якій багато різних полів. Деякі поля необов’язкові, а деякі - обов’язкові. У моїй БД є таблиця, у якій є всі ці значення, чи краще вводити значення NULL або порожній рядок у стовпці БД, де користувач не вводив жодних даних?

Відповіді:


220

За допомогою NULL ви можете розрізняти "ставити без даних" і "ставити порожні дані".

Ще кілька відмінностей:

  • A LENGTHof NULLis NULL, a LENGTHпорожній рядок є 0.

  • NULLs сортуються перед порожніми рядками.

  • COUNT(message)буде рахувати порожні рядки, але не NULLs

  • Ви можете шукати порожній рядок за допомогою зв'язаної змінної, але не для NULL. Цей запит:

    SELECT  *
    FROM    mytable 
    WHERE   mytext = ?

    ніколи не буде відповідати NULLін mytext, незалежно від значення ви передаєте від клієнта. Щоб відповідати NULLs, вам доведеться використовувати інший запит:

    SELECT  *
    FROM    mytable 
    WHERE   mytext IS NULL

3
але який ви думаєте швидше? 0 або NULL або ""
Atul Dravid

8
в InnoDB NULL зайняли менше місця
Тимо Хуовінен

37
Я думаю, що це нормальна відповідь, але він також повністю ігнорує елемент "найкращої практики" питання і фокусується лише на дотично важливих фактах (NULL порядок сортування та довжина? Це не має значення). У більшості типів вхідних текстових даних є НЕ різниця між «немає відповіді» та «порожній відповідь», так що я думаю , що це велике питання , який заслуговує кращої відповіді.
Нік

6
NULL також чудово працюють, коли встановлено поле UNIQUE. Наприклад, якщо у вас є поле типу "Водійське посвідчення", щоб додати номер DL-адреси особи, а хлопець цього не має. Оскільки це унікальне поле, перша особа без DL-номера буде додана, але не наступна, оскільки це призведе до помилки унікального обмеження. Отже, NULL краще.
Сайфур Рахман Мохсін

1
@Quassnoi ах вибачте ... Я мав на увазі, чому це погана практика встановлювати посвідчення водійських номерів як унікальне ...?
cedbeu

44

Одне, що слід врахувати, якщо ви коли-небудь плануєте перемикати бази даних, - це те, що Oracle не підтримує порожні рядки . Вони перетворюються в NULL автоматично, і ви не можете запитувати їх за допомогою подібних пропозицій WHERE somefield = ''.


11
Це звучало для мене неймовірно рибно, навіть на вашому посиланні, тому я спробував це. Нульове поле, встановлене на '', оракул його ігнорує. Довжина звітів як нульова, а не 0. Це просто неправильно. Має бути якийсь шлях до цього. Думаю, я опублікую це як інше питання.
Стів Б.

1
Steve B.: Див це питання: stackoverflow.com/questions/1171196 / ...
Quassnoi

Дякую за довідку, хоча я досі не розумію міркування. Опубліковано як stackoverflow.com/questions/1268177/…
Стів Б.

Можливо, варто оновити відповідь, щоб включити інформацію за посиланням, яке розмістив Quassnoi
SamuelKDavis

7
Peoplesoft (з Oracle DB) використовує єдиний пробіл для позначення порожнього значення. Неймовірно дурний. Вони також використовують 0,00025 для позначення 0 для FTE, оскільки 0 заборонено. У цьому продукті було зроблено чудовий вибір.
JP Duffy

9

Варто пам’ятати, що NULL може зробити ваші кодові шляхи набагато складнішими. Наприклад, у Python більшість адаптерів бази даних / ORM відображаються NULLв None.

Отже, такі речі:

print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow

це може призвести до "Привіт, жодного Джо Доу!" Щоб уникнути цього вам потрібно щось подібне до цього коду:

if databaserow.title:
    print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow
else:
    print "Hello, %(firstname) %(lastname)!" % databaserow

Що може зробити речі набагато складнішими.


25
На мою думку, зловживання вашою базою даних для «виправлення» помилок у вашому коді чи рамках - це (дуже) погана практика кодування. Коли немає даних, ви просто повинні вставити NULL та бути послідовними у використанні. В іншому випадку потрібно використовувати такі операції, як: if (myString == null || myString = ""). Якщо об’єкт не встановлений або визначений у вашому коді, ви також використовуєте NULL замість якогось "заповнювача" (який, на мою думку, порожній рядок).
Гертян

5
Дуже залежить від вашої мови вибору. У Python "якщо не myString:" тести для None та "". Мабуть, головним чином, питання культури. "Погана практика" Java-хлопців - це динамічна елегантність людини.
макс

9

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

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

Дивіться також: Чи може іноземний ключ бути NULL та / або дублювати?


Проблема з обмеженнями спонукала мене раніше, тому я "поставив" +1 цю відповідь.
HPWD

Але якщо ви використовуєте NULL, переконайтеся, що ви ніколи не стикаєтесь і з порожніми рядками. Легко це зробити з багатьма технологіями інтерфейсу.
Tuntable

5

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

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

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


1
... І тепер, коли я бачу відповідь над собою, я думаю, що можна з упевненістю сказати, що звичайна диференціація, про яку ви б піклувались, - це не дані проти порожніх даних. :-)
Platinum Azure

1

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

КОЛИНИ В УНІКАЛЬНОМ ІНДЕКСІ:
(event_type_id, event_title, дата, місцезнаходження, URL)

ПРИКЛАД 1:
(1, 'BBQ', '2018-07-27', null, null)
(1, 'BBQ', '2018-07-27', null, null) // дозволено і дублюється.

ПРИКЛАД 2:
(1, 'BBQ', '2018-07-27', '', '')
(1, 'BBQ', '2018-07-27', '', '') // НЕ дозволено, оскільки він дублюється.

Ось кілька кодів:

CREATE TABLE `test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `event_id` int(11) DEFAULT NULL,
  `event_title` varchar(50) DEFAULT NULL,
  `date` date DEFAULT NULL,
  `location` varchar(50) DEFAULT NULL,
  `url` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `event_id` (`event_id`,`event_title`,`date`,`location`,`url`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Тепер вставте це, щоб побачити, що це дозволить дублювати рядки:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

Тепер вставте це і переконайтеся, що це не дозволено:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

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

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