sql >> Databáze >  >> RDS >> PostgreSQL

Ověření jedinečnosti v databázi, když má ověření podmínku na jiné tabulce

Bohužel neexistuje řešení tak jednoduché a čisté jako pro vaše předchozí otázka .

Toto by mělo fungovat:

  • Přidejte nadbytečný příznak is_published na Child tabulka

    ALTER TABLE child ADD column is_published boolean NOT NULL;
    

    Nastavte jej na DEFAULT FALSE nebo cokoli, co obvykle máte v nadřazených sloupcích při vkládání.
    Musí být NOT NULL abyste se vyhnuli mezeře s NULL hodnoty a výchozí MATCH SIMPLE chování v cizích klíčích:
    Dvousloupcové omezení cizího klíče pouze v případě, že třetí sloupec NENÍ NULL

  • Přidejte (zdánlivě nesmyslné, ale přesto) jedinečné omezení na parent(parent_id, is_published)

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

    Od parent_id je primární klíč, kombinace by byla jedinečná v obou směrech. Ale to je vyžadováno pro následující omezení fk.

  • Místo odkazování na parent(parent_id) s jednoduchým omezení cizího klíče , vytvořte cizí klíč s více sloupci na (parent_id, is_published) pomocí ON UPDATE CASCADE .
    Tímto způsobem bude stav child.is_published je udržován a vynucován systémem automaticky a spolehlivěji, než byste mohli implementovat pomocí vlastních spouštěčů:

    ALTER TABLE child
    ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published)
    REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
    
  • Poté přidejte částečný UNIQUE index jako ve vaší předchozí odpovědi.

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

Samozřejmě při vkládání řádků do child tabulky jste nuceni použít aktuální stav parent.is_published Nyní. Ale o to jde:prosadit referenční integritu.

Úplné schéma

Nebo namísto přizpůsobení existujícího schématu zde je kompletní rozvržení:

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. MySQL - Najděte body v okruhu z databáze

  2. Vnořená knihovna modelu sady PHP

  3. Chyba MySQL 1064 při přidávání cizího klíče pomocí MySQL Workbench

  4. Která je podřízená tabulka v Identifikačním nebo Neidentifikujícím vztahu?