PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Validasi keunikan dalam database ketika validasi memiliki kondisi di tabel lain

Sayangnya, tidak ada solusi yang sesederhana dan sebersih pertanyaan Anda sebelumnya .

Ini harus berhasil:

  • Tambahkan bendera berlebihan is_published ke Child tabel

    ALTER TABLE child ADD column is_published boolean NOT NULL;
    

    Jadikan DEFAULT FALSE atau apa pun yang biasanya Anda miliki di kolom induk saat menyisipkan.
    Harus NOT NULL untuk menghindari celah dengan NULL nilai dan default MATCH 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) dengan ON UPDATE CASCADE .
    Dengan cara ini, status child.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;



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. String -> java.util.Date -> java.sql.Date (dengan cap waktu)

  2. Cara mendeklarasikan variabel dalam kueri PostgreSQL

  3. Agregat PostgreSQL atau fungsi jendela untuk mengembalikan nilai terakhir saja

  4. Apa yang dimaksud dengan batasan pengecualian `KECUALIKAN MENGGUNAKAN Gist (c WITH &&)`?

  5. PostgreSQL:apakah mungkin untuk memberikan nama khusus untuk PRIMARY KEY atau UNIQUE?