Уникальный индекс по двум столбцам и наоборот - PullRequest
0 голосов
/ 18 мая 2018

У меня есть следующая таблица в postgres 9.5:

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 Ответ

0 голосов
/ 18 мая 2018

Вы можете создать уникальный индекс, охватывающий как 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) 
);

Возможно, вы хотите, чтобы оба идентификаторабыть NOT NULL также.В этом случае вы также можете использовать check (id1 <> id2)

...