Tôi đã có một số nghi ngờ về vấn đề cơ bản nhưng quan trọng này, vì vậy tôi quyết định tìm hiểu bằng ví dụ.
Hãy tạo bảng kiểm tra master với hai cột, con_id với ràng buộc duy nhất và ind_id được lập chỉ mục theo chỉ mục duy nhất.
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)
Trong mô tả bảng (\ d trong psql), bạn có thể cho biết ràng buộc duy nhất từ chỉ mục duy nhất.
Tính độc đáo
Hãy kiểm tra tính duy nhất, đề phòng.
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=#
Nó hoạt động như mong đợi!
Khóa ngoại
Bây giờ chúng ta sẽ xác định chi tiết bảng có hai khóa ngoại tham chiếu đến hai cột của chúng tôi trong 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)
Chà, không có lỗi. Hãy đảm bảo rằng nó hoạt động.
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=#
Cả hai cột đều có thể được tham chiếu trong khóa ngoại.
Ràng buộc sử dụng chỉ mục
Bạn có thể thêm ràng buộc bảng bằng cách sử dụng chỉ mục duy nhất hiện có.
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)
Bây giờ không có sự khác biệt giữa mô tả ràng buộc cột.
Chỉ mục một phần
Trong khai báo ràng buộc bảng, bạn không thể tạo chỉ mục từng phần, nó xuất phát trực tiếp từ định nghĩa của create table ...
Trong khai báo chỉ mục duy nhất, bạn có thể đặt WHERE clause
để tạo chỉ mục từng phần. Bạn cũng có thể tạo chỉ mục trên biểu thức (không chỉ trên cột) và xác định một số tham số khác (đối chiếu, thứ tự sắp xếp, vị trí NULL).
Bạn không thể thêm ràng buộc bảng bằng cách sử dụng chỉ mục một phần.
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.