4

首先,如果这是一个骗局,我深表歉意——我怀疑它可能是,但我找不到它。

假设我有一张公司表:

 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

是否可以以这样一种方式设置contacts表,即它要求一个且只有一个记录is_primary为每个 common 设置标志company_id

因此,如果我尝试这样做:

UPDATE contacts
SET is_primary = 1
WHERE id = 4

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

我不太在意检查表中是否company_id存在companies,我的 PHP 代码在我到达这个阶段之前已经执行了这个检查(尽管如果有办法在同一个操作中做到这一点,那会很好,我想) .

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

我知道我可以在表中添加一个primary_contact字段,并在companies表中添加一个 FK,contacts但感觉很乱。我不喜欢两张桌子都对另一张桌子有 FK 的想法——在我看来,一张桌子应该依赖另一张桌子,而不是两张桌子相互依赖。我想我只是认为随着时间的推移,出现问题的可能性会更大。

总结一下:

  • 如何限制联系人表,以便只有一个给定的记录设置company_idis_primary标志?
  • 有人对两张彼此有 FK 的桌子是否是个好主意/坏主意有任何想法吗?
4

2 回答 2

3

表之间的循环引用确实很混乱。请参阅这篇(十年前的)文章: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(company_id, id)

于 2012-02-17T10:38:12.080 回答
2

您可以在该设置之前进行查询

UPDATE contacts SET is_primary = 0 WHERE company_id = .....

甚至

UPDATE contacts
SET is_primary = IF(id=[USERID],1,0)
WHERE company_id = (
    SELECT company_id FROM contacts WHERE id = [USERID]
);

只是把一个替代方案放在那里 - 我个人可能会考虑 FK 方法,而不是这种类型的解决方法,即在公司表中有一个带有 primary_user_id 字段的字段。

不依赖于 contact.is_primary 字段的EDIT方法

替代方法,首先从联系人中删除 is_primary。其次,将“primary_contact_id”INT 字段添加到公司中。第三,在更改主要联系人时,只需更改该 primary_contact_id 从而防止任何时候有超过 1 个主要联系人的可能性,并且无需在后台使用触发器等。

此选项在任何引擎中都可以正常工作,因为它只是更新一个 INT 字段,可以根据需要添加/删除对 FK 等的任何依赖,但最简单的是它只是更改一个 INT 字段值

只要您需要一个从公司到标记主要联系人的链接,此选项是可行的

于 2012-02-17T10:38:19.543 回答