PostgreSQL唯一索引复合键

Car*_*ado 1 sql postgresql indexing null unique-index

我需要基于四列创建对表的限制,其中两个是互斥的,我的意思是,如果一个是NULL而另一个不是.

理想的脚本是这样的:

ALTER TABLE ONLY t_users_prizes
ADD CONSTRAINT t_user_prize_test_circuit_key
UNIQUE (id_event||':'||id_circuit, id_prize, id_user);
Run Code Online (Sandbox Code Playgroud)

但Postgres不允许这种连接.

我该如何实施这个限制?

Erw*_*ter 6

@Catcall的CHECK约束强制执行(a, b)必须的一个NULL.

但是NULL值不违反UNIQUE约束 - 两个NULL永远不会被认为是相等的!因此,简单UNIQUE约束不起作用.

您可以使用两个部分 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! 
Run Code Online (Sandbox Code Playgroud)

我宣布cd作为NOT NULL,以防止进一步的并发症.

这个密切相关的答案的更多细节.

如果您还想禁止(1, NULL, 3, 4)(NULL, 1, 3, 4)(请参阅我的评论),您可以使用一个索引COALESCE:

CREATE UNIQUE INDEX foo_xcd_idx ON foo(COALESCE(a,b),c,d);
Run Code Online (Sandbox Code Playgroud)