Bạn có thể thực hiện điều đó mà không cần thủ thuật bẩn . Chỉ cần mở rộng khóa ngoại tham chiếu đến tùy chọn đã chọn để bao gồm variable_id
ngoài choice_id
.
Đây là một bản demo đang hoạt động. Bảng tạm thời, vì vậy bạn có thể dễ dàng chơi với nó:
CREATE TABLE systemvariables (variable_id int PRIMARY KEY, choice_id int, biến văn bản); INSERT INTO systemvariables (variable_id, variable) VALUES (1, 'var1'), (2, 'var2'), (3, 'var3'); CREATE TABLE variableoptions (option_id int PRIMARY KEY, variable_id int TÀI LIỆU THAM KHẢO các biến hệ thống TRÊN CẬP NHẬT CASCADE ON XÓA CASCADE, văn bản tùy chọn, DUY NHẤT (option_id, biến_id) - cần thiết cho FK); ALTER TABLE systemvariables ADD CONSTRAINT systemvariables_choice_id_fk FOREIGN KEY (choice_id, variable_id) REFERENCES biến tùy chọn (_ option_id, biến_id); INSERT INTO biến 1 ', 1), (2,' var1_op2 ', 1), (3,' var1_op3 ', 1), (4,' var2_op1 ', 2), (5,' var2_op2 ', 2), (6,' var3_op1 ', 3);
Cho phép chọn một tùy chọn được liên kết:
CẬP NHẬT các biến hệ thống SET lựa chọn_id =2 WHERE biến_id =1; CẬP NHẬT các biến hệ thống SET lựa chọn_id =5 WHERE biến_id =2; CẬP NHẬT các biến hệ thống SET lựa chọn_id =6 WHERE biến_id =3;
Nhưng không có gì vượt quá giới hạn:
CẬP NHẬT các biến hệ thống SET choice_id =7 WHERE biến_id =3; CẬP NHẬT các biến hệ thống SET lựa chọn_id =4 WHERE biến_id =1;
Chính xác những gì bạn muốn.
Tất cả các cột chính KHÔNG ĐẦY ĐỦ
Tôi nghĩ rằng tôi đã tìm thấy giải pháp tốt hơn trong câu trả lời sau này:
- Cách xử lý với các phần chèn phụ thuộc lẫn nhau
Giải quyết câu hỏi của @ ypercube trong nhận xét, để tránh các mục nhập có liên kết không xác định làm cho tất cả các cột chính KHÔNG ĐẦY ĐỦ
, bao gồm cả khóa ngoại.
Sự phụ thuộc vòng tròn thông thường sẽ làm cho điều đó không thể thực hiện được. Đó là quả trứng gà cổ điển vấn đề:một trong cả hai phải ở đó đầu tiên để sinh ra cái còn lại. Nhưng thiên nhiên đã tìm ra cách giải quyết vấn đề đó và Postgres cũng vậy: các ràng buộc khóa ngoại có thể hoãn lại .
CREATE TABLE systemvariables (variable_id int PRIMARY KEY, variable text, choice_id int NOT NULL); CREATE TABLE variableoptions (option_id int PRIMARY KEY, option text, variable_id int NOT NULL DEFERRED, UNIQUE (option_id, biến_id) - cần cho khóa ngoại); ALTER TABLE systemvariablesADD CONSTRAINT systemvariables_choice_id_fk FOREIGN KEY (lựa chọn_id, biến_id) REFERENCES biến tùy chọn (option_id, biến_id) DEFERRABLE BAN ĐẦU; - không có CASCADING ở đây!
Mới các biến và các tùy chọn liên quan phải được chèn trong cùng một giao dịch:
BEGIN; INSERT INTO systemvariables (variable_id, variable, choice_id) VALUES (1, 'var1', 2), (2, 'var2', 5), (3, 'var3', 6); INSERT INTO biến tùy chọn (option_id, option, biến_id) VALUES (1, 'var1_op1', 1), (2, 'var1_op2', 1), (3, 'var1_op3', 1), (4, 'var2_op1', 2), (5, 'var2_op2', 2), (6, 'var3_op1', 3); HẾT;
NOT NULL
ràng buộc không thể được trì hoãn, nó được thực thi ngay lập tức. Nhưng ràng buộc khóa ngoại có thể , bởi vì chúng tôi đã định nghĩa nó theo cách đó. Nó được kiểm tra khi kết thúc giao dịch, điều này tránh được vấn đề quả trứng gà.
Trong đã chỉnh sửa này kịch bản, cả hai khóa ngoại đều bị hoãn . Bạn có thể nhập các biến và tùy chọn theo trình tự tùy ý.
Bạn thậm chí có thể làm cho nó hoạt động với ràng buộc FK đơn giản không thể hoãn lại nếu bạn nhập các mục nhập có liên quan trong cả hai bảng trong một câu lệnh sử dụng CTE như được nêu chi tiết trong câu trả lời được liên kết.
Bạn có thể nhận thấy rằng ràng buộc khóa ngoại đầu tiên không có CASCADE
bổ nghĩa. (Sẽ không hợp lý nếu cho phép thay đổi đối với variableoptions.variable_id
để xếp tầng trở lại.
Mặt khác, khóa ngoại thứ hai có CASCADE
sửa đổi và được định nghĩa DEFERRABLE
dù sao thì. Điều này mang một số hạn chế. Hướng dẫn sử dụng:
Các hành động tham chiếu khác với
KHÔNG HÀNH ĐỘNG
séc không thể được hoãn lại, ngay cả khi ràng buộc được tuyên bố là có thể hoãn lại.
KHÔNG HÀNH ĐỘNG
là mặc định.
Vì vậy, kiểm tra tính toàn vẹn của tham chiếu trên INSERT
được hoãn lại, nhưng các hành động xếp tầng được khai báo trên DELETE
và UPDATE
không. Điều sau không được phép trong PostgreSQL 9.0 trở lên vì các ràng buộc được thực thi sau mỗi câu lệnh:
tùy chọn CẬP NHẬT SET var_id =4 WHERE var_id =5; XÓA TỪ var WHERE var_id =5;
Chi tiết:
- Ràng buộc đã xác định CÓ THỂ XÁC ĐỊNH BAN ĐẦU NGAY LẬP TỨC vẫn bị XÁC ĐỊNH?