我有一个桌子栏
CREATE TABLE bar(
bar_id serial,
good_bar boolean,
PRIMARY KEY (bar_id) );
和一个表foo
CREATE TABLE foo (
foo_id serial,
side_a INTEGER REFERENCES bar(bar_id),
side_b INTEGER REFERENCES bar(bar_id)
PRIMARY KEY (foo_id);
但是,一旦在foo.side_a中使用了“ bar”条目,我想防止在foo.side_b中使用它,反之亦然。
PostgreSQL CHECK约束似乎仅限于约束所在的列,并且复合主键(side_a,side_b)不提供类似
的覆盖范围INSERT INTO foo(side_a,side_b) VALUES
(0, 1),
(1, 0);
我想提出某种错误。
我知道我应该能够使用功能+触发器来检查插入或更新,但是想知道是否没有更简单的解决方案,或者我是否会错误地解决该问题。
编辑以进行澄清: 对于bar_id引用只有一列的问题是,bar表中的数据将根据分配给bar_id的哪一侧进行转换(在数据库外部)。
我能想到的最好的比喻是棋子。双方都有相同的片段,但是从白色(side_a)的角度和黑色(side_b)的角度都可以考虑这些片段的位置。
还有更多实现细节,这些细节依赖于数据的两个不同视角的存在。
答案 0 :(得分:1)
您需要在表达式上具有唯一索引:
CREATE UNIQUE INDEX ON foo (greatest(side_a, side_b), least(side_a, side_b));
INSERT INTO foo(side_a,side_b)
VALUES
(1, 2),
(2, 1);
ERROR: duplicate key value violates unique constraint "foo_greatest_least_idx"
DETAIL: Key ((GREATEST(side_a, side_b)), (LEAST(side_a, side_b)))=(2, 1) already exists.