【问题标题】:Database modeling for a weak entity弱实体的数据库建模
【发布时间】:2012-05-26 05:41:30
【问题描述】:

我的数据库中有 2 个表 ordersorderHistory

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

现在一个order 可以有多个history lines。但是,history line 不能单独存在。我听说这被称为弱实体,因此来自 ordersPK 必须是表 orderHistoryPK 的一部分。

问题

  1. 这真的是一个正确的弱实体关系吗?还有其他方法可以识别它们吗?
  2. 是否应该将表orderPK添加到表orderHistory并使其成为复合主键?
  3. 如果我决定向orderHistory 添加新记录,我将如何添加新的复合键? (orderID 可从表 orders 获得,但 historyLineID 应自动递增。)
  4. 如果我决定将其建模为普通的一对多关系,其中orderID被添加为的外键,该怎么办?这样做有什么坏处?
  5. 如果所有表都处于第三范式,那么在设计后期是否会完全忽略弱实体会导致任何问题?

注意

orderIDhistoryLineID 都是代理键。 提前致谢。

【问题讨论】:

    标签: mysql sql database database-design data-modeling


    【解决方案1】:

    一个实体不是弱的,因为它不能独立存在,而是因为它不能被识别独立。因此,将“引导”到弱实体的关系称为“识别”关系。在实践中,这意味着父主键被迁移到(通常proper)子主键的子集中(术语“弱实体”通常与主键相关,尽管理论上它可以适用于任何键)。

    拥有一个不能独立存在但可以独立识别的实体是完全合法的——换句话说,它与非 NULL 存在非识别关系。

    你要问:historyLineID 可以是唯一的单独,还是与orderID 结合?我怀疑是后者,这将使它成为一个弱实体。

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

    您向我们展示的并不是一个弱实体——父母的 PK 不会迁移到孩子的 PK。

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

    您基本上有两个选择:

    • orderHistory 有一个复合 PK:{orderID, historyLineID},其中orderID 是 FK。 BTW,这个PK可以说是“自然”了:

    • orderHistory 有一个代理 PK:{orderHistoryID},而 orderID 在 PK 之外。不过,您仍然需要备用密钥 {orderID, historyLineID}

    要不要把表orderHistory的PK添加到表orderHistory中,做成复合主键?

    是的,这是上面描述的第一个选项。除非您在 orderHistory 本身上有子关系,否则这也是最好的解决方案。如果orderHistory 确实有孩子,那么这可能是也可能不是最佳解决方案,具体取决于几个因素。

    如果我决定将其建模为普通的一对多关系,其中 orderID 被添加为外键,该怎么办?这样做有什么坏处?

    这不是非此即彼。一个字段既可以是 FK,也可以是(主键或备用)键的一部分,如上所示。

    如果所有表都处于第三范式,那么在设计后期是否会完全忽略弱实体会导致任何问题?

    除非您正确指定密钥,否则您将无法达到 3NF,并且如果不考虑哪些实体可以独立识别,哪些不能独立识别,您将无法做到这一点。

    【讨论】:

    • 感谢您的回复 :) 只是为了准确理解您的意思:“一个实体不是弱的,因为它不能独立存在,而是因为它不能独立识别。 ”,如果我有 2 张桌子 customersorders?一个客户可以有很多订单,但是一个订单只属于一个客户。我已将其建模为 2 个表,其中 CustomerID 仅作为 FK 添加到 Orders 表中。然而,现在想想如果不是由客户 下的订单 本身就没有任何意义。应该由弱实体命令吗?
    • @Songo 你如何识别订单?如果客户的 PK 在订单的 PK 范围内,则为弱。如果不是,那么它不是。在这两种情况下,如果没有客户,订单就无法存在。
    • 好吧,我为表 Orders 创建了一个代理主键 OrderID。我以前从未考虑过弱实体,因此对于我拥有的每个实体,我只是创建了一个代理键来识别它们。如果我需要关联实体,我只需使用外键(1-11-MM-M)。我现在不确定 identify 的真正含义:D
    • @Songo 什么是手段实际上在我的回答的第 3 段中有所描述。您基本上必须弄清楚给定的字段是否可以单独唯一,或者您需要将其与父母的 PK 结合起来。在 order 的情况下,如果 OrderID 单独是唯一的(我猜是这种情况),那么 order 不是一个弱实体。顺便说一句,不要只是不分青红皂白地创建代理。 InnoDB 是集群的,并且备用索引在集群表中很昂贵,因此如果您可以使用“自然”复合 PK(和 1 个索引),这通常比同时拥有代理和自然键更好(和 2 个索引)。
    • 嗯,我明白你的意思了。所以基本上,如果我向所有表添加一个代理自动增量 ID 字段(就像我一直做的那样),那么我永远不会有弱实体,对吧?
    【解决方案2】:
    1. 由于依赖,是弱实体关系,但本质上是优柔寡断的一个实例。一个订单可能有一对多历史记录行,但每个历史记录行必须有一个 orderID,对吗?

    这听起来像是一种可选-强制关系。 因此,您的 orderId 在 orderHistory 中具有“可选”属性... 2.可以通过将主键设为orderID和historyLineID的组合来部分解决问题 3. 你必须在 orderID 表上做一个内卷关系。因此您必须重新加入 order.orderID,然后创建新的 historyLineID,否则您无法在尚不存在的东西上创建。 4. 这是应该的方式。对于未来从事脚本工作的人(可能还有您自己)来说,这种方式更容易理解。使用外键创建具有多个historyLineID(子)的orderID(父),因为订单可以有多个订单行,这种方法可能是最好的。

    链接:enter link description here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-31
      • 2016-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-24
      • 2015-03-07
      相关资源
      最近更新 更多