1

我的问题与 0 到许多关系有关。例如,如果您有一个客户表和一个订单表,一个客户可以有一个或多个订单,而一个订单可以有零个或一个客户。它可以为零的原因是因为订单是从未保存客户详细信息的旧订单系统导入的。

我相信有两种选择:

  1. 对于没有客户的订单,将 CustomerID(Orders 表中的外键)设置为 null。
  2. 在包含 CustomerID 和 OrderID 的客户和订单之间创建联结表。但是,我认为联结表专门用于多对多关系

哪个是最好的选择?

编辑:

我发现了以下帖子并同意 Molf 的回答,这是我原来问题中的选项 2:任何必要的可为空外键的示例?.

4

2 回答 2

3

我不会创建联结表,除非您最初将订单键限制为唯一和/或预见到关系变为多对多。

具有普通单个 FK 的更简单的两表选项中的问题是您是否希望在订单行中允许 NULL 客户 FK。当然可以不允许这样做(出于明显的良好参考完整性原因),并有一个“未知客户”客户,用于所有具有未知客户的旧订单。以一种非常好的方式,这将 NULL (可能被误解)替换为明确的内容(对“未知客户”的引用,一旦创建或识别出真正的客户就可以随时修复)。

我会强烈考虑这一点,因为人们希望遗留数据将是您未来数据中相对较小的一部分,并且您希望确保典型案例的数据中有尽可能多的 RI(所有未来的案例都必须确定一个客户在订单创建期间),同时仍然适应遗留案例(随着时间的推移,这些案例在您的数据世界中的重要性会降低)

于 2012-05-10T19:37:18.527 回答
1

这里有一个概念上令人困惑的冗余,尽管您可能对此有要求。如果您从头开始执行此操作,您可以简单地让 Orders 具有 Customer.CustomerID 的 NULLable FK。这将满足有 1 个客户 - 许多订单和 1/0 个客户的订单。您也可以通过使用联结表来做到这一点,因为这在技术上是多对多的关系。

最好的选择将取决于您如何查询数据。例如,对 Orders 表进行分析型查询可能更方便

在没有客户的情况下寻找订单

SELECT SUM(CASE WHEN customer iS NULL THEN 1 ELSE 0 END) FROM Orders

对比

SELECT SUM(CASE WHEN j.oid iS NULL THEN 1 ELSE 0 END) FROM 
Orders o  LEFT OUTER JOIN Junction j 
WHERE o.o_id = j.o_id

您可以提出其他示例也可以进行更清洁、更有效的查询。

于 2012-05-10T18:53:29.343 回答