Как определить уникальное ограничение для нескольких столбцов в нескольких таблицах в postgres? - PullRequest
2 голосов
/ 07 мая 2020

У меня есть несколько таблиц, скажем, 2 для простоты:

CREATE TABLE A (
    name varchar
    ...
);
CREATE TABLE B (
    name varchar
    ...
);

Эти таблицы имеют разные структуры, но все имеют один и тот же столбец (name)

Я хочу добавить уникальное ограничение для всех этих столбцов во всех этих таблицах.

Как я могу это сделать? Это кажется простым делом, но мой поиск в Google пока не увенчался успехом. Большинство существующих вопросов, похоже, относятся к нескольким столбцам в одной таблице.

1 Ответ

2 голосов
/ 07 мая 2020

Поскольку ограничения UNIQUE не могут охватывать несколько таблиц, вам необходимо создать дополнительную таблицу для хранения всех имен. Тогда каждая таблица будет иметь внешний ключ для дополнительной таблицы.

Например:

create table all_names (
  zone int not null,
  name varchar(20) not null,
  constraint uq1 unique (zone, name),
  constraint uq2 unique (name) -- this is the critical constraint!
);

create table a (
  zone int not null default 1 check (zone = 1),
  name varchar(20) not null,
  constraint fk1 foreign key (zone, name) references all_names (zone, name)
);

insert into all_names (zone, name) values (1, 'Jenny'); -- succeeds
insert into a (name) values ('Jenny'); -- succeeds

create table b (
  zone int not null default 2 check (zone = 2),
  name varchar(20) not null,
  constraint fk2 foreign key (zone, name) references all_names (zone, name)
);

insert into all_names (zone, name) values (2, 'Ivan'); -- succeeds
insert into b (name) values ('Ivan'); -- succeeds

insert into all_names (zone, name) values (2, 'Jenny'); -- fails!
insert into b (name) values ('Jenny'); -- fails!

Обратите внимание, что для каждой вставки теперь требуется дополнительная вставка в дополнительную all_names таблицу. Однако это можно автоматизировать (и происходить за кулисами) с помощью триггера до / после вставки (не показан).

См. Пример выполнения на DB Fiddle .

Если вы реализуете триггер, ваши вставки будут выглядеть просто, например:

insert into a (name) values ('Jenny'); -- succeeds
insert into b (name) values ('Ivan'); -- succeeds
insert into b (name) values ('Jenny'); -- fails!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...