数据库设计:我有一个 child table 可能被多个 parent table (one-to-one) 使用。我如何设计它的架构

Database Design: I have a child table which might be used from more than one parent table (one-to-one). How do I design its schema

假设我有一个名为 offers 的 child table。 offers 可以从多个 table 引用,例如 purchasemembership 等。请注意,将来可能会有更多 table引用自.

购买和会员资格已经存在于数据库中,并且它们将始终在相应的优惠 object 之前创建。把它想象成购买 X 可能会提供报价 Y(一对一)

为了在关系模式中实现这一点,我想到了两个可能的选择。

选项 1

offers table 不会有任何引用。相反,purchase table 和 membership table 将有一个名为 offer_id 的列,它引用 offer table。如下所示

   table offers { 
      id,
      offer_name, 
   }

   table purchase { 
      id,
      ..other fields,
      offer_id fk(offers),
   }

   table membership { 
      id,
      ..other fields,
      offer_id fk(offers),
   }

选项 2

offers table 将包含一个 type 字段,它指的是要约的类型(purchasemembership 等),并且会有是引用每个 table.

的多个可空外键
   table offers { 
      id,
      offer_name, 
      type enum(purchase, membership,
      purchase_id fk(purchases) NULL, 
      membership_id fk(memberships) NULL,
   }

   table purchase { 
      id,
      ..other fields,
   }

   table membership { 
      id,
      ..other fields,
   }

我觉得方案一是最简单的方法,也是正确的方法。但是感觉有违数据库设计原则(Parent不应该引用child,等等)。

执行此操作的正确方法应该是什么?如果我选择选项 1,会出现什么问题?

由于您在 purchasemembership 实体 之后创建了 offer 实体,因此 offer 是 child 实体,因此应该有 parent table.

的外键

我知道相反的做法很诱人,但语义在数据库设计中很重要:

  1. 如果您的 FK 在 parent 个实体中,那么您 运行 有不属于任何实体的孤立报价的风险。您不能通过 FK 强制完整性。
  2. 您无法通过标准数据库技术阻止将 1 个报价分配给多个实体。您需要编写额外的应用程序代码来执行此规则。
  3. 任何查看您的 ERD 的人都会对关系的性质得出错误的初步结论,因此您必须向每位新同事提供额外的解释。
  4. 如果您在数据库架构之上使用 ORM,ORM 将再次错误地解释关系,在 FK 之后设置 类 和关系。同样,需要额外的解释。

您有三个选项来设计 offer table 中的外键以遵循选项 2:

  1. 每个 parent 都有一个单独的 FK 字段。优点是很清楚 child 属于哪个 parent 实体,并且很容易强制执行参照完整性。缺点是您需要创建与 parent 个实体一样多的字段,并且需要更改 table 才能添加新字段。如果您的 parent 个实体数量有限且数量为 stable,效果很好。
  2. 使用 typeparent_id 字段组合。类型字段告诉您记录属于哪个parent。这与之前的解决方案相反 - 可以灵活地添加新的 parent 类型,但是通过数据库工具强制执行参照完整性并不简单!
  3. 为每种 parent 类型使用单独的商品 table。如果您计划按类型区分各种优惠,这种设计会很有用。