为什么复合外键需要单独的唯一约束?

Zil*_*ilk 13 postgresql foreign-key constraint unique-constraint

这是一个简单的表,其中记录可以引用同一个表中的父记录:

CREATE TABLE foo (
    id         SERIAL  PRIMARY KEY,
    parent_id  INT     NULL,
    num        INT     NOT NULL,
    txt        TEXT    NULL,
    FOREIGN KEY (parent_id) REFERENCES foo(id)
);
Run Code Online (Sandbox Code Playgroud)

由于增加了其他字段值之一 ( num) 在父记录和子记录之间必须相同的要求,我认为复合外键应该可以解决问题。我将最后一行更改为

    FOREIGN KEY (parent_id, num) REFERENCES foo(id, num)
Run Code Online (Sandbox Code Playgroud)

并得到错误:没有唯一约束匹配给定键的引用表 "foo"

我可以很容易地添加这个约束,但我不明白为什么它是必要的,当引用的列 ( id) 之一已经保证是唯一的?在我看来,新的约束将是多余的。

ype*_*eᵀᴹ 12

这是 DBMS 的限制 - 据我所知,在所有这些限制中。不仅在添加列时,而且在重新排列列时也是如此。如果我们对 有一个UNIQUE约束(a1, a2),我们就不能添加一个FOREIGN KEYREFERENCES (a2, a1)除非有一个(a2, a1)本质上是多余的唯一约束。

将其添加为一项功能并不会非常困难:

当 存在UNIQUE约束时(a),则任何(a, b, c, ..., z)(b,c, ...a, ...z)组合也得到保证UNIQUE

或概括:

当 上存在UNIQUE约束时(a1, a2, ..., aN)(a1, a2, ..., aN, b1, b2, ..., bM)也保证了任何组合或任何重新排列UNIQUE

似乎还没有被问到,或者它没有被认为是足够高的优先级来实施。

您始终可以在相应的频道中提出要实施的功能的请求。或者甚至自己实现它,如果 DBMS 是开源的,比如 Postgres。


Joi*_*dio 6

一般的外键(不仅仅是复合键)必须指向另一个表中某种类型的唯一键。如果他们不这样做,就不会有关系数据的完整性。

这是抱怨,因为,虽然你在 (id) 上有一个唯一键......你没有在 (id, num) 上有一个唯一键......因此,就数据库而言,这对 (id, num) 是不保证是独一无二的。我们,作为人类,可以确定它是独一无二的,但我相信他们必须添加很多额外的代码才能使 Postgres 足够聪明,以看到“哦,嘿.. id 应该是独一无二的,所以 id,num 也应该是唯一的" ..

如果他们在您需要做的只是在两列上创建另一个唯一索引来解决问题时添加了该代码,我会感到非常惊讶。

为了清楚起见,他们必须添加的代码不仅仅是这种简单的情况......它必须处理所有情况,甚至是外键在 4+ 列上的情况,等等......我敢肯定逻辑会相当复杂。