弱实体的数据库建模

5

我在数据库中有两个表 ordersorderHistory

 -----------------                    -----------------------
 |  orders       |                    |  orderHistory       |
 -----------------                    -----------------------
 | orderID  (PK) |                    | historyLineID  (PK) |
 | orderDate     |                    | status              |
 | price         |                    | quantity            |
 -----------------                    -----------------------

现在,一个订单可以有多个历史记录。然而,一个历史记录不能独立存在。我听说这被称为弱实体,因此订单的PK必须是表orderHistory的PK的一部分。
问题:
1.这真的是正确的“弱实体”关系吗?还有其他方法来识别它们吗? 2.我应该将表order的PK添加到表orderHistory中并将其作为复合主键吗? 3.如果我决定向orderHistory添加新记录,如何添加新的复合键?(orderID可从订单表orders中获取,但historyLineID应自动递增。) 4.如果我决定将其建模为普通的一对多关系,仅添加orderID作为外键,那么做这样做的缺点是什么? 5.在设计中忽略弱实体是否会在以后造成任何问题,前提是所有表都处于第三正式形式?
注意:orderID和historyLineID都是代理键。
2个回答

7
一个实体不是弱实体,因为它不能独立存在,而是因为它不能被单独识别。因此,“导致”弱实体的关系称为“标识”关系。在实践中,这意味着父项的主键被迁移到子项的PK(通常是proper)子集中(术语“弱实体”通常是与主键相关定义的,尽管理论上它可以适用于任何键)。
拥有不能独立存在但可以独立识别的实体是完全合法的 - 换句话说,它与非NULL的非标识关系。
你必须问: historyLineID 单独或与 orderID 结合时是否唯一?我怀疑后者是正确的,这将使它成为一个弱实体。

这真的是正确的弱实体关系吗?

你展示给我们的不是弱实体 - 父项的主键没有迁移到子项的主键。

还有其他识别它们的方法吗?

你基本上有两个选择:
  • orderHistory拥有一个复合主键:{orderID, historyLineID},其中orderID是外键。顺便说一下,这个主键可以被认为是“自然的”:

    enter image description here

  • orderHistory拥有一个替代主键:{orderHistoryID},而orderID在主键之外。不过你仍需要有另一个备选键 {orderID, historyLineID}

    enter image description here

我应该将表order的主键添加到表orderHistory并使其成为复合主键吗?

是的,这是上述第一种选项。除非orderHistory本身有子关系,否则这也是最好的解决方案。如果orderHistory有子级,则可能是或可能不是最佳解决方案,具体取决于几个因素。

如果我决定将其建模为普通的一对多关系,其中orderID作为外键添加,那么做这样做的缺点是什么?
这不是非此即彼。一个字段既可以是FK,也可以是(主要或备用)键的一部分,如上所示。
忽略弱实体会在设计后期造成任何问题吗,只要所有表都在第三范式中?
除非正确指定键,否则无法达到3NF,而没有考虑哪个实体可以独立识别,哪个实体不能,您将无法做到这一点。

谢谢您的回复 :) 只是为了确切理解您所说的:“_实体之所以不弱,不是因为它不能独立存在,而是因为它不能被独立识别_”,如果我有两个表customersorders呢?一个客户可以有多个订单,但一个订单只属于一个客户。我将其建模为2个表,其中在Orders表中仅添加了CustomerID作为FK。然而,现在当我考虑它时,如果没有客户下的订单,那么订单本身就没有意义。Orders应该是一个弱实体吗? - Songo
@Songo 你如何确定订单?如果客户的PK在订单的PK内,则它是弱的。如果不是,则不是。在这两种情况下,订单都不能存在于没有客户的情况下。 - Branko Dimitrijevic
我为表“订单”创建了一个代理主键OrderID。以前从未考虑过弱实体,因此对于每个实体,我都只创建了一个代理键来_标识_它们。如果需要关联实体,我只使用外键(1-11-MM-M)。现在我不确定_标识_的真正含义是什么:D - Songo
@Songo,我的回答第三段实际上已经解释了这句话的含义。你需要确定给定的字段是否可以单独成为唯一标识,或者需要与父表的主键组合。以订单为例,如果仅凭OrderID就可以唯一标识(我猜是这样),那么订单就不是弱实体。顺便说一下,不要随意创建代理键。InnoDB是聚集索引,聚集表中的备用索引很昂贵,因此,如果你可以仅使用“自然”复合主键(和1个索引),通常比同时具有代理键和自然键(和2个索引)更好。 - Branko Dimitrijevic
嗯,我明白你的意思。所以基本上如果我在所有表中添加一个代理自动递增ID字段(就像我一直做的那样),那么我就永远不会有弱实体了,对吧? - Songo
显示剩余6条评论

0
  • 由于依赖性,它是一个弱实体关系,但本质上是犹豫不决的一个实例。一个订单可能有一到多个历史记录行,但每个历史记录行必须有一个orderID,对吗?

听起来像是可选-强制关系。 因此,在orderHistory中,您的orderId具有“可选”属性... 2.您可以通过将主键组成orderID和historyLineID来部分解决问题 3.您将不得不在orderID表上进行一个反向关系。因此,您将不得不在order.orderID上进行连接,然后创建新的historyLineID,否则您无法在尚不存在的内容上创建。 4.这就是应该的方式。这种方式更容易为未来的脚本工作者和您自己所理解。使用外键创建一个orderID(父项)和多个historyLineID(子项),因为订单可以有多个订单行,这种方法可能是最好的。

链接:输入链接描述


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