sql >> Database >  >> RDS >> PostgreSQL

Uniciteitsvalidatie in database wanneer validatie een voorwaarde heeft voor een andere tabel

Helaas is er geen oplossing die zo eenvoudig en schoon is als voor je vorige vraag .

Dit zou het werk moeten doen:

  • Voeg een overbodige vlag toe is_published aan het Child tafel

    ALTER TABLE child ADD column is_published boolean NOT NULL;
    

    Maak het DEFAULT FALSE of wat je gewoonlijk in bovenliggende kolommen hebt bij het invoegen.
    Het moet NOT NULL zijn om een ​​maas in de wet te vermijden met NULL waarden en standaard MATCH SIMPLE gedrag in buitenlandse sleutels:
    Twee-koloms refererende sleutel beperking alleen wanneer de derde kolom NIET NULL is

  • Voeg een (schijnbaar zinloze, maar toch) unieke beperking toe aan parent(parent_id, is_published)

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

    Sinds parent_id de primaire sleutel is, zou de combinatie hoe dan ook uniek zijn. Maar dat is vereist voor de volgende fk-beperking.

  • In plaats van te verwijzen naar parent(parent_id) met een simpele buitenlandse sleutelbeperking , maak een externe sleutel met meerdere kolommen op (parent_id, is_published) met ON UPDATE CASCADE .
    Op deze manier wordt de status van child.is_published wordt automatisch en betrouwbaarder door het systeem onderhouden en gehandhaafd dan u zou kunnen implementeren met aangepaste triggers:

    ALTER TABLE child
    ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published)
    REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
    
  • Voeg vervolgens een gedeeltelijke UNIEKE index toe zoals in je vorige antwoord.

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

Natuurlijk, bij het invoegen van rijen in de child tabel bent u gedwongen om de huidige status van parent.is_published . te gebruiken nu. Maar daar gaat het om:referentiële integriteit afdwingen.

Volledig schema

Of, in plaats van een bestaand schema aan te passen, is hier de volledige lay-out:

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. formaat datum wijzigen MySql

  2. Hoe een afbeelding ophalen uit een SQLite-database?

  3. Wat zijn sequentiële versus parallelle streams in Java?

  4. Entiteit Framework Code First - Tabelkolomsortering wijzigen