I had some doubts about this basic, but important problem, so I decided to learn by example.
Let me create a test table wizard with two columns, con_id with a unique constraint and an index ind_id indexed by a unique index.
create table master ( con_id integer unique, ind_id integer ); create unique index master_unique_idx on master (ind_id); Table "public.master" Column | Type | Modifiers
In the table description (\ d in psql) you can specify a unique constraint from a unique index.
Uniqueness
Let it verify uniqueness just in case.
test=# insert into master values (0, 0); INSERT 0 1 test=# insert into master values (0, 1); ERROR: duplicate key value violates unique constraint "master_con_id_key" DETAIL: Key (con_id)=(0) already exists. test=# insert into master values (1, 0); ERROR: duplicate key value violates unique constraint "master_unique_idx" DETAIL: Key (ind_id)=(0) already exists. test=#
It works as expected!
Foreign keys
Now we will define a detailed table with two foreign keys referencing our two columns in master.
create table detail ( con_id integer, ind_id integer, constraint detail_fk1 foreign key (con_id) references master(con_id), constraint detail_fk2 foreign key (ind_id) references master(ind_id) ); Table "public.detail" Column | Type | Modifiers
Well, no mistakes. Let it work.
test=# insert into detail values (0, 0); INSERT 0 1 test=# insert into detail values (1, 0); ERROR: insert or update on table "detail" violates foreign key constraint "detail_fk1" DETAIL: Key (con_id)=(1) is not present in table "master". test=# insert into detail values (0, 1); ERROR: insert or update on table "detail" violates foreign key constraint "detail_fk2" DETAIL: Key (ind_id)=(1) is not present in table "master". test=#
Both columns can refer to foreign keys.
Index Constraint
You can add a table constraint using an existing unique index.
alter table master add constraint master_ind_id_key unique using index master_unique_idx; Table "public.master" Column | Type | Modifiers --------+---------+----------- con_id | integer | ind_id | integer | Indexes: "master_con_id_key" UNIQUE CONSTRAINT, btree (con_id) "master_ind_id_key" UNIQUE CONSTRAINT, btree (ind_id) Referenced by: TABLE "detail" CONSTRAINT "detail_fk1" FOREIGN KEY (con_id) REFERENCES master(con_id) TABLE "detail" CONSTRAINT "detail_fk2" FOREIGN KEY (ind_id) REFERENCES master(ind_id)
Now there is no difference between the description of column restrictions.
Partial indexes
In a table constraint declaration, you cannot create partial indexes. It comes directly from the definition of create table ... In a unique index declaration, you can set the WHERE clause to create a partial index. You can also create an index by expression (not just a column) and define some other parameters (sort, sort order, NULL placement).
You cannot add a table constraint using a partial index.
alter table master add column part_id integer; create unique index master_partial_idx on master (part_id) where part_id is not null; alter table master add constraint master_part_id_key unique using index master_partial_idx; ERROR: "master_partial_idx" is a partial index LINE 1: alter table master add constraint master_part_id_key unique ... ^ DETAIL: Cannot create a primary key or unique constraint using such an index.