Thiết lập thử nghiệm
Bạn giả sử tên ràng buộc test_def_abc_id_fkey
, tên mặc định do thiết lập của bạn trong Postgres 11 trở lên. Tuy nhiên, đáng chú ý là các tên mặc định đã được cải thiện cho Postgres 12, trong đó thiết lập tương tự dẫn đến test_def_abc_id_abc_id2_fkey
. Ghi chú phát hành cho Postgres 12:
Xem:
db <> fiddle tại đây
Vì vậy, hãy sử dụng tên rõ ràng test_def_abc_fkey
đối với ràng buộc FK để tránh nhầm lẫn:
CREATE TABLE test_abc (
pk int PRIMARY KEY
, id int NOT NULL
, id2 int NOT NULL
);
CREATE UNIQUE INDEX test_abc_ids ON test_abc(id,id2);
CREATE TABLE test_def (
id int PRIMARY KEY
, abc_id int
, abc_id2 int
, CONSTRAINT test_def_abc_fkey -- !
FOREIGN KEY (abc_id,abc_id2) REFERENCES test_abc(id,id2)
);
Và hoạt động trong Postgres 9.5 - Postgres 12.
Ngay cả trong Postgres 9.3.
(Tôi đã có ấn tượng sai về một ràng buộc thực tế sẽ được yêu cầu.)
Trả lời
Quan sát của bạn từ việc truy vấn lược đồ thông tin nắm giữ:
SELECT *
FROM information_schema.referential_constraints
WHERE constraint_name = 'test_def_abc_fkey'; -- unequivocal name
Chúng tôi nhận được một hàng, nhưng ba trường unique_constraint_catalog
, unique_constraint_schema
và unique_constraint_name
là NULL
.
Lời giải thích có vẻ đơn giản. Các cột đó mô tả, như sách hướng dẫn sử dụng:
Nhưng không có UNIQUE
ràng buộc
, chỉ là UNIQUE
chỉ mục
. Một UNIQUE
ràng buộc được thực hiện bằng cách sử dụng UNIQUE
chỉ mục trong Postgres. Các ràng buộc được xác định bởi tiêu chuẩn SQL, các chỉ mục là chi tiết triển khai. Có những khác biệt giống như một trong những bạn đã phát hiện ra. Có liên quan:
Thử nghiệm tương tự với UNIQUE
thực tế ràng buộc hiển thị dữ liệu như mong đợi:
db <> fiddle tại đây
Vì vậy, điều này dường như có ý nghĩa. Đặc biệt là vì lược đồ thông tin cũng được xác định bởi ủy ban tiêu chuẩn SQL và các chỉ mục không được tiêu chuẩn hóa, chỉ có các ràng buộc. (Không có thông tin chỉ mục trong các chế độ xem giản đồ thông tin.)
Tất cả rõ ràng? Không hoàn toàn.
Tuy nhiên
Có một chế độ xem giản đồ thông tin khác key_column_usage
. Cột cuối cùng của nó được mô tả là:
In đậm nhấn mạnh của tôi. Đây, vị trí thứ tự của cột trong chỉ mục vẫn được liệt kê:
SELECT *
FROM information_schema.key_column_usage
WHERE constraint_name = 'test_def_abc_fkey';
Xem:
db <> fiddle tại đây
Có vẻ không nhất quán.
Còn tệ hơn, hướng dẫn sử dụng
tuyên bố rằng một PRIMARY KEY
thực tế hoặc UNIQUE
ràng buộc sẽ được yêu cầu để tạo FOREIGN KEY
ràng buộc:
Có vẻ là một lỗi tài liệu ? Nếu không ai có thể chỉ ra nơi tôi làm sai ở đây, tôi sẽ gửi một báo cáo lỗi.
Có liên quan:
Giải pháp
Trong Postgres, danh mục hệ thống là nguồn chân lý thực tế. Xem:
Vì vậy, bạn có thể sử dụng một cái gì đó như thế này (như tôi cũng đã thêm vào fiddle trên):
SELECT c.conname
, c.conrelid::regclass AS fk_table, k1.fk_columns
, c.confrelid::regclass AS ref_table, k2.ref_key_columns
FROM pg_catalog.pg_constraint c
LEFT JOIN LATERAL (
SELECT ARRAY (
SELECT a.attname
FROM pg_catalog.pg_attribute a
, unnest(c.conkey) WITH ORDINALITY AS k(attnum, ord)
WHERE a.attrelid = c.conrelid
AND a.attnum = k.attnum
ORDER BY k.ord
) AS fk_columns
) k1 ON true
LEFT JOIN LATERAL (
SELECT ARRAY (
SELECT a.attname
FROM pg_catalog.pg_attribute a
, unnest(c.confkey) WITH ORDINALITY AS k(attnum, ord)
WHERE a.attrelid = c.confrelid
AND a.attnum = k.attnum
ORDER BY k.ord
) AS ref_key_columns
) k2 ON true
WHERE conname = 'test_def_abc_fkey';
Lợi nhuận:
conname | fk_table | fk_columns | ref_table | ref_key_columns :---------------- | :------- | :--------------- | :-------- | :-------------- test_def_abc_fkey | test_def | {abc_id,abc_id2} | test_abc | {id,id2}
Có liên quan:
- Tìm tên bảng được tham chiếu bằng cách sử dụng bảng, trường và tên giản đồ
- Tìm trường được tham chiếu ( s) ràng buộc khóa ngoại
- Làm cách nào để tìm các bảng tham chiếu đến một hàng cụ thể thông qua khóa ngoại?