sql >> Databasteknik >  >> RDS >> PostgreSQL

Unikhetsvalidering i databasen när validering har ett villkor på en annan tabell

Tyvärr finns det ingen lösning riktigt så enkel och ren som för din tidigare fråga .

Detta borde göra jobbet:

  • Lägg till en redundant flagga is_published till Child bord

    ALTER TABLE child ADD column is_published boolean NOT NULL;
    

    Gör det till DEFAULT FALSE eller vad du vanligtvis har i överordnade kolumner när du infogar.
    Det måste vara NOT NULL för att undvika ett kryphål med NULL värden och standard MATCH SIMPLE beteende i främmande nycklar:
    Tvåkolumns främmande nyckelbegränsning endast när den tredje kolumnen INTE är NULL

  • Lägg till en (till synes meningslös men ändå) unik begränsning på parent(parent_id, is_published)

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

    Sedan parent_id är den primära nyckeln, skulle kombinationen vara unik oavsett. Men det krävs för följande fk-begränsning.

  • Istället för att referera till parent(parent_id) med en enkel restriktion för främmande nyckel , skapa en främmande nyckel med flera kolumner på (parent_id, is_published) med ON UPDATE CASCADE .
    På detta sätt är tillståndet för child.is_published underhålls och upprätthålls av systemet automatiskt och mer tillförlitligt än vad du skulle kunna implementera med anpassade utlösare:

    ALTER TABLE child
    ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published)
    REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
    
  • Lägg sedan till ett partiellt UNIKT index som i ditt tidigare svar.

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

Naturligtvis när du infogar rader i child tabell du tvingas använda det nuvarande tillståndet för parent.is_published nu. Men det är poängen:att upprätthålla referensintegritet.

Fullständigt schema

Eller, istället för att anpassa ett befintligt schema, här är den fullständiga layouten:

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. Django mysql-fel

  2. bästa mysql-datakällans egenskaper för Grails tomcat jndi

  3. Välj inlägg från två taggar (OCH)

  4. viloläge map java Long till MySQL BIGINT-fel