【问题标题】:design issues as to circular foreign keys关于循环外键的设计问题
【发布时间】:2014-12-21 21:37:08
【问题描述】:

我正处于设计数据库的最后阶段,遇到以下设计问题。

我有两个表,A 和 B。这些表本质上是一对一的关系 - 如果没有相应的 B 行,A 行就没有意义,反之亦然。

我最初的想法是创建相互的外键,但是如果我删除一个外键会产生问题(鸡和蛋的问题)吗?我正在使用 mysql。

我听到人们说“如果他们处于一对一关系中,只需将他们放在一张桌子上”。但是,我有一种感觉(这只是一种感觉)它们应该位于单独的表中,因为它们是不同的实体。

我应该把它们放在一张桌子上吗?循环外键有问题吗?

谢谢

【问题讨论】:

  • 多个 A 是否可以与同一个 B 关联(反之亦然),或者它们之间是否存在排他性配对?
  • 这些是什么东西,真的吗?
  • @Mureinik - 是的,几个 B 可以与一个 A 相关联
  • @MikeSherrill'CatRecall' - 我正在设计一个橄榄球数据库。当您获得“尝试”时,您可以“转换”它并获得更多积分。 A = 尝试和 B= 转换。将这些放在同一张桌子上感觉不对(尤其是尝试得分者和转换尝试的人可能是不同的玩家)。
  • 你说“这些表本质上是一对一的关系”,“几个B可以与一个A关联”。这两种说法之一必然是错误的。哪一个?

标签: mysql database-design


【解决方案1】:

我很难想到不同实体之间 1-1 关系的示例。通常,一侧或另一侧都有一个选项。考虑搁在书架上的书。书架上的每个位置都有一本书。给定的书占据一个位置。但是您可能有空位、未上架的书籍,或者书籍可能会随着时间的推移而更换位子。这只是一个例子。

下一个问题是访问路径。如果同时访问两个“实体”,则考虑将它们放入一个表中。我这样说是有警告的。有时您确实希望将列拆分为单独的表(通常出于性能原因)。这称为垂直分区。

如果它们确实是单独的实体,则使用两个表,每个表都有自己的主键。包括一个指向另一个表的外键。插入记录时要小心,以保持引用完整性。

如果它们是相同的实体但具有不同的列,则对两者使用相同的主键。让键在一个表中自动递增。然后在创建该记录时将该值插入到第二个表中。

【讨论】:

    【解决方案2】:

    在橄榄球中,每次尝试(或罚球尝试)不能有超过一次的转换,因此一个 A 不能有多个 B(正如您在其中一个 cmets 中所述)。每次尝试通常都有一次转换尝试 - 这是一个 1-1 的关系。此外,try 在其转换之前始终存在。

    您是否还在转换表中存储惩罚转换?如果你是,那么这些惩罚转换将不会与任何尝试相关联,因此与尝试不存在硬 1-1 关系,并且尝试表的外键必须接受空值。同样,由于您将在关联转换之前在 try 表中创建一个条目,因此转换的外键也必须接受空值。

    对我来说,最简单的方法是在转换表中创建一个外键,返回相关联的 try。如果惩罚转换也保存在同一个表中,外键将接受空值。这样,您可以先插入 try(假设您必须暂时这样做),而不必担心对转换表的引用完整性。然后您可以稍后添加转换,而无需返回并更新 try 表对新添加的转换的引用。

    【讨论】:

    • 感谢您的帮助。我知道每次尝试只能进行一次转换,但我的意思是有两种不同类型的尝试(标准尝试和惩罚尝试)。根据尝试的类型,转换需要链接到任何一个。
    【解决方案3】:

    看看这三个标签下的问题和信息:

    称为共享主键的技术对于建模 IS-A 关系和其他一对一关系很有用。使用外键作为共享主键强制关系的一对一性质。由于一个副本是另一个副本,因此您不会处于引发此问题的循环绑定中。

    转换和尝试之间的关系实际上是零或一对一。并非所有尝试都有转换。这意味着转换应该有一个外键来尝试。如果没有转换,就没有行。讨论结束。

    如果出于某种奇怪的原因,您确实需要在单独的表中使用标准尝试和惩罚尝试,您可以使用类表继承和共享主键来模拟标准尝试、惩罚尝试和尝试之间的 IS-A 关系.

    我只想把尝试放在一张桌子上。

    【讨论】:

      猜你喜欢
      • 2011-08-17
      • 2014-05-21
      • 1970-01-01
      • 2015-01-04
      • 2020-01-14
      • 1970-01-01
      • 2011-05-08
      • 1970-01-01
      相关资源
      最近更新 更多