在SQL Server的表上具有多个可为空的FK是否被视为一种不好的做法


13

在SQL Server的数据库结构中,我有3种类型的产品,它们需要有关订单的不同信息。所以,我创建了一个Customers桌子,三个不同的顺序表:OrdersForProductAsOrdersForProductBsOrdersForProductCs。所有订单表在表上都有一对多的关系Customers

我还有另一个表格,Payments里面将保存付款明细。但是我在这里对如何组织感到怀疑。

因为我有多种产品类型,并且一个客户可能同时具有多个产品的订单,所以我需要将这三个订单表与Payments表相关联。

另一个问题是,客户只能订购一种产品。因此,表上的FK列Payments需要为nullable

我的问题是nullable,从长远来看,那些FK色谱柱是否会让我头疼?一般来说,在表上具有可空的FK列是否会被视为不好的做法?


2
确保包括检查约束,以便这些FK 中的至少一个不为空。
Damien_The_Unbeliever 2012年

3
一个可为空的外键太多了。
nvogel

Answers:


13

我想问问你为什么要有OrdersForProductX桌子?有
可能可以设计出你所问的FK问题...

如果这些表具有相同的结构,则只需要ProductType在某些OrderProduct表上添加一列即可。然后Payment只用一个FK链接到该链接

如果表具有不同的结构,则假定它们具有一些共同的属性。因此,您可以为OrderProduct每个产品类型创建一个公用表,然后是一个特定的子表(请参见下文)。再次,Payment只需使用一个FK链接到公用表即可

这是“超级键/子类型模式”

  • UQ1是在子类型表上使用外键的“超级键”
  • 每个子类型表上都有一个组合的PK和FK (OrderID, ProductType)
  • 每个子类型表都有一个CHECK约束来限制该表中的类型

订购产品

  • OrderID,PK,UQ1
  • 产品类型,UQ1
  • 普通事物1
  • ...

订购产品A

  • OrderID,PK,FK
  • ProductType,PK,FK,CHECK ProductType = A
  • 产品1
  • ...

订购产品B

  • OrderID,PK,FK
  • ProductType,PK,FK,CHECK ProductType = B
  • 产品B东西1
  • ...

4
@tugberk:请注意,NULL使用这种方法将没有FK列。
ypercubeᵀᴹ

“如果这些表具有相同的结构”,则它们不具有相同的结构。
tugberk

5

避免使用可为空的“外键”。它们具有多个缺点。

当外键包含null时,对引用行的约束并不总是强制执行。但是,默认行为在不同的DBMS之间不一致。一些DBMS支持配置选项来更改可为空的外键的行为,而某些则不。因此,从数据完整性的角度来看,SQL开发人员和用户可能不清楚可为空的外键约束的实际含义。在DBMS产品之间甚至使用同一产品的不同服务器之间移植数据库可能会导致不一致的结果。

数据库设计工具,集成工具和其他软件并不总是正确地支持它们,并且它们产生的结果可能是错误的。

外键经常在联接和其他查询逻辑中使用,给那些认为约束无效或不知道特定DBMS所应用的逻辑的用户增加了问题。

当外键为空时,某些允许查询重写的查询优化功能和其他优化功能可能不可用。

用逻辑术语来说,可为空的“外键”约束在逻辑上没有多大意义。根据SQL标准,即使引用的表为空,也不会违反这种约束。这与使用null的最常见的指控理由之一相矛盾-它代表“未知”情况。如果没有X的有效值,那么任何“未知” X肯定都不是有效值-但是SQL会允许它。

可空的外键是完全没有必要的。您始终可以将外键分解为新表,也可以使用超类型/子类型模式,从而不需要空值。因此,出于简单性和准确性的考虑,最好将空值留空而不是放空值。


2

我从未听说过使用可空FK列被认为是不好的做法。它们非常适合引用其他表但可能未填写的列(即,它是可选数据)。

(为什么您会认为这是个问题?)


谢谢!好吧,我对此不太确定,但是几年前我有一个类似的项目,我记得我对某些事情感到头疼。因此,正如您所看到的,我不清楚:这就是为什么我问这个问题。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.