Jeg var i tvivl om dette grundlæggende, men vigtige spørgsmål, så jeg besluttede at lære ved eksempel.
Lad os oprette testtabel master med to kolonner, con_id med unik begrænsning og ind_id indekseret af unikt indeks.
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
--------+---------+-----------
con_id | integer |
ind_id | integer |
Indexes:
"master_con_id_key" UNIQUE CONSTRAINT, btree (con_id)
"master_unique_idx" UNIQUE, btree (ind_id)
I tabelbeskrivelsen (\d i psql) kan du skelne unikke begrænsninger fra unikke indeks.
Unik
Lad os tjekke det unikke, for en sikkerheds skyld.
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=#
Det virker som forventet!
Fremmednøgler
Nu vil vi definere detaljer tabel med to fremmednøgler, der refererer til vores to kolonner i 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
--------+---------+-----------
con_id | integer |
ind_id | integer |
Foreign-key constraints:
"detail_fk1" FOREIGN KEY (con_id) REFERENCES master(con_id)
"detail_fk2" FOREIGN KEY (ind_id) REFERENCES master(ind_id)
Nå, ingen fejl. Lad os sikre os, at det virker.
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=#
Begge kolonner kan refereres i fremmednøgler.
Begrænsning ved hjælp af indeks
Du kan tilføje tabelbegrænsning ved hjælp af eksisterende unikke indeks.
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)
Nu er der ingen forskel mellem beskrivelse af kolonnebegrænsninger.
Delvise indekser
I tabelbegrænsningserklæringen kan du ikke oprette delvise indekser. Det kommer direkte fra definitionen af create table ...
.I en unik indekserklæring kan du indstille WHERE clause
at oprette delvist indeks. Du kan også oprette indeks på udtryk (ikke kun på kolonne) og definere nogle andre parametre (sortering, sorteringsrækkefølge, NULLs placering).
Du kan ikke tilføje tabelbegrænsning ved hjælp af delvist indeks.
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.