Как добавить или эмулировать ограничение уникальности для части столбца составного первичного ключа многораздельной таблицы в postgres 12? - PullRequest
0 голосов
/ 12 февраля 2020

Я бы хотел сделать следующее:

create table foo (
  foo_id int,
  cutlery text,
  primary key (foo_id, cutlery)
  unique (foo_id)
) partition by list (cutlery);

create table foo_spoon partition of foo for values in ('SPOON');
create table foo_fork partition of foo for values in ('FORK');

, но postgres жаловаться:

[0A000] ОШИБКА: недостаточно столбцов в определении УНИКАЛЬНОГО ограничения

Подробно: в уникальном ограничении на таблицу "foo" отсутствует столбец "столовые приборы", являющийся частью ключа раздела.

Я могу добавить уникальное ограничение для foo_id для каждого таблицы разделов, но это не мешает делать что-то вроде

insert into foo_spoon (foo_id, cutlery) values (1, 'SPOON'); -- this goes into one partition
insert into foo_fork (foo_id, cutlery) values (1, 'FORK');    -- this goes into another partition

Есть ли хороший способ решения этой проблемы, основан ли единственный триггер решения?


Используя триггеры, я сделал что-то вроде:

create or replace function _check_duplicate_foo_id()
returns trigger as
$$
begin
    if exists (select count(*) from foo where foo.foo_id = new.foo_id having count(*) <> 1) then
        raise exception 'Duplicate foo.foo_id %s', new.foo_id;
    end if;
    return new;
end;
$$ language plpgsql;

create trigger _check_duplicate_foo_id_trig
    after insert or update on foo_spoon
    for each row execute procedure _check_duplicate_foo_id();

-- same for foo_fork

Это правильное направление или это выглядит совершенно сумасшедшим?

1 Ответ

1 голос
/ 12 февраля 2020

Нет встроенного «красивого» способа справиться с этим, потому что уникальные ограничения реализованы в Postgres. Документы отмечают это ограничение :

Уникальные ограничения для секционированных таблиц должны включать все столбцы ключей секционирования. Это ограничение существует, потому что PostgreSQL может применять уникальность только в каждом разделе отдельно.

Уникальные ограничения реализуются с использованием индекса, и каждый индекс применяется только к одному разделу, поэтому применение уникальности для нескольких разделов должно выполняться использовать другой механизм.

...