Reputation: 269
I'd like to do domething like:
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');
but postgres complain:
[0A000] ERROR: insufficient columns in UNIQUE constraint definition
Detail: UNIQUE constraint on table "foo" lacks column "cutlery" which is part of the partition key.
I can add a unique constraint on foo_id for each partition table but it does not prevent to do something like
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
Is there a nice way to address this issue, is the only solution trigger based ?
Using triggers i did something like:
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
Is it the right direction or does it looks totally crazy?
Upvotes: 2
Views: 1304
Reputation: 14081
There is no built-in "nice" way to handle this, because of how unique constraints are implemented in Postgres. The docs note this limitation:
Unique constraints on partitioned tables must include all the partition key columns. This limitation exists because PostgreSQL can only enforce uniqueness in each partition individually.
Unique constraints are implemented using an index, and each index only applies to a single partition, so enforcing uniqueness across multiple partitions must use some other mechanism.
Upvotes: 1