I have a many-to-many join table in Postgres that I would like to index to A) increase performance (obviously) and B) enforce uniqueness. For example:
a_id | b_id
1 | 2 <- okay
1 | 3 <- okay
2 | 3 <- okay
1 | 3 <- not okay (same as row 2)
Is it possible to have a single index on two columns that enforces uniqueness in the values? What type of index should I use?
As Primary Key
Do this if that unique is primary key:
Not Primary Key
Do this if that unique is non-primary key:
Existing Table
If you have existing table, do this instead:
That alter table display this message:
Drop
If you wanted to drop that constraint(you might want to make unique a combination of 3 fields):
Index & Constraint & Nulls
Regarding index, from Postgres doc:
Source: http://www.postgresql.org/docs/9.1/static/indexes-unique.html
If uniqueness depends on some rules, you shall use
CREATE UNIQUE INDEX, for example:Given this:
That unique can catch these duplicates, this will be rejected by database:
Yet that UNIQUE CONSTRAINT cannot catch duplicate nulls. Nulls serves as unknown, they serves as wildcard, that’s why it’s allowed to have multiple nulls in unique constraint. This will be accepted by database:
Think of
UNIQUE CONSTRAINTthat it allows deferred uniqueness, hence the acceptance of null values above.If you want only one wildcard(null b_id) per a_id, aside from the unique constraint, you need to add a
UNIQUE INDEX. UNIQUE CONSTRAINT can’t have an expression on them.INDEXandUNIQUE INDEXcan. This will be your complete DDL for rejecting multiple null;This will be your complete DDL:
This will be rejected by your database now:
This will be allowed:
Related to http://www.ienablemuch.com/2010/12/postgresql-said-sql-server2008-said-non.html