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

tug*_*erk 14 sql-server-2008 database-design sql-server sql-server-2008-r2

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

我还有另一张桌子,Payments里面有付款细节。但我在这里对如何构建它有疑问。

由于我有多种产品类型,并且客户可能同时订购多种产品,因此我需要将这三个订单表关联到Payments表。

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

我的问题是nullable,从长远来看,这些FK 专栏是否会让我头疼?一般来说,在表上拥有可为空的 FK 列是否被认为是一种不好的做法?

gbn*_*gbn 14

我会质疑为什么你有OrdersForProductX表格
你问的 FK 问题有可能被设计出来......

如果这些表具有相同的结构,那么您只需要ProductType在某个OrderProduct表上有一列。然后Payment只用一个 FK 链接到那个

如果表有不同的结构,我假设它们有一些共同的属性。所以,你可以有一个公用OrderProduct表,然后是每个产品类型的特定子表(见下文)同样,Payment只需使用一个 FK 链接到公用表

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

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

订购产品

  • 订单 ID、PK、UQ1
  • 产品类型,UQ1
  • 共同事物1
  • ...

订购产品A

  • 订单 ID、PK、FK
  • 产品类型,PK,FK,检查产品类型 = A
  • 产品AThing1
  • ...

订购产品B

  • 订单 ID、PK、FK
  • 产品类型,PK,FK,检查产品类型 = B
  • 产品BThing1
  • ...

  • @tugberk:请注意,使用这种方法,您将没有 `NULL` FK 列。 (4认同)

nvo*_*gel 5

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

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

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

外键经常用于连接和其他查询逻辑,对于认为约束有效但不知道您的特定 DBMS 所应用的逻辑的用户来说,问题更加复杂。

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

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

可空的外键是完全没有必要的。您始终可以将外键分解为新表或使用超类型/子类型模式,以便不需要空值。因此,为了简单和准确起见,最好将空值排除在外而不是将它们放入。