Miałem pewne wątpliwości co do tego podstawowego, ale ważnego problemu, więc postanowiłem uczyć się przez przykład.
Stwórzmy tabeli testowej mistrza z dwoma kolumnami, con_id z unikalność i ind_id indeksowane przez unikalnego indeksu.
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)
W opisie tabeli (\ d w psql) można określić unikalne ograniczenie z unikalnego indeksu.
check wyjątkowość wyjątkowość
Miejmy, na wszelki wypadek.
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=#
Działa zgodnie z oczekiwaniami!
klucze obce
Teraz będziemy definiować fragment stół dwa klucze obce odniesienie do naszych dwóch kolumnach w mistrza.
Cóż, bez błędów. Upewnijmy się, że to działa.
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=#
Do obu kolumn można się odwoływać w kluczach obcych.
Ograniczenie stosując wskaźnik
Możesz dodać stołowego ograniczenie wykorzystania istniejącej unikatowy 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)
Teraz nie ma różnicy między opisem ograniczeń kolumn.
cząstkowe indeksy
W deklaracji więzów tabeli nie można utworzyć częściowe indeksów. Pochodzi bezpośrednio z definition z create table ...
. W unikatowej deklaracji indeksu można ustawić WHERE clause
, aby utworzyć indeks częściowy. Możesz także create index na wyrażenie (nie tylko na kolumnie) i zdefiniować kilka innych parametrów (sortowanie, porządek sortowania, umieszczanie wartości NULL).
Nie można dodać ograniczenia tabeli za pomocą częściowego indeksu.
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.
The (tylko) różnica praktyczna jest, że można utworzyć klucz obcy do unikalnej przymusu, ale nie do unikalnego indeksu. –
Zaletą na odwrót ([pojawił się ostatnio w innym pytaniu] (http://stackoverflow.com/a/23449309/157957)) jest to, że możesz mieć * częściowy * unikatowy indeks, taki jak "Unikatowy (foo) Gdzie bar jest pusty ". AFAIK, nie da się tego zrobić z przymusem. – IMSoP
[tutaj] (http://flatiron.engineering/technology/2016/09/13/uniqueness-in-postgres.html) fajny artykuł na temat różnicy –