PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Walidacja unikatowości w bazie danych, gdy walidacja ma warunek na innej tabeli

Niestety, nie ma tak prostego i przejrzystego rozwiązania jak w przypadku Twoje poprzednie pytanie .

To powinno wystarczyć:

  • Dodaj nadmiarową flagę is_published do Child stół

    ALTER TABLE child ADD column is_published boolean NOT NULL;
    

    Ustaw DEFAULT FALSE lub cokolwiek, co zwykle masz w kolumnach nadrzędnych podczas wstawiania.
    Musi to być NOT NULL aby uniknąć luki z NULL wartości i domyślne MATCH SIMPLE zachowanie w kluczach obcych:
    Dwukolumnowe ograniczenie klucza obcego tylko wtedy, gdy trzecia kolumna NIE JEST NULL

  • Dodaj (pozornie bezsensowne, ale) unikalne ograniczenie do parent(parent_id, is_published)

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

    Od parent_id jest kluczem podstawowym, kombinacja byłaby unikalna. Ale jest to wymagane dla następującego ograniczenia fk.

  • Zamiast odwoływać się do parent(parent_id) z prostym ograniczeniem klucza obcego , utwórz wielokolumnowy klucz obcy w (parent_id, is_published) z ON UPDATE CASCADE .
    W ten sposób stan child.is_published jest utrzymywany i wymuszany przez system automatycznie i bardziej niezawodnie niż można zaimplementować za pomocą niestandardowych wyzwalaczy:

    ALTER TABLE child
    ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published)
    REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
    
  • Następnie dodaj częściowy UNIKALNY indeks jak w Twojej poprzedniej odpowiedzi.

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

Oczywiście podczas wstawiania wierszy w child tabela, w której musisz użyć aktualnego stanu parent.is_published Teraz. Ale o to właśnie chodzi:wymusić integralność referencyjną.

Pełny schemat

Lub zamiast dostosowywać istniejący schemat, oto kompletny układ:

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. PostgreSQL bez instalacji działa w systemie Windows, ale serwer nie uruchamia się w CentOS Linux

  2. Jak przechowywać i odpytywać bazę danych o strukturze drzewa?

  3. PHP PDO Postgres a typ kolumny Sqlite dla count(*)

  4. Postgresql:Skryptowanie wykonania psql z hasłem

  5. Data zapisu PostgreSQL w 'Lokalnej strefie czasowej', podczas gdy ustawiam ją na 'UTC' za pomocą Django