MySQL, лучше вставить NULL или пустую строку?


230

У меня есть форма на сайте, которая имеет много разных полей. Некоторые поля являются необязательными, а некоторые - обязательными. В моей БД у меня есть таблица, в которой хранятся все эти значения, лучше ли вставлять значение NULL или пустую строку в столбцы БД, в которые пользователь не помещал никаких данных?

Ответы:


220

С помощью NULLвы можете различать «положить данные» и «положить пустые данные».

Еще несколько отличий:

  • A LENGTHиз NULLis NULL, a LENGTHиз пустой строки есть 0.

  • NULLs сортируются перед пустыми строками.

  • COUNT(message)будет считать пустые строки, но не NULLс

  • Вы можете искать пустую строку, используя связанную переменную, но не для NULL. Этот запрос:

    SELECT  *
    FROM    mytable 
    WHERE   mytext = ?

    никогда не будет соответствовать NULLin mytext, какое бы значение вы ни передавали от клиента. Чтобы соответствовать NULLs, вам нужно использовать другой запрос:

    SELECT  *
    FROM    mytable 
    WHERE   mytext IS NULL

3
но какой из них вы думаете, быстрее? 0 или NULL или ""
Атул Дравид

8
в InnoDB NULL занимают меньше места
Тимо Хуовинен

37
Я думаю, что это хороший ответ, но он также полностью игнорирует элемент «наилучшей практики» вопроса и фокусируется только на тангенциально значимых фактах (порядок и длина сортировки NULL? Это не имеет значения). В большинстве типов ввода текстовых данных нет разницы между «без ответа» и «пустым ответом», поэтому я думаю, что это отличный вопрос, который заслуживает лучшего ответа.
Ник

6
NULL также отлично работают, когда установлено уникальное поле. Например, если у вас есть поле типа «Водительские права» для добавления номера 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 Guys - это элегантность динамичного человека.
максимум

9

Лучше вставить NULLдля согласованности в вашей базе данных в MySQL. Внешние ключи могут быть сохранены как, NULLно НЕ как пустые строки.

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

Смотрите также: Может ли внешний ключ быть пустым и / или дублировать?


В прошлом проблема с ограничениями привела меня в замешательство, поэтому я «+1» ответил на этот вопрос.
HPWD

Но если вы используете NULL, убедитесь, что вы никогда не получите пустых строк. Легко сделать со многими технологиями пользовательского интерфейса.
Tuntable

5

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

Обратите внимание, что я говорю, что вам нужно определить, как вы хотите, чтобы они отличались. Иногда имеет смысл различать их, иногда нет. Если нет, просто выберите один и придерживайтесь его. Как я уже сказал, я склоняюсь к NULL большую часть времени.

Да, и имейте в виду, что если столбец имеет значение NULL, вероятность того, что запись появится практически в любом запросе, который выбирает (имеет условие where, в терминах SQL) на основе этого столбца, если только выбор не для пустого столбца конечно.


1
... И теперь, когда я вижу ответ над собой, я думаю, что можно с уверенностью сказать, что обычное различие, о котором вы заботитесь, - это не данные, а пустые данные. :-)
Platinum Azure

1

Если вы используете несколько столбцов в уникальном индексе, и хотя бы один из этих столбцов является обязательным (т. Е. Обязательным полем формы), если вы установите для других столбцов индекса значение NULL, вы можете получить дублированные строки. Это потому, что значения NULL игнорируются в уникальных столбцах. В этом случае используйте пустые строки в других столбцах уникального индекса, чтобы избежать дублирования строк.

КОЛОННЫ В УНИКАЛЬНОМ ИНДЕКСЕ:
(event_type_id, event_title, дата, местоположение, URL)

ПРИМЕР 1:
(1, «Барбекю», «2018-07-27», ноль, ноль)
(1, 'BBQ', '2018-07-27', null, null) // разрешено и продублировано.

ПРИМЕР 2:
(1, «Барбекю», «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.