两列上的唯一索引,反之亦然

Unique Index on two columns and vice versa

我在 postgres 9.5 中有以下 table:

CREATE TABLE public.test
(
id bigint NOT NULL DEFAULT nextval('test_id_seq'::regclass),
id1 integer,
id2 integer,
CONSTRAINT test_pkey PRIMARY KEY (id)
);

我想在两列上添加限制,只允许

处的记录集
  1. 新记录集 (id1,id2) 不存在并且
  2. 新记录集 (id1,id2) 不存在 (id2,id1) 并且
  3. 新记录集的id1和id2不相等

它应该是这样的:

 id | id1 | id2
---------------
 1  | 1   | 1    <-- invalid (violates restriction 3.)
 2  | 1   | 2    <-- valid
 3  | 1   | 2    <-- invalid (violates restriction 1.)
 4  | 2   | 1    <-- invalid (violates restriction 2.)
 5  | 3   | 1    <-- valid
 6  | 3   | 2    <-- valid

对于限制1,我添加了:

ALTER TABLE test ADD CONSTRAINT test_id1_id2_unique UNIQUE(id1, id2);

但是如何为 2. 和 3. 添加约束?

在a_horse_with_no_name帮助下的最终解决方案:

CREATE TABLE public.test(
id bigint NOT NULL DEFAULT nextval('test_id_seq'::regclass),
id1 integer NOT NULL,
id2 integer NOT NULL,
CONSTRAINT test_pkey PRIMARY KEY (id),
CONSTRAINT test_check CHECK (id1 <> id2)
);

CREATE UNIQUE INDEX test_id1_id2_unique
ON public.test
USING btree
((LEAST(id1, id2)), (GREATEST(id1, id2)));

您可以创建一个唯一索引来涵盖 1. 和 2.

create unique index on test ( least(id1,id2), greatest(id1,id2) );

对于 3. 你需要一个检查约束:

CREATE TABLE public.test
(
  id bigint NOT NULL DEFAULT nextval('test_id_seq'::regclass),
  id1 integer,
  id2 integer,
  constraint check_not_equal check (id1 is distinct from id2),
  CONSTRAINT test_pkey PRIMARY KEY (id) 
);

您可能希望两个 ID 都为 NOT NULL。在这种情况下,您还可以使用 check (id1 <> id2)