Ich hatte einige Zweifel über dieses grundlegende, aber wichtige Problem, also beschloss ich, mit gutem Beispiel zu lernen.
Lassen Sie sich Testtabelle Master mit zwei Spalten erstellen, con_id mit einzigartigem Zwang und ind_id durch eindeutigen Index indiziert.
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)
In der Tabellenbeschreibung (\ d in psql) können Sie eindeutige Einschränkung von eindeutigen Index angeben.
Einmaligkeit
Scheck Einzigartigkeit Lassen Sie uns, nur für den Fall.
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=#
Es funktioniert wie erwartet!
Fremdschlüssel
Jetzt werden wir Detail Tabelle mit zwei Fremdschlüssel verweist auf unsere zwei Spalten in Master definieren.
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)
Nun, keine Fehler. Lassen Sie uns sicherstellen, dass es funktioniert.
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=#
Beide Spalten können in Fremdschlüsseln referenziert werden.
Constraint mit Index
Sie können Tabellenbedingung in einem der vorhandenen eindeutigen Index hinzuzufügen.
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)
Jetzt gibt es keinen Unterschied mehr zwischen den Beschreibungen der Spaltenbeschränkungen.
Teilindizes
In Tabellenconstraint Deklaration Sie nicht Teilindizes erstellen können. Es kommt direkt aus der definitioncreate table ...
. In der eindeutigen Indexdeklaration können Sie WHERE clause
einstellen, um Teilindex zu erstellen. Sie können auch create index auf Ausdruck (nicht nur auf Spalte) und definieren Sie einige andere Parameter (Sortierung, Sortierreihenfolge, NULLs Platzierung).
Sie können Tabelleneinschränkungen nicht mit Teilindex hinzufügen.
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.
Die (nur) praktische Unterschied ist, dass Sie einen Fremdschlüssel zu einer einzigartigen Einschränkung erstellen kann, aber nicht auf einen eindeutigen Index. –
Ein Vorteil umgekehrt ([wie kürzlich in einer anderen Frage kam] (http://Stackoverflow.com/a/23449309/157957)) ist, dass Sie einen * partiellen * eindeutigen Index haben können, z. B. "Unique (foo) Wo bar ist Null ". AFAIK, es gibt keine Möglichkeit, dies mit einer Einschränkung zu tun. – IMSoP
[hier] (http://flatiron.engineering/technology/2016/09/13/uniqueness-in-postgres.html) schönen Artikel über Unterschied –