Обнуляемый внешний ключ плохая практика?
Допустим, у вас есть таблица заказов с внешним ключом для идентификатора клиента. Теперь предположим, что вы хотите добавить Заказ без Идентификатора Клиента (возможно, это еще один вопрос), вам нужно сделать внешний ключ NULL... Это плохая практика, или вы предпочитаете работать с таблицей ссылок между Заказы и клиенты? Хотя отношение равно 1 к n, таблица ссылок сделает его n к n. С другой стороны, с таблицей ссылок у меня больше нет этих NULL...
На самом деле в базе данных не будет много NULL, потому что запись с внешним ключом для NULL просто временно, пока клиент для заказа не будет добавлен.
(В моем случае это не Заказ, а Клиент).
РЕДАКТИРОВАТЬ: А как насчет неназначенного Клиента, чтобы ссылаться?
11 ответов
Наличие таблицы ссылок, вероятно, является лучшим вариантом. По крайней мере, это не нарушает нормализацию BCNF (нормальная форма Бойса-Кодда). однако я предпочел бы быть прагматичным. Если у вас очень мало этих нулевых значений, и они являются только временными, я думаю, вам следует пропустить таблицу ссылок, поскольку это только усложняет схему.
На боковой ноте; использование таблицы ссылок не обязательно делает его n n, если вы в таблице ссылок используете внешний ключ, который указывает на вашу таблицу заказов, в качестве первичного ключа в этой таблице ссылок, отношение по-прежнему равно 1..n. В каждой таблице ссылок может быть только одна запись.
Нет Нет ничего плохого в Nullable FKs. Это часто встречается, когда объект, на который указывает FK, находится в (от нуля или одного) до (1 или много) взаимосвязи с таблицей, на которую ссылается первичный ключ.
Примером может быть, если у вас есть физический адрес и атрибут почтового адреса (столбец) в таблице с FK для таблицы адресов. Вы можете сделать физический адрес доступным для обработки, если у объекта есть только почтовый ящик (почтовый адрес), а почтовый адрес можно обрабатывать, если почтовый адрес совпадает с физическим адресом (или нет).
Nullable столбцы могут быть в 1NF до 5NF, но не в 6NF в соответствии с тем, что я прочитал.
Только если вы знаете лучше, чем Крис Дэйт, "что на самом деле означает первая нормальная форма". Если x и y оба обнуляются, и действительно в некоторой строке x и y оба null
, затем WHERE x=y
не дает true
, Это вне разумных сомнений доказывает, что ноль не является значением (потому что любое реальное значение всегда равно самому себе). А так как RM предписывает, что "в каждой ячейке таблицы должно быть значение", любая вещь, которая может содержать нули, не является реляционной, и, таким образом, вопрос 1NF даже не возникает.
Я слышал, что аргументы о том, что столбцы Nullable в целом нарушают первую степень нормализации.
Смотрите выше для обоснованной причины этого аргумента.
Но на практике это очень практично.
Только если вы невосприимчивы к головным болям, которые они обычно вызывают во всем остальном мире. Одна такая головная боль (и это только незначительная, по сравнению с другими null
феноменами) является тот факт, что WHERE x=y
в SQL на самом деле означает WHERE x is not null and y is not null and x=y
Но большинство программистов просто не знают об этом и просто перечитывают его. Иногда без вреда, иногда нет.
Фактически, столбцы, которые могут содержать пустые значения, нарушают одно из самых фундаментальных правил проектирования базы данных: не объединяйте отдельные информационные элементы в одном столбце. Нули делают именно это, потому что они объединяют логическое значение "это поле действительно присутствует / не присутствует" с фактическим значением.
Я не вижу ничего плохого в том, что это просто необязательное отношение n-1, которое будет представлено нулем во внешнем ключе. В противном случае, если вы разместите свою таблицу ссылок, вам придется решить, что она не станет nn-отношением, что вызовет еще больше проблем.
Необязательные отношения определенно возможны в реляционной модели.
Вы можете использовать нули, чтобы выразить отсутствие отношений. Они удобны, но они вызовут у вас те же головные боли, что и нули, вызывающие вас в другом месте. Единственное место, где они не доставляют неприятностей - это соединения. Строки с нулевым значением во внешнем ключе не соответствуют ни одной строке в ссылочной таблице. Таким образом, они выпадают из внутреннего соединения. Если вы делаете внешние соединения, вы все равно будете иметь дело с нулями.
Если вы действительно хотите избежать нулей (6-ая нормальная форма), вы можете разложить таблицу. Одна из двух разложенных таблиц имеет два столбца внешнего ключа. Одним из них является необязательный внешний ключ, который у вас есть, а другим - внешний ключ, ссылающийся на первичный ключ исходной таблицы. Теперь вы должны использовать ограничения, чтобы отношения не становились многими ко многим, если вы хотите предотвратить это.
Использование NULL было бы хорошим способом убрать неполные заказы:
SELECT * FROM `orders`
WHERE `started_time` < (UNIX_TIMESTAMP() + 900) AND `customer_id` IS NULL
Выше будут отображаться заказы старше 15 минут без идентификатора клиента.
Если вы добавляете заказ только временно без идентификатора клиента до тех пор, пока клиент не будет определен, не будет ли проще добавить клиента и заказ в одной транзакции, тем самым устраняя необходимость ввода внешнего ключа NULL и избегая любых ограничений или триггеров вы настроили быть нарушенным?
Обычно такая ситуация возникает в веб-приложениях, где заказ детализируется до того, как клиент определит, кто он / она. И в этих ситуациях заказ сохраняется в состоянии сервера или в файле cookie до тех пор, пока не будет предоставлено все необходимое состояние для полного заказа, после чего заказ сохраняется в базе данных.
Внешние ключи NULL подходят для таких вещей, как адреса, как упоминалось выше. Но поле NULL customer не имеет смысла для заказа и должно быть ограничено.
Вы всегда можете добавить искусственную строку в свою таблицу Customer, например, Id=-1 и CustomerName = 'Unknown', а затем в тех случаях, когда вы обычно устанавливаете CustomerId в Order NULL, установите значение -1.
Это позволяет вам не иметь обнуляемых FK, но при этом все равно представлять недостаток данных (и избавит вас от последующих пользователей, не знающих, как обращаться с NULL).
Обнуляемые FKs для необязательных отношений "многие к одному" вполне подойдут.
Да, что-то не так. Это не внешний ключ, если его можно обнулять. Дизайн базы данных по коду. Может быть, вы делаете нулевую ссылку на неназначенные. или "Unassigned", если вы используете символ col. Сохраняйте целостность ваших данных на 100%.
Я слышал, что аргументы о том, что столбцы Nullable в целом нарушают первую степень нормализации. Но на практике это очень практично.