四表关系设计

Tes*_*rex 7 database-design

我最近在不同的项目中多次遇到过这种情况.这是一个四个表格的图表,标有字母:

     A
  1 / \ 1
   /   \
* /     \ *
 B       C
1 \     / 1
   \   /
  * \ / *
     D
Run Code Online (Sandbox Code Playgroud)

在这种情况下,有可能将数据变得不一致如果从按键BA,并CA不匹配给定的D.

对于特定的(组成的)示例,想象ACompany,BEmployee,CProjectDWorkItem.在这种情况下,没有什么能阻止创建工作项,声称被分配给一个甚至不为拥有该项目的公司工作的人.

我主要只是好奇,有这个问题的设计解决方案吗?我知道在实际的应用程序中,您可以使用触发器或其他一些安全措施.我还没有找到一种方法来改变表格,使这种不一致变得不可能.有办法吗?

请注意,只是切断了连接中的一个,像CA不行的,因为如果没有D了存在的C,你就没有追查连接回的方式A.

j_r*_*ker 7

为下游表使用复合键(即包含多个字段的键).然后在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都是如此.