To enforce partial uniqueness in postgres, it is a well known workaround to create a partial unique index instead of an explicit constraint, like so:
CREATE TABLE possession (
possession_id serial PRIMARY KEY,
owner_id integer NOT NULL REFERENCES owner(owner_id),
special boolean NOT NULL DEFAULT false
);
CREATE UNIQUE INDEX possession_unique_special ON possession(owner_id, special) WHERE special = true;
This would restrict each owner to having no more than one special possession at the database level. It obviously isn't possible to create indices spanning multiple tables, so this method cannot be used to enforce partial uniqueness in a supertype & subtype situation where the columns exist in different tables.
CREATE TABLE possession (
possession_id serial PRIMARY KEY,
owner_id integer NOT NULL REFERENCES owner(owner_id)
);
CREATE TABLE toy (
possession_id integer PRIMARY KEY REFERENCES possession(possession_id),
special boolean NOT NULL DEFAULT false
);
As you can see, the earlier method does not allow for restricting each owner to no more than one special toy in this example. Assuming each possession must implement exactly one subtype, what is the best way to enforce this constraint in postgres without substantially altering the original tables?
owner_id
totoy
. 2.Add unique constraint onpossession(owner_id, possession_id)
. 3.Change the FK to include both columns(owner_id, possession_id)
4.Then you can add the desired partial unique index on the subtype table.owner_id
orspecial
are likely to be later updated for my purposes, I'd still prefer not to store the column twice if it's reasonably possible. A solution that doesn't might help someone else with a similar problem too.possession_id
column. I don't think there is any other way to enforce what you want with DRI.possession_id
in both tables is fairly necessary, otherwise it would be impossible to join the attributes of both the supertype and subtype. (Sure, there are alternatives, but it's beside the point.) Unlikepossession_id
,owner_id
is actually modifiable data and not an arbitrary identifier so it may be subject to updates and inconsistency. Increasing storage requirements by duplicating columns is also obviously undesirable.possesion_id
in both tables is not a duplication. It's a reference.