Reputation: 13
I am building a site with 2 templates: stats and tags but there is also an N:M mapping between them.
Stats and tags both have their own pages on the site and these have common characteristics, so I'd like a parent table called pages.
create table pages (id serial primary key, title varchar(50));
create table stats (show_average boolean) inherits (pages);
create table tags (color varchar(50)) inherits (pages);
create table stat_tags (
stat_id int
,tag_id int
,foreign key (stat_id) references stats(id)
,foreign key (tag_id) references tags(id)
);
This last query yields:
ERROR: there is no unique constraint matching given keys for referenced table "tags"
If I do it without inheritance like this:
create table stats (id serial primary key, title varchar(50), show_average boolean);
create table tags (id serial primary key, title varchar(50), color varchar(50));
create table stat_tags (
stat_id int
,tag_id int
,foreign key (stat_id) references stats(id)
,foreign key (tag_id) references tags(id)
);
... it accepts all queries.
Is it possible for two children to have a mapping table in PostgreSQL? How?
Thanks!
Upvotes: 1
Views: 1034
Reputation: 95642
Using inherits
probably isn't the best way to do this.
A serious limitation of the inheritance feature is that indexes (including unique constraints) and foreign key constraints only apply to single tables, not to their inheritance children. This is true on both the referencing and referenced sides of a foreign key constraint.
See Caveats
I would be more comfortable with something along these lines.
create table pages (
id serial primary key,
page_type char(1) not null
check (page_type in ('s', 't')),
title varchar(50) not null unique,
unique (id, page_type)
);
create table stats (
id integer primary key,
page_type char(1) not null default 's'
check(page_type = 's'),
show_average boolean,
foreign key (id, page_type) references pages (id, page_type)
);
create table tags (
id integer primary key,
page_type char(1) not null default 't'
check(page_type = 't'),
color varchar(50) not null
);
create table stat_tags (
stat_id int not null,
tag_id int not null,
primary key (stat_id, tag_id),
foreign key (stat_id) references stats(id),
foreign key (tag_id) references tags(id)
);
In production, you'd probably want to build two updatable views, one to resolve the join between pages and stats, and one to resolve the join between pages and tags.
Upvotes: 3