假设我有一个CustomerOrder
表和一个RentalEquipment
表。
客户可以租用其中一个RentalEquipment
,并且CustomerOrder
内会记录该独特的租赁设备。
由于关系为1:1
(客户需要租用2台设备,必须订购2台),哪两台都应包含外键?
请考虑以下事项:
答案 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)并找到强制执行(2)的方法。
考虑以下模型:
[From, To]
是租房的时间段。
{CustomerId, From}
确保客户无法同时开始租用(相同或不同的设备)两次。{RentalEquipmentId, From}
确保一件设备无法同时开始租给(相同或不同的客户)两次。不幸的是,两种约束只能及时时刻,并且都不能保证时间期间不会重叠(换句话说:它们不会{{ 1}}考虑到)。您需要找到一种方法来防止任何给定To
的时间段[From, To]
重叠(对于任何给定的CustomerId
都是相同的。)
如果运气好,您的DBMS可以为您做到这一点(请参阅PostgreSQL下的exclusion constraint)。否则,您可以使用触发器强制执行(但要小心锁定,以避免竞争条件)。