多个表的唯一约束

时间:2011-06-08 14:39:19

标签: sql postgresql normalization denormalization relational-algebra

假设我们有这些表格:

CREATE TABLE A (
    id SERIAL NOT NULL PRIMARY KEY
);
CREATE TABLE B (
    id SERIAL NOT NULL PRIMARY KEY
);
CREATE TABLE Parent (
    id SERIAL NOT NULL PRIMARY KEY,
    aId INTEGER NOT NULL REFERENCES A (id),
    bId INTEGER NOT NULL REFERENCES B (id),
    UNIQUE(aId, bId)
);
CREATE TABLE Child (
    parentId INTEGER NOT NULL REFERENCES Parent (id),
    createdOn TIMESTAMP NOT NULL
);

是否可以在Child上创建一个唯一约束,以便Child中的所有行最多一个引用Parent,其值为aId?换句话说,我可以创建一个唯一约束,以便上表的连接没有重复aId?我在想 - 我能找到的每个数据库的语法似乎都与每个约束的一个表相关联 - 但这可能是我缺乏想象力的。 (当然,在aId上取消标准化以包含Child是一种解决方案。)

2 个答案:

答案 0 :(得分:4)

您可以尝试以下方法。你必须在Parent的(id, aId)上创建一个冗余的UNIQUE约束(SQL非常愚蠢不是吗?!)。

CREATE TABLE Child
(parentId INTEGER NOT NULL,
 aId INTEGER NOT NULL UNIQUE,
FOREIGN KEY (parentId,aId) REFERENCES Parent (id,aId),
createdOn TIMESTAMP NOT NULL);

可能更好的解决方案是完全从Child表中删除parentId,而是添加bId,然后根据(aId, bId)引用Parent表:

CREATE TABLE Child
(aId INTEGER NOT NULL UNIQUE,
 bId INTEGER NOT NULL,
FOREIGN KEY (aId,bId) REFERENCES Parent (aId,bId),
createdOn TIMESTAMP NOT NULL);

你有什么理由不能这样做吗?

答案 1 :(得分:1)

执行此操作的正确方法是完全取消Child表并将createdOn列放在Parent表中,而不使用NOT NULL约束。你要说的只是一个Parent条目可以有零个或一个(但不是更多)createdOn个值。您不需要单独的表。这样做的事实并不容易或不明显,这部分证明了我的观点。 ;-) SQL通常以这种方式运行。