数据库1:1关系外键

时间:2014-05-13 15:15:45

标签: database database-design

假设我有一个CustomerOrder表和一个RentalEquipment表。

客户可以租用其中一个RentalEquipment,并且CustomerOrder内会记录该独特的租赁设备。

由于关系为1:1(客户需要租用2台设备,必须订购2台),哪两台都应包含外键?

请考虑以下事项:

  1. 客户可以退回租赁设备,以便将来随时可以使用其他客户的订单。

3 个答案:

答案 0 :(得分:1)

我要做的是为客户订单和租赁设备之间的关系创建一个单独的表 - 让我们称之为CustomerRental,这将为每个外键创建两列,并创建一个复合主键每把钥匙。这样,客户或订单的每一行都可以独立修改,而不必担心破坏它们之间的关系。

在返回的情况下,我建议创建另一个表来捕获这个想法,让我们称之为CustomerRentalStatus,将许多地方映射到:RentalStatus。以编程方式,您可以执行的操作是验证订单的租赁状态,例如"已收到","已发送","已发送","已退回"并且您可以使用修改日期列来检查上次更新状态的时间。

当然,根据应用程序的需要(yagni),您可能不希望规范化您的解决方案,在这种情况下,您可以在Orders表中有一列来捕获订单的状态

答案 1 :(得分:1)

好吧,考虑一下。 RentalEquipment是否包含CustomerOrder,或者CustomerOrder是否包含RentalEquipment?

我的猜测是它是后者,除非你有一个非常奇怪的系统。

鉴于此,CustomerOrder应包含对其包含的RentalEquipment的引用。您可以在CustomerOrder上有一个状态标志,指示订单是否仍处于打开状态,或者是否已返回RentalEquipment。

如果您想跟踪给定RentalEquipment的订单历史记录,这也是有意义的。

如果它是CustomerOrder中的外键,您可以查看您的CustomerOrders以查找历史记录。如果您将关系放在RentalEquipment中,那么您只会获得有关CurrentOrder的信息。此外,当客户退回时,您必须更新RentalEquipment记录并将FK设置为​​null。凌乱。

答案 2 :(得分:0)

这实际上不是1:1。

同一件设备可以租给多个客户,同一个客户可以租用多件设备,只要在不同的时间完成......

  1. 所以它实际上是M:N,超过数据库的生命周期
  2. 但是,在特定时间段内<1> 1
  3. 因此,您需要通过联结表来表示(1)并找到强制执行(2)的方法。

    考虑以下模型:

    enter image description here

    [From, To]是租房的时间段。

    • UNIQUE约束{CustomerId, From}确保客户无法同时开始租用(相同或不同的设备)两次。
    • UNIQUE约束{RentalEquipmentId, From}确保一件设备无法同时开始租给(相同或不同的客户)两次。

    不幸的是,两种约束只能及时时刻,并且都不能保证时间期间不会重叠(换句话说:它们不会{{ 1}}考虑到)。您需要找到一种方法来防止任何给定To的时间段[From, To]重叠(对于任何给定的CustomerId都是相同的。)

    如果运气好,您的DBMS可以为您做到这一点(请参阅PostgreSQL下的exclusion constraint)。否则,您可以使用触发器强制执行(但要小心锁定,以避免竞争条件)。