PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Postgres Unique Constraint vs. Index

Ich hatte einige Zweifel an diesem grundlegenden, aber wichtigen Thema, also habe ich mich entschieden, anhand meines Beispiels zu lernen.

Lassen Sie uns die Testtabelle master erstellen mit zwei Spalten, con_id mit Unique Constraint und ind_id indexiert nach eindeutigem 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
--------+---------+-----------
 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 die eindeutige Einschränkung vom eindeutigen Index unterscheiden.

Einzigartigkeit

Lassen Sie uns die Eindeutigkeit überprüfen, 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 definieren wir detail Tabelle mit zwei Fremdschlüsseln, die auf unsere beiden Spalten in master verweisen .

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. Stellen wir sicher, 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.

Einschränkung mit Index

Sie können eine Tabelleneinschränkung mithilfe eines vorhandenen eindeutigen Index hinzufü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 zwischen der Beschreibung der Spaltenbeschränkungen.

Teilindizes

In der Tabelleneinschränkungsdeklaration können Sie keine Teilindizes erstellen. Dies kommt direkt aus der Definition von create table ... .In der eindeutigen Indexdeklaration können Sie WHERE clause setzen um einen partiellen Index zu erstellen. Sie können auch einen Index für einen Ausdruck erstellen (nicht nur für eine Spalte) und einige andere Parameter definieren (Sortierung, Sortierreihenfolge, NULL-Platzierung).

Das können Sie nicht Tabelleneinschränkung mit partiellem Index 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.