我需要基于四列创建对表的限制,其中两个是互斥的,我的意思是,如果一个是NULL而另一个不是。
理想的脚本是:
ALTER TABLE ONLY t_users_prizes
ADD CONSTRAINT t_user_prize_test_circuit_key
UNIQUE (id_event||':'||id_circuit, id_prize, id_user);
但Postgres不允许这种连接。
如何实施此限制?
答案 0 :(得分:6)
@Catcall's CHECK
constraint强制(a, b)
中只有一个必须是NULL
。
但是NULL
值不违反UNIQUE约束 - 两个NULL永远不会被认为是相等的!因此,简单的UNIQUE
约束不起作用。
你可以用两个partial UNIQUE索引来完成它:
CREATE TEMP TABLE foo (
a int
,b int
,c int NOT NULL
,d int NOT NULL
,CHECK ((a IS NOT NULL AND b IS NULL) OR (b IS NOT NULL AND a IS NULL))
);
CREATE UNIQUE INDEX foo_acd_idx ON foo(a,c,d)
WHERE b is NULL;
CREATE UNIQUE INDEX foo_bcd_idx ON foo(b,c,d)
WHERE a is NULL;
INSERT INTO foo VALUES (NULL,2,3,4);
INSERT INTO foo VALUES (NULL,2,3,4); -- error!
我将c
和d
声明为NOT NULL
,以防止进一步的并发症。
More details in this closely related answer.
如果您还想禁止(1, NULL, 3, 4)
和(NULL, 1, 3, 4)
(请参阅我的评论),您可以使用COALESCE
代替一个索引:
CREATE UNIQUE INDEX foo_xcd_idx ON foo(COALESCE(a,b),c,d);