我最近在不同的项目中多次遇到过这种情况.这是一个四个表格的图表,标有字母:
A
1 / \ 1
/ \
* / \ *
B C
1 \ / 1
\ /
* \ / *
D
Run Code Online (Sandbox Code Playgroud)
在这种情况下,有可能将数据变得不一致如果从按键B到A,并C以A不匹配给定的D.
对于特定的(组成的)示例,想象A是Company,B是Employee,C是Project和D是WorkItem.在这种情况下,没有什么能阻止创建工作项,声称被分配给一个甚至不为拥有该项目的公司工作的人.
我主要只是好奇,有这个问题的设计解决方案吗?我知道在实际的应用程序中,您可以使用触发器或其他一些安全措施.我还没有找到一种方法来改变表格,使这种不一致变得不可能.有办法吗?
请注意,只是切断了连接中的一个,像C到A不行的,因为如果没有D了存在的C,你就没有追查连接回的方式A.
为下游表使用复合键(即包含多个字段的键).然后在D中,您只能使用一个字段来保存A的键:
[编辑:修复了D的第二个FK中的愚蠢复制和粘贴错误!]
CREATE TABLE A (
A_ID INTEGER PRIMARY KEY
-- Any other fields you want...
);
CREATE TABLE B (
A_ID INTEGER REFERENCES A.A_ID,
B_ID INTEGER,
-- Any other fields you want...
PRIMARY KEY (A_ID, B_ID)
);
CREATE TABLE C (
A_ID INTEGER REFERENCES A.A_ID,
C_ID INTEGER,
-- Any other fields you want...
PRIMARY KEY (A_ID, C_ID)
);
CREATE TABLE D (
A_ID INTEGER, -- This field forms part of the FK for BOTH B and C
B_ID INTEGER,
C_ID INTEGER,
D_ID INTEGER,
-- Any other fields you want...
PRIMARY KEY (A_ID, B_ID, C_ID, D_ID),
FOREIGN KEY (A_ID, B_ID) REFERENCES B (A_ID, B_ID),
FOREIGN KEY (A_ID, C_ID) REFERENCES C (A_ID, C_ID)
);
Run Code Online (Sandbox Code Playgroud)
我还没有测试过上面的SQL,但是你有希望得到这个想法.请注意,D不需要第三个FK约束回到A,因为它已经被其他FK隐含了(实际上它们分别由它们隐含).
参照完整性检查总是优于触发器 - 至少对于PostgreSQL来说,并且我怀疑所有RDBMS都是如此.