7

我最近在不同的项目中多次遇到这种情况。这是四个表的图表,用字母标记:

     A
  1 / \ 1
   /   \
* /     \ *
 B       C
1 \     / 1
   \   /
  * \ / *
     D

在这种情况下,如果给定的 from和Bto的键不匹配,则数据可能会变得不一致。ACAD

对于特定的(编造的)示例,想象Ais CompanyBis EmployeeCisProjectDis WorkItem。在这种情况下,没有什么可以阻止创建声称分配给甚至不为拥有该项目的公司工作的人的工作项。

我主要是好奇,这个问题有设计解决方案吗?我知道在实际应用中这很重要,您可以使用触发器或其他一些保护措施。我还没有找到一种方法来更改表格以使这种不一致成为不可能。有办法吗?

请注意,仅切断其中一个连接,例如 from CtoA是行不通的,因为如果不D存在 ' ,C您将无法将连接追溯到A.

4

1 回答 1

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)
);

我没有测试过上面的 SQL,但希望你能明白。请注意,D 不需要返回 A 的第三个 FK 约束,因为它的其他 FK 已经暗示了这一点(实际上它们每个都单独暗示了这一点)。

参照完整性检查总是比触发器好——至少在 PostgreSQL 中是这样,而且我怀疑所有 RDBMS 都是如此。

于 2013-10-24T15:52:34.460 回答