19
Customers
 customer_id

Orders
 order_id
 customer_id fk

如果我有两个表并在 Orders 表中的 customer_id 上定义一个外键,通过允许它为空,我是说我可以有一个没有与之关联的客户的订单。因此,可空外键的概念似乎与外键的目的不一致,即强制执行此约束。

是否有一个简单的例子说明需要可空外键的情况?还是赞成允许他们的论据?

4

8 回答 8

49

想象一个包含团队 TODO 的表。如果 TODO 尚未分配给团队成员,则它user_idNULL. 如果不是NULL,则它是表的外键users

于 2009-05-29T09:47:58.980 回答
16

不,可空外键从来都不是必需的。

您始终可以规范化可选的一对多关系。以您的示例为例,您可能有以下表格:

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

这两个独特的约束确保一个订单只能属于一个客户,而不能两次属于同一客户。

您是否应该始终使这种关系正常化是另一回事。在某些情况下,非规范化可能会导致更简单的实现。

于 2009-05-29T09:58:00.863 回答
5

因此,可空外键的概念似乎与外键的目的不一致,即强制执行此约束。

外键的目的是明确概念,Orders 表中的随机整数实际上是指 Customers 表中的项目。实际上将其作为约束执行是偶然的。

于 2009-05-29T09:58:50.800 回答
3

要设置外键可为空或为空,请使用以下 sql 脚本

ALTER TABLE Return_COMMENTS MODIFY order_ID Number NULL;
于 2011-01-06T10:14:30.950 回答
1

有,做一些树结构,一个与自身相关的表。考虑一下:

table_node(node_id, parent_node_id, name)

对于根,parent_node_id 应该为空,对吧?

于 2011-11-09T02:24:06.920 回答
0

将列设置为 null 的常见设计方案是,如果您有一对多的父子关系,但子项不必存在。

当父记录(如帐户)具有可删除的子记录(如帮助请求)时,这是一个很好的用法。

您可能有一个包含最新帮助请求 ID 的 MostRecentRequest 列。当从系统中删除请求时,MostRecentRequest 列设置为 NULL,表示不存在。

另一个示例是当您希望 NULL 表示尚未为行分配父行时。也许您收到了帮助请求,并且技术人员字段上的 NULL 表示没有为请求分配技术。当您删除该技术人员时,您希望通过将值重置为 NULL 将他所有未完成的工作返回到池中。

于 2009-07-11T04:53:42.267 回答
0

我们有很多这样的东西,因为我们的应用程序是从某个事件的一些基本信息开始的,随着时间的推移,随着事件的计划更加全面,会添加更多信息。但是当添加信息时,我们要确保它满足 FK 约束。FK 用于数据完整性,但在插入初始数据时并不总是知道所有数据,因此允许使用空值。

于 2011-01-05T18:55:55.163 回答
0

还有一种情况我能想到:

在一个表中,您有一个唯一标识该记录的 ID 字段。相同的记录可能(或可能没有)有一个单亲。

包含以下列的表:

  • id 为整数,自增,不可为空
  • parentid 作为整数,可为空。

使用外键约束,您可以确保如果该字段不为空,则它引用一个有效的父项。此外,如果您尝试删除父记录而不修复子记录,则无法删除父记录。

于 2013-07-31T00:35:32.027 回答