Database design 可空外键错误实践?
假设您有一个带有客户Id外键的表Orders。现在,假设您要添加一个没有客户Id的订单(这是否可行是另一个问题),您必须将外键设置为NULL。。。这是一种糟糕的做法,还是您更愿意使用订单和客户之间的链接表?虽然关系是1到n,但链接表将使其成为n到n。另一方面,有了链接表,我再也没有那些空值了 实际上,数据库中不会有很多NULL,因为外键为NULL的记录只是暂时的,直到添加订单的客户为止 (就我而言,这不是订单和客户)Database design 可空外键错误实践?,database-design,Database Design,假设您有一个带有客户Id外键的表Orders。现在,假设您要添加一个没有客户Id的订单(这是否可行是另一个问题),您必须将外键设置为NULL。。。这是一种糟糕的做法,还是您更愿意使用订单和客户之间的链接表?虽然关系是1到n,但链接表将使其成为n到n。另一方面,有了链接表,我再也没有那些空值了 实际上,数据库中不会有很多NULL,因为外键为NULL的记录只是暂时的,直到添加订单的客户为止 (就我而言,这不是订单和客户) 编辑:关于要链接到的未分配客户呢?我看不出有什么问题,它只是一个可选的n-1关
编辑:关于要链接到的未分配客户呢?我看不出有什么问题,它只是一个可选的n-1关系,外键中用null表示。否则,如果放置链接表,则必须管理它不会成为n-n关系,因此会造成更多麻烦。对于可选的多对一关系,可为空的FK完全可以。不,可为空的FK没有问题。当FK指向的实体与主键引用表处于(零或一对(1或多)关系时,这是常见的
例如,如果表中同时具有物理地址和邮寄地址属性(列),并且FKs指向地址表。当实体只有一个邮政信箱(邮寄地址)时,您可以将物理地址设置为空,当邮寄地址与物理地址相同(或不相同)时,可以将邮寄地址设置为空。使用空将是清理未完成订单的好方法:
SELECT * FROM `orders`
WHERE `started_time` < (UNIX_TIMESTAMP() + 900) AND `customer_id` IS NULL
从订单中选择*`
其中'started\u time'<(UNIX\u TIMESTAMP()+900)和'customer\u id'为空
上面显示的订单超过15分钟,没有相关的客户ID。使用链接表可能是一个更好的选择。至少它不违反规范化(Boyce Codd范式)。然而,我倾向于务实。如果这些空值很少,而且它们只是临时值,我认为应该跳过链接表,因为它只会增加方案的复杂性
在旁注上;使用链接表不一定是n到n,如果在链接表中使用指向orders表的外键作为该链接表中的主键,则关系仍然是1..n。每个订单在该链接表中只能有一个条目。我听说有人认为可空列通常会破坏第一级规范化。但在实践中,这是非常实际的 如果您只是临时添加订单,在定义客户之前没有客户id,那么在单个事务中添加客户和订单会不会更简单,从而消除对空外键条目的需要,并避免违反您设置的任何约束或触发器 通常情况下,这种情况在web应用程序中出现,在客户定义他/她是谁之前,订单是详细的。在这些情况下,订单将保持在服务器状态或cookie中,直到提供了完整订单所需的所有状态,此时订单将持久保存到数据库中
如上所述,对于地址之类的东西,空外键是可以的。但是空的customer字段对于订单没有意义,应该加以约束。在关系模型中,可选关系绝对是可能的 可以使用null来表示没有关系。它们很方便,但它们会给你带来与null在其他地方给你带来的同样的麻烦。他们不会造成任何麻烦的一个地方是连接。外键中为null的行与引用表中的任何行都不匹配。所以它们从内部连接中退出。如果您进行外部联接,那么无论如何都要处理空值 如果您真的想避免空值(第六范式),可以分解表。两个分解表中的一个有两个外键列。一个是您拥有的可选外键,另一个是引用原始表主键的外键。现在,您必须使用约束来防止关系变成多对多,如果您希望防止这种情况发生的话
可以为空的列可以是1NF到5NF,但根据我所读的内容,不是6NF 除非你比Chris Date更清楚“第一范式的真正含义”。如果x和y都可以为null,并且确实在某些行中x和y都是
null
,那么其中x=y
不会产生true
。这毫无疑问地证明了null不是一个值(因为任何实际值总是等于自身)。由于RM规定“表的每个单元格中都必须有一个值”,任何可能包含null的东西都不是关系性的东西,因此1NF的问题甚至不会出现
我听说有人认为可空列通常会破坏一级规范化 参见上文,了解该论点背后的合理理由 但在实践中,这是非常实际的 除非你对它通常在世界其他地方引起的头痛免疫。其中一个头痛的问题(与其他
null
现象相比,这只是一个小问题)是,SQL中的其中x=y
实际上意味着,其中x不为null,y不为null,x=y
,但大多数程序员根本没有意识到这一事实,只是仔细阅读了一遍。有时没有任何伤害,有时没有
事实上,可空列违反了最基本的数据库设计规则之一:不要在一列中组合不同的信息元素。空值正是这样做的,因为它们将布尔值“this field is/not really present”和