Любой пример необходимого внешнего ключа, который может иметь значение NULL? - PullRequest
18 голосов
/ 29 мая 2009
Customers
 customer_id

Orders
 order_id
 customer_id fk

Если у меня есть две таблицы и я определяю внешний ключ для customer_id в таблице «Заказы», ​​допустив, чтобы он был нулевым, я говорю, что у меня может быть заказ, с которым не связан клиент. Таким образом, понятие обнуляемого внешнего ключа противоречит цели внешнего ключа, который заключается в применении этого ограничения.

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

Ответы [ 8 ]

48 голосов
/ 29 мая 2009

Представьте себе таблицу, в которой хранятся ТОДО команды. Если TODO еще не назначен члену команды, его user_id равно NULL. Если это не NULL, это внешний ключ к таблице users.

16 голосов
/ 29 мая 2009

Нет, внешние ключи, которые могут иметь значение NULL, никогда не нужны необходимо .

Вы всегда можете нормализовать необязательные отношения 1-много. Принимая ваш пример, вы можете иметь следующие таблицы:

Customers: customer_id, ...
Orders: order_id, ...
OrdersCustomers: order_id, customer_id
  UNIQUE(order_id)

Два уникальных ограничения гарантируют, что один заказ может принадлежать только одному клиенту, а не одному и тому же клиенту дважды.

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

5 голосов
/ 29 мая 2009

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

Цель внешнего ключа - сделать явное понятие случайным целым числом в таблице «Заказы», ​​фактически ссылающимся на элемент в таблице «Клиенты». Фактически соблюдение этого в качестве ограничения является случайным.

3 голосов
/ 06 января 2011

Чтобы установить внешний ключ, обнуляемый или нулевой, используйте ниже sql script

ALTER TABLE Return_COMMENTS MODIFY order_ID Number NULL;
1 голос
/ 09 ноября 2011

есть, составьте какую-то древовидную структуру, таблицу, которая связана с самим собой. Учтите это:

table_node(node_id, parent_node_id, name)

Для корня parent_node_id должен быть нулевым, верно?

0 голосов
/ 31 июля 2013

Есть еще одна ситуация, о которой я могу подумать:

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

Таблица со следующими столбцами:

  • идентификатор как целое число, автоинкремент, не обнуляемый
  • Парентид как целое число, обнуляемое.

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

0 голосов
/ 05 января 2011

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

0 голосов
/ 11 июля 2009

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

Когда родительская запись (например, учетная запись) имеет дочерних элементов, которые можно удалить (например, запросы на помощь), это хорошее использование.

Возможно, у вас имеется столбец для MostRecentRequest, в котором указан идентификатор самого последнего запроса о помощи. Когда запрос удален из системы, столбцу MostRecentRequest присваивается значение NULL, что означает, что его нет.

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

...