我在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 |
+------------+-------------+--------------+
所以现在有一个问题,我无法解决。当我INSERT
或UPDATE
行时,我会设置groups_id
,但这也可能是groups_id
,不属于该组织。
发生这种情况,因为GROUPS中的所有ID都是有效的FK值。这是我想要避免的事情。应该只有insert
或update
行groups_id
与org_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或类似的(检查,连接,子查询)来解决这个问题。或者我应该考虑我的数据库设计?
答案 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。在这种情况下,允许插入包含这样一个外键的(子表)行,而不是匹配引用的(父)表中的任何行。可以使用触发器实现其他语义。“