Chỉ DEFERRABLE
các ràng buộc có thể được hoãn lại.
Trước tiên, hãy để tôi đề xuất các lựa chọn thay thế vượt trội:
1. INSERT
theo thứ tự
Đảo ngược trình tự của INSERT
tuyên bố và không cần phải hoãn lại. Đơn giản nhất và nhanh nhất - nếu có thể.
2. Lệnh đơn
Làm điều đó trong một lệnh duy nhất . Sau đó, vẫn không có gì cần phải hoãn lại, vì các ràng buộc không thể hoãn lại được kiểm tra sau mỗi lệnh và CTE được coi là một phần của lệnh đơn:
WITH ins1 AS (
INSERT INTO b(j) VALUES(2)
)
INSERT INTO a(i) VALUES(2);
Trong khi ở đó, bạn có thể sử dụng lại các giá trị cho INSERT
đầu tiên; an toàn hơn / thuận tiện hơn cho một số trường hợp nhất định hoặc chèn nhiều hàng:
WITH ins1 AS (
INSERT INTO b(j) VALUES(3)
RETURNING j
)
INSERT INTO a(i)
SELECT j FROM ins1;
Nhưng tôi cần các ràng buộc hoãn lại! (Thật không?)
ALTER TABLE b ADD CONSTRAINT fkey_ij FOREIGN KEY (j)
REFERENCES a (i) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE; -- !!!
Sau đó, mã gốc của bạn hoạt động (chậm hơn một chút, vì các ràng buộc hoãn lại thêm chi phí).
db <> fiddle tại đây
Có liên quan:
Câu trả lời ban đầu của tôi đã trích dẫn sách hướng dẫn :
Nhưng điều đó đã gây hiểu lầm vì nó chỉ áp dụng cho "hành động tham chiếu", tức là những gì sẽ xảy ra ON UPDATE
hoặc ON DELETE
đến các hàng trong bảng được tham chiếu. Trường hợp hiện tại không phải là một trong những trường hợp đó - như @ zer0hedge đã chỉ ra
.