【发布时间】: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