sql >> Database teknologi >  >> RDS >> PostgreSQL

Unikitetsvalidering i databasen, når validering har en betingelse på en anden tabel

Desværre er der ingen løsning helt så enkel og ren som for dit tidligere spørgsmål .

Dette burde gøre jobbet:

  • Tilføj et redundant flag is_published til Child bord

    ALTER TABLE child ADD column is_published boolean NOT NULL;
    

    Gør det til DEFAULT FALSE eller hvad du typisk har i overordnede kolonner, når du indsætter.
    Det skal være NOT NULL for at undgå et smuthul med NULL værdier og standard MATCH SIMPLE adfærd i fremmede nøgler:
    To-søjlets fremmednøglebegrænsning kun, når tredje kolonne IKKE er NULL

  • Tilføj en (tilsyneladende meningsløs, men alligevel) unik begrænsning på parent(parent_id, is_published)

    ALTER TABLE parent ADD CONSTRAINT parent_fk_uni
    UNIQUE (parent_id, is_published);
    

    Siden parent_id er den primære nøgle, ville kombinationen være unik på begge måder. Men det er påkrævet for følgende fk-begrænsning.

  • I stedet for at henvise til parent(parent_id) med en simpel fremmednøglebegrænsning , opret en fremmednøgle med flere kolonner på (parent_id, is_published) med ON UPDATE CASCADE .
    På denne måde er tilstanden child.is_published vedligeholdes og håndhæves af systemet automatisk og mere pålideligt, end du kunne implementere med tilpassede triggere:

    ALTER TABLE child
    ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published)
    REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
    
  • Tilføj derefter et delvist UNIKT indeks ligesom i dit tidligere svar.

    CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text)
    WHERE is_published;
    

Selvfølgelig, når du indsætter rækker i child tabel er du tvunget til at bruge den aktuelle tilstand parent.is_published nu. Men det er pointen:at håndhæve referentiel integritet.

Fuldstændig skema

Eller, i stedet for at tilpasse et eksisterende skema, er her det komplette layout:

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. SQL Server 2016:Tilgængelighedsgruppeforbedringer

  2. Bliver den primære nøgle automatisk indekseret i MySQL?

  3. Hvordan får jeg min, median og max fra min forespørgsel i postgresql?

  4. Opsætning af Django og PostgreSQL på to forskellige EC2-instanser