Thật không may, không có giải pháp nào đơn giản và sạch sẽ như đối với câu hỏi trước của bạn .
Điều này sẽ thực hiện công việc:
-
Thêm cờ dự phòng
is_published
đếnChild
bảngALTER TABLE child ADD column is_published boolean NOT NULL;
Đặt nó thành
DEFAULT FALSE
hoặc bất kỳ thứ gì bạn thường có trong các cột chính khi chèn.
Nó cần phải làNOT NULL
để tránh sơ hở vớiNULL
giá trị vàMATCH SIMPLE
mặc định hành vi trong khóa ngoại:
Ràng buộc khóa ngoại hai cột chỉ khi cột thứ ba KHÔNG ĐẦY ĐỦ -
Thêm một ràng buộc duy nhất (dường như vô nghĩa, nhưng) trên
parent(parent_id, is_published)
ALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);
Kể từ
parent_id
là khóa chính, cách kết hợp sẽ là duy nhất. Nhưng điều đó là bắt buộc đối với ràng buộc fk sau đây. -
Thay vì tham chiếu đến
parent(parent_id)
đơn giản với ràng buộc khóa ngoại , tạo khóa ngoại nhiều cột trên(parent_id, is_published)
vớiON UPDATE CASCADE
.
Bằng cách này, trạng thái củachild.is_published
được duy trì và thực thi bởi hệ thống tự động và đáng tin cậy hơn những gì bạn có thể triển khai với các trình kích hoạt tùy chỉnh:ALTER TABLE child ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published) REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
-
Sau đó, thêm một một phần chỉ mục UNIQUE như trong câu trả lời trước của bạn.
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text) WHERE is_published;
Tất nhiên, khi chèn các hàng trong child
bảng bạn buộc phải sử dụng trạng thái hiện tại của parent.is_published
bây giờ. Nhưng đó là vấn đề:thực thi tính toàn vẹn của tham chiếu.
Lược đồ hoàn chỉnh
Hoặc, thay vì điều chỉnh một lược đồ hiện có, đây là bố cục hoàn chỉnh:
CREATE TABLE parent(
parent_id serial PRIMARY KEY
, is_published bool NOT NULL DEFAULT FALSE
--, more columns ...
, UNIQUE (parent_id, is_published) -- required for fk
);
CREATE TABLE child (
child_id serial PRIMARY KEY
, parent_id integer NOT NULL
, is_published bool NOT NULL DEFAULT FALSE
, txt text
, FOREIGN KEY (parent_id, is_published)
REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE
);
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text)
WHERE is_published;