【问题标题】:How to solve circular reference between two tables?如何解决两个表之间的循环引用?
【发布时间】:2018-12-14 22:13:26
【问题描述】:

很简单的例子:

一个公司可以有N个Locations,其中一个Locations就是主要位置。我们可以用 MySQL 外键解决这个问题吗?

我们当前的方法是在每个位置 (company_id) 中都有一个指向公司的指针,在公司中拥有一个指向位置的指针 (main_location_id)。

假设我们不允许空引用,这种方法显然是错误的,因为它禁止创建:您无法创建公司,因为它没有 main_location_id,您无法创建位置,因为 if 没有 company_id。鉴于验证仍在交易的每个步骤中运行,交易无济于事。

有什么想法吗?

谢谢!

编辑 1

有些人建议在 Location 或中间表中使用具有唯一索引的标志来解决问题。我们已经考虑过它,但它有一个主要问题:它增加了开销,因为添加一个新的主要位置需要遍历所有其他位置才能将它们的标志设置为 false。

编辑 2

我们首选的解决方案(在理想情况下)是在交易结束时检查验证,而不是在每个步骤中。这可以通过禁用外键检查来完成,正如 cmets 中所建议的那样,但这当然是一个次优的解决方案。

结论:

如果不放松其中的一个约束,就无法使用 MySQL 来做到这一点。我们将在公司中使用插入前检查来检查位置参考是否为空。

尽管如此,我仍然很好奇为什么 MySQL 不允许在事务结束时通过验证,而不是在每一步都这样做。

【问题讨论】:

  • 多个公司可以共享位置吗?
  • 只需添加一个字段,表明该位置是主要的。或者一个额外的表格,您可以在其中添加更多位置详细信息,例如访问位置或邮箱之类的东西
  • 你为什么不允许null?它可以立即解决您的问题。为了避免添加额外的表,这实际上是您需要实施的事情。 FK 的可空值存在用于您的目的。使用正确的工具。
  • 看起来你已经把自己逼到了一个角落。如果你不放松你的限制之一,你就不能真正做到这一点。
  • 允许空外键允许插入。在您的公司表上创建触发器before insert 并在位置为空时引发SQLSTATE 绝对是微不足道的。您正在考虑一个超级简单的问题并避免唯一有效的解决方案 - 允许可为空的 fk。

标签: mysql entity-relationship circular-dependency database-normalization circular-reference


【解决方案1】:

你必须有三个表。

第一个是您的Company 表,其中包含有关贵公司的标量信息(如名称、财务代码等)

第二个,带有Location 的表,没有指向您公司的链接。在此表中,即您的行为:

  • 特拉法加广场
  • 翁贝托街

等等

第三个,一个中间表,CompanyLocation,你有一个双外键,companyId 和 locationId,第三列由一个标志 (isPrimary) 表示

就是这样

【讨论】:

  • 我不相信这是正确的。在这种情况下,数据模型不会强制存在主要位置,因此您最终可能会得到 Company 和 Location 而没有 MainLocation(第三个表)。
  • 你可以在第三张表中添加关于isPrimary字段的检查约束(必须是一个公司,并且只有一个),所以当你在该表中为公司添加第一行时,它必须是isPrimary = 真
  • 我明白了。这类似于我们已经尝试过的另一种方法:在每个公司都有一个唯一索引的位置有一个 isPrimary 键。您提出了相同的建议,但将此标志移动到第三个中间表。我没有看到使用该中间表的好处,我们不想这样做,因为它会增加开销:每次添加新的主要位置时,都必须检查所有位置以将其 isPrimary 标志设置为 false。
  • MySQL 只解析 CHECK 语句它并没有真正使用它@JoeTaras 它在手册中
猜你喜欢
  • 2020-07-07
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多