mysql – 允许/只需要一个具有公共FK的记录具有“主”标志

首先,如果这是一个骗局我道歉 – 我怀疑它可能是但我找不到它.

说我有一张公司表:

 id | company_name
----+--------------
  1 | Someone
  2 | Someone else

……和一个联系人表:

 id | company_id | contact_name | is_primary
----+------------+--------------+------------
  1 |     1      | Tom          |      1
  2 |     2      | Dick         |      1
  3 |     1      | Harry        |      0
  4 |     1      | Bob          |      0

是否可以以这样的方式设置联系人表:它要求只有一条记录为每个公共company_id设置了is_primary标志?

所以如果我试图这样做:

UPDATE contacts
SET is_primary = 1
WHERE id = 4

…查询将失败,因为Tom(id = 1)已被标记为company_id = 1的主要联系人.或者甚至更好,是否可以构造一个触发器以使查询成功,但是Tom的is_primary标志会被同样的操作清除吗?

我不太关心检查company_id是否存在于公司表中,我的PHP代码在我进入这个阶段之前就已经执行了这个检查(虽然如果有一种方法可以在同一个操作中执行此操作,那将是很好的,我假设).

当我最初想到这一点时,我认为“这将很容易,我只会在company_id和is_primary列中添加一个唯一索引”,但显然这不会起作用,因为它会限制我只有一个主要联系人和一个非主要联系人 – 任何添加第三次联系的尝试都将失败.但我不禁觉得有一种方法可以配置一个独特的索引,它为我提供了我所需的最低功能 – 拒绝尝试添加第二个主要联系人,或拒绝尝试离开没有主要联系人的公司.

我知道我可以将一个primary_contact字段添加到Companies表中,并将FK添加到contacts表中,但它感觉很麻烦.我不喜欢两个表都有FK到另一个表的想法 – 在我看来,一个表应该依赖于另一个表,而不是两个表依赖于彼此.我想我只是觉得随着时间的推移出现问题的可能性会更大.

总结一下:

>如何限制联系人表,以便只有一个给定company_id的记录设置了is_primary标志?
>任何人都有任何关于两张桌子相互之间的FK是一个好/坏主意的想法吗?

解决方法:

表之间的循环反应确实很混乱.看到这个(十年之久)文章:SQL By Design: The Circular Reference

制作此类约束的最简洁方法是添加另一个表:

Company_PrimaryContact
----------------------
company_id
contact_id
PRIMARY KEY (company_id)
FOREIGN KEY (company_id, contact_id)
  REFERENCES Contact (company_id, id)

这还需要表中的UNIQUE约束Contact on(company_id,id)

上一篇:mysql – 用于从数据库中删除行的SQL触发器


下一篇:mysql – 从Trigger调用包含动态SQL的存储过程