在MySQL中实现一对一关系时,如何决定外键?

26

我有两个简单的表格"items"和"orders"。为了简单起见,假设一个物品只能在一个订单中,或者一个订单只能包含一个物品。

现在,由于可以使用简单的一对一关系来实现此操作,因此我可以执行以下操作:

我可以将订单表的主键添加到物品表中,如下所示:

//Table Items
item_id, item_name, order_id
1,        shoes,    1
2,        watch,    2

//Table Orders
order_id, customer
1,        James
2,        Rick

或者我可以像下面这样将items表的主键添加到orders表中:

//Table Items
    item_id, item_name
    1,        shoes
    2,        watch

//Table Orders
order_id, customer, item_id
1,        James,    1   
2,        Rick,     2
哪一个是正确的,为什么?有没有指南可以决定哪个键应该放在哪里?当然,在如上简单的例子中常识会起作用,但在复杂的例子中我们如何决定?

哪一个是正确的,为什么?有没有指南可以决定哪个键应该放在哪里?当然,在如上简单的例子中常识会起作用,但在复杂的例子中我们如何决定?

1个回答

29

一对一关系通常应该简单地合并成一个表。如果没有任何矛盾,一对一关系可能是未经考虑的决定的标志。

如果您确实想使用这种关系,完全由您决定放置外键在哪里。在应用外键时,您可能需要考虑可选性。然而,在MySQL中,它仍然不是真正的一对一关系,因为不支持延迟键。


同意。但是它们就不再是一对一关系了,而会变成自引用关系。 - Jay Bhatt
@JayBhatt 在上述方法中,您在哪里看到自引用关系?SRR创建层次结构,但我在那里没有看到任何关系。 - Grzegorz Piwowarek
1
@JayBhatt,如果没有延迟外键(MySQL不支持),你就不能在两个表之间建立“一对一”的关系。最好的情况是“一对零或一”——FK的放置决定了哪一边是哪一边。如果你想要真正的“一对一”,你必须在一个表中完成。 - Branko Dimitrijevic
9
有些一对一的关系是属于IS-A类型的,与此问题中给出的示例不同。在对象建模中,IS-A关系通常是类/子类模式的示例,在实体关系建模中则称为泛化/特化。在这种情况下,通常有必要像[标签:类表继承]中所示那样拆分表格。 - Walter Mitty
2
我们遇到了类似的问题,我们的问题是交易和位置之间存在一对一的关系。位置包含了交易发生的地点信息。经过进一步分析,我们得出结论:位置与交易相关联,不能独立存在。从某种意义上说,这就像一个子实体。因此,我们在位置表中使用了交易的外键。 - Shashi Jeevan M. P.
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接