Saya memiliki keraguan tentang masalah mendasar namun penting ini, jadi saya memutuskan untuk belajar dengan memberi contoh.
Mari kita buat master tabel uji dengan dua kolom, con_id dengan kendala unik dan ind_id diindeks oleh indeks unik.
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)
Dalam deskripsi tabel (\ d dalam psql), Anda dapat memberi tahu batasan unik dari indeks unik.
Keunikan
Mari kita periksa keunikannya, untuk berjaga-jaga.
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=#
Ini berfungsi seperti yang diharapkan!
Kunci asing
Sekarang kita akan mendefinisikan tabel detail dengan dua kunci asing yang merujuk ke dua kolom kita di 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)
Yah, tidak ada kesalahan. Mari kita pastikan itu berhasil.
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=#
Kedua kolom dapat direferensikan dalam kunci asing.
Batasi menggunakan indeks
Anda bisa menambahkan batasan tabel menggunakan indeks unik yang ada.
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)
Sekarang tidak ada perbedaan antara deskripsi batasan kolom.
Indeks sebagian
Dalam deklarasi kendala tabel Anda tidak dapat membuat indeks parsial. Ini datang langsung dari definisi dari create table ...
. Dalam deklarasi indeks unik Anda dapat mengatur WHERE clause
untuk membuat indeks parsial. Anda juga dapat membuat indeks pada ekspresi (tidak hanya pada kolom) dan menentukan beberapa parameter lainnya (susunan, susunan urutan, penempatan NULLs).
Anda tidak bisa menambahkan batasan tabel menggunakan indeks parsial.
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.