如何划分外键的可能值?

时间:2016-12-19 22:28:03

标签: mysql sql foreign-keys foreign-key-relationship

我在MySQL数据库中有三个表。 这是与组织相关的主要表格。每个组织都有一个唯一的标识符,它也是某些表中的外键。

org
+------------+-------------+ 
| org_id     | name        |   
+------------+-------------+ 
| 1          | a           | 
| 2          | b           |  
| 3          | c           |  
+------------+-------------+

这是群组表。组织可以有很多小组。

groups
FOREIGN KEY (ORG_ID) REFERENCES ORG (ID);
+------------+-------------+----------+ 
| ID         | org_id      |   name   |
+------------+-------------+ ---------+
| 1          | 1           |  Group1  |
| 2          | 2           |  Group2  |
| 3          | 2           |  Group3  |
+------------+-------------+----------+

这是我想要执行更新的Feed表。 Feed只能有一个关联组。

feed
FOREIGN KEY (GROUP_ID) REFERENCES GROUPS (ID);
+------------+-------------+--------------+ 
| ID         | org_id      |   group_id   |
+------------+-------------+ -------------+
| 1          | 1           |      1       |
| 2          | 2           |      2       |
| 3          | 1           |     NULL     |
| 4          | 2           |      3       |
+------------+-------------+--------------+

所以现在有一个问题,我无法解决。当我INSERTUPDATE行时,我会设置groups_id,但这也可能是groups_id,不属于该组织。 发生这种情况,因为GROUPS中的所有ID都是有效的FK值。这是我想要避免的事情。应该只有insertupdategroups_idorg_id中的feeds.org_id相同。

如您所见,数据现在很好。但是当我尝试制作这个INSERT INTO feed VALUES (4, 2, 1)时,很高兴看到错误。是的,是的,我错过了一个可爱的错误......

我很难在它们之间建立联系。我似乎缺少一种信息或方法。我一直在寻找很多,但我不知道用来描述我的问题的词语。

所以我问你,你能给我一个小费吗?

编辑:

所有供稿和所有群组都与具有标识符的组织相关。组织可以创建订阅源/消息。如果此Feed与组无关,则此Feed是公开的。对于特殊Feed,他们可以创建一个组。该小组与这个特殊组织有关。

这很有效,一切都很好:

UPDATE feed 
SET title = "Title", message = "Message", groups_id = "1" 
WHERE id = "1" AND org_id = "1"

但这也有效:

UPDATE feed 
SET title = "Title", message = "Message", groups_id = "2" 
WHERE id = "1" AND org_id = "1"

问题是,可以将组关联到源(与组织1关联),而组不与组织关联(组2与组织2关联)。

所以我的想法是,有没有办法通过FOREIGN KEY或类似的(检查,连接,子查询)来解决这个问题。或者我应该考虑我的数据库设计?

1 个答案:

答案 0 :(得分:3)

我认为组合的外键可以解决您的问题:

create table agroup (
  id int primary key,
  orgid int,
  UNIQUE (id,orgid)
);

create table feed (
  id int primary key,
  groupid int,
  orgid int,
  FOREIGN KEY (groupid, orgid) REFERENCES agroup(id, orgid)
);

insert into agroup values (10, 1), (20, 1), (30, 2), (40, NULL);
insert into feed values (100,10,1), (101, 20, 1);
insert into feed values (102, 40, NULL); # works
insert into feed values (103, NULL, 1); # works as well
# insert into feed values (110,10,2); # yields error "Cannot add or update a child row: a foreign key constraint fails"

注意UNIQUE(id,orgid),这似乎是必要的。虽然我不明白为什么agroup(id primary key)不足以使agroup(id,orgid)唯一,但我得到了一个没有这个显式unique(id,orgid} - 约束的编译器错误。文档说必须索引引用的属性。无论如何,你的问题应该解决。

编辑:扩展示例,现在还演示了引用属性中NULL值的情况。

至少在MySQL中,复合外键约束允许引用(子)行中的NULL值,无论父表是否包含具有相应NULL值的行。如果为外键属性插入一个具有NULL值的行,则简单地忽略外键约束。授予mysql foreign key semantics,其中说: “...... MySQL基本上实现了MATCH SIMPLE定义的语义,允许外键全部或部分为NULL。在这种情况下,允许插入包含这样一个外键的(子表)行,而不是匹配引用的(父)表中的任何行。可以使用触发器实现其他语义。“