Когда использовать NULL, а когда использовать пустую строку?

82

Мне интересны в основном MySQL и PostgreSQL, но вы можете ответить на следующие вопросы в целом:

  • Есть ли логический сценарий, в котором было бы полезно отличить пустую строку от NULL?
  • Каковы будут физические последствия хранения для хранения пустой строки как ...

    • ЗНАЧЕНИЕ NULL?
    • Пустой строкой?
    • Другое поле?
    • Любым другим путем?
Maniero
источник

Ответы:

67

Допустим, запись поступает из формы для сбора информации об имени и адресе. Строка 2 адреса, как правило, будет пустой, если пользователь не живет в квартире. Пустая строка в этом случае совершенно корректна. Я предпочитаю использовать NULL для обозначения того, что значение неизвестно или не указано.

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

Ларри Коулман
источник
2
+1 очень немногие dba когда-либо должны беспокоиться о разнице в скорости / размере использования NULLили нет
Патрик
28
Согласовано ... Я пытаюсь зарезервировать NULL для "not unknown" ... пустая строка - "мы знаем, что она должна быть пустой". Это особенно полезно, когда ваши данные поступают из нескольких источников
Джо
6
Выдающийся - NULL не известен, указана пустая строка.
ScottCher
@ Ларри, что влияет на производительность? Как зависит производительность от таблиц с множеством столбцов от таблиц с множеством строк?
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 varchars обрабатываются как пустые строки.

select NULL || 'abc' from DUAL;

дает abc . Другие СУБД возвращали бы NULL в этих случаях.

Если вы хотите явно указать, что значение назначено, вы должны использовать что-то вроде ''.

И вам нужно беспокоиться, приведет ли обрезка к пустым значениям в NULL

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

Оно делает.

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

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

bernd_k
источник
связанные: stackoverflow.com/questions/203493/…
Джо
17

Это зависит от домена, на котором вы работаете. NULLозначает отсутствие значения (т. е. нет значения ), а пустая строка означает, что есть строковое значение нулевой длины.

Например, скажем, у вас есть таблица для хранения данных человека, и она содержит Genderстолбец. Вы можете сохранить значения как «Мужской» или «Женский». Если пользователь может выбрать не предоставлять половые данные, вы должны сохранить их как NULL(т. Е. Пользователь не предоставил значение), а не пустую строку (поскольку нет пола со значением '').

Гань
источник
7
Если пользователь решил не указывать пол, обязательно сохраните «Отказано в предоставлении». NULL неоднозначен; это также может означать, что «клиента не спросили», «клиент идентифицирует себя с полом, которого нет в нашем списке» и т. д.
Джон на все руки
9

Стоит помнить одну вещь: если у вас есть поле, которое не является обязательным, но любые значения, которые присутствуют, должны быть уникальными, вам потребуется хранить пустые значения как NULL. В противном случае у вас будет только один кортеж с пустым значением в этом поле.

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

Мэтью Шинкель
источник
4
На самом деле это не тот случай, когда NULL! = NULL, потому что это NULL. ;-)
Питер Айзентраут
1
Обратите внимание, что MS SQL не следует этому правилу: несколько значений NULL нарушат UNIQUEограничение. К счастью, начиная с 2008 года вы можете использовать отфильтрованный индекс, чтобы получить правильное поведение.
Джон на все руки
6

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

Обе ссылки и подробно обсуждаются в связанном SO потоке, Опции для исключения столбцов NULLable из модели БД .

Abie
источник
4

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

Если вы не используете каркас или если вы используете простые SQL-операторы и обработку, я бы выбрал тот вариант, который вам проще отслеживать. Я обычно предпочитаю NULL, чтобы INSERTоператоры не утомительно забыли установить пустые поля NULL.

Патрик
источник
вопрос о NULL или пустой строке (в обнуляемом столбце, IMO), а не NULL против NOT NULL, не так ли?
Ган
часть вопроса, касающегося хранения, заставила меня подумать, что он может думать также и о Null / Not Null
Патрик
или @everyone, что касается значения NULL против NOT NULL, вы можете сослаться на это: dba.stackexchange.com/q/63/107
Ган
2

Приходясь работать с Oracle ( что не позволяет вам дифференцироваться ), я пришел к следующему выводу:

  • С логической точки зрения это не имеет значения. Я действительно не могу вспомнить убедительный пример, когда различие между NULL и строкой нулевой длины добавляет какое-либо значение в СУБД.

  • Из чего следует: У вас есть либо 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"

Теперь давайте попробуем с нулем:

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

INSERT 0 1

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

INSERT 0 1

Это разрешено

Оооочень: нули не являются ни тривиальными строками, ни обратными.

ура

Гай Биркбек
источник
1

Если говорить о теории, то правила Кодда гласят, что СУБД должна обрабатывать NULLзначения особым образом.

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

noonex
источник