Sayangnya, tidak ada solusi yang sesederhana dan sebersih pertanyaan Anda sebelumnya .
Ini harus berhasil:
-
Tambahkan bendera berlebihan
is_published
keChild
tabelALTER TABLE child ADD column is_published boolean NOT NULL;
Jadikan
DEFAULT FALSE
atau apa pun yang biasanya Anda miliki di kolom induk saat menyisipkan.
HarusNOT NULL
untuk menghindari celah denganNULL
nilai dan defaultMATCH SIMPLE
perilaku dalam kunci asing:
Kendala kunci asing dua kolom hanya jika kolom ketiga TIDAK NULL -
Tambahkan (tampaknya tidak ada gunanya, namun) batasan unik pada
parent(parent_id, is_published)
ALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);
Sejak
parent_id
adalah kunci utama, kombinasinya akan unik. Tapi itu diperlukan untuk batasan fk berikut. -
Alih-alih merujuk
parent(parent_id)
dengan batasan kunci asing , buat kunci asing multi-kolom di(parent_id, is_published)
denganON UPDATE CASCADE
.
Dengan cara ini, statuschild.is_published
dipelihara dan ditegakkan oleh sistem secara otomatis dan lebih andal daripada yang dapat Anda terapkan dengan pemicu khusus:ALTER TABLE child ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published) REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
-
Kemudian tambahkan indeks UNIK parsial seperti pada jawaban Anda sebelumnya.
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text) WHERE is_published;
Tentu saja, saat menyisipkan baris di child
tabel Anda terpaksa menggunakan status parent.is_published
saat ini sekarang. Tapi itulah intinya:untuk menegakkan integritas referensial.
Skema lengkap
Atau, alih-alih mengadaptasi skema yang ada, berikut tata letak lengkapnya:
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;