可空的外键坏习惯?

比方说,你有一个表的订单与客户ID的外键。 现在,假设你想添加一个没有客户ID的订单(是否应该是另一个问题),你将不得不使外键为NULL …是不好的做法,还是宁愿使用链接表订单和客户? 尽pipe关系是1到n,但链接表会使它成为n到n。 另一方面,用链接表,我没有那些NULLS了…

在数据库中实际上不会有太多的NULL,因为外部键值为NULL的logging只是暂时的,直到添加了订单的客户。

(在我的情况下,这不是一个订单和一个客户)。

编辑:未分配的客户链接到什么?

有链接表可能是一个更好的select。 至less它不违反正常化BCNF (Boyce-Codd正常forms)。 不过,我赞成务实。 如果这些空值很less,而且它们只是暂时的,我认为你应该跳过链接表,因为它只增加了scheme的复杂性。

在附注中; 使用链接表并不一定使n到n,如果你在链接表中使用指向你的订单表的外键作为该链接表中的主键,关系仍然是1..n。 每个订单在该链接表中只能有一个条目。

不,可空的FK没有问题。 当FK指向的实体与主键引用的表中的(零或一)到(1或多个)关系时,这是很常见的。

例如,如果您在表中具有物理地址和邮寄地址属性(列),并将FK添加到地址表中。 当实体只有一个邮局地址(邮寄地址)时,你可以使实际地址为空来处理,而当邮寄地址与实际地址(或不是)相同时,邮寄地址可以为空。

可空列可以在1NF到5NF之间,但根据我读过的,不能在6NF。

只有当你比Chris Date更清楚“什么是第一范式的真正含义”。 如果x和y都是可以为空的,而且在某些行中x和y都是null ,那么WHERE x=y不会产生true 。 这certificate无可置疑的是,空值不是一个值(因为任何实际值总是等于它本身)。 而且由于RM规定“在表格的每个单元格中都必须有一个值”,所以任何可能包含空值的东西都不是一个关系的东西,因此1NF的问题甚至不会出现。

我听说它认为,可空列总体上是打破了正常化的第一个程度。

请参阅上文,了解这个论点的正确理由。

但实际上这是非常实用的。

只有当你不受通常在世界其他地方引起的头痛的困扰的时候。 一个这样的头痛(这只是一个小问题,相对于其他的null现象)是这样一个事实,即SQL中的WHERE x=y实际上意味着WHERE x is not null and y is not null and x=y ,但是大多数程序员只是简单的不知道这个事实,只是读了一下。 有时没有任何伤害,其他时间没有。

事实上,可空列违反了最基本的数据库devise规则之一:不要在一列中组合不同的信息元素。 因为它们把布尔值“这个字段是/不是真的存在”与实际值相结合,所以空值就是这样做的。

我看不出有什么问题,它只是一个可选的n-1关系,在外键中将用空值表示。 否则,如果你把你的链接表,那么你将不得不pipe理,它不会成为一个关系,所以造成更多的麻烦。

可选关系在关系模型中是绝对可能的。

你可以使用空值来表示没有关系。 他们很方便,但他们会导致你在其他地方导致你的头痛。 一个他们没有任何麻烦的地方是join。 外键中有空的行不匹配被引用表中的任何行。 所以他们退出了一个内部连接。 如果你做外连接,你将会处理空值。

如果你真的想避免空值(第六范式),你可以分解表。 两个分解的表之一有两个外键列。 一个是您拥有的可选外键,另一个是引用原始表的主键的外键。 现在你必须使用约束来防止关系变成多对多,你想要防止这种关系。

使用NULL将是清理不完整的订单的好方法:

 SELECT * FROM `orders` WHERE `started_time` < (UNIX_TIMESTAMP() + 900) AND `customer_id` IS NULL 

以上将显示超过15分钟的订单,但没有相关的客户ID。

可选的多对一关系的可空FK是完全正确的。

如果您只是在客户定义之前临时添加订单而没有客户ID,那么在单个事务中添加客户和订单并不是一件简单的事情,从而消除了对NULL外键input的需求,避免了任何约束或触发你设置了被侵犯?

通常情况下,这种情况出现在networking应用程序中,在客户定义他/她之前,订单是详细的。 在这种情况下,订单被保存在服务器状态或cookie中,直到提供完整订单的所有必要状态,在这一点上订单被持久保存到数据库中。

如上所述,NULL外键可以用于地址之类的东西。 但是,一个NULL客户字段对于一个订单是没有意义的,应该受到限制。

你总是可以添加一个虚假的行到你的Customer表中,像Id = -1和CustomerName ='Unknown',然后在通常将你的CustomerId设置为NULL的情况下将它设置为-1。

这可以让你没有可空的FK,但仍然表示缺乏适当的数据(并且会从不知道如何处理NULL的下游用户中保存)。

我听说它认为,可空列总体上是打破了正常化的第一个程度。 但实际上这是非常实用的。

是的,有什么不对劲。 如果它是可空的,它不是一个外键。 它的数据库devise由代码。 也许你做一个零链接未分配。 或“未分配”,如果您使用字符列。 保持数据的完整性100%。