sql >> Database >  >> RDS >> PostgreSQL

Unieke beperking van Postgres versus index

Ik had wat twijfels over deze fundamentele maar belangrijke kwestie, dus besloot ik het voorbeeld te leren.

Laten we een testtabel master maken met twee kolommen, con_id met unieke beperking en ind_id geïndexeerd door unieke 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 de tabelbeschrijving (\d in psql) kun je de unieke beperking onderscheiden van de unieke index.

Uniek

Laten we de uniciteit controleren, voor het geval dat.

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=#

Het werkt zoals verwacht!

Buitenlandse sleutels

Nu gaan we detail definiëren tabel met twee externe sleutels die verwijzen naar onze twee kolommen 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
--------+---------+-----------
 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)

Nou, geen fouten. Laten we ervoor zorgen dat het werkt.

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=#

Er kan in externe sleutels naar beide kolommen worden verwezen.

Beperking met index

U kunt tabelbeperkingen toevoegen met behulp van een bestaande unieke 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)

Er is nu geen verschil tussen de beschrijving van de kolombeperkingen.

Gedeeltelijke indexen

In tabelbeperkingsdeclaratie kunt u geen gedeeltelijke indexen maken. Het komt rechtstreeks uit de definitie van create table ... .In unieke indexdeclaratie kunt u WHERE clause . instellen om een ​​gedeeltelijke index te maken. U kunt ook een index maken op expressie (niet alleen op kolom) en enkele andere parameters definiëren (sortering, sorteervolgorde, plaatsing van NULL's).

Je kan niet voeg tabelbeperking toe met behulp van gedeeltelijke 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.


  1. Hoe splits ik de uitvoer van mysqldump in kleinere bestanden?

  2. OTA instellen in R12 en 11i

  3. Volledig beheerde PostgreSQL-hosting op AWS en Azure wordt op tijd gelanceerd voor verouderde migraties

  4. Hoe te bestellen op maandnaam in SQLite