sql >> データベース >  >> RDS >> PostgreSQL

外部キーの関係を関連するサブタイプの行に制限する

    MATCH SIMPLEでの構築を簡素化する fk制約の動作

    デフォルトのMATCH SIMPLEで複数列の外部制約の少なくとも1つの列がある場合 動作はNULL 、制約は適用されません。その上に構築して、設計を大幅に簡素化できます。

    CREATE SCHEMA test;
    
    CREATE TABLE test.status(
       status_id  integer PRIMARY KEY
      ,sub        bool NOT NULL DEFAULT FALSE  -- TRUE .. *can* be sub-status
      ,UNIQUE (sub, status_id)
    );
    
    CREATE TABLE test.entity(
       entity_id  integer PRIMARY KEY
      ,status_id  integer REFERENCES test.status  -- can reference all statuses
      ,sub        bool      -- see examples below
      ,additional_col1 text -- should be NULL for main entities
      ,additional_col2 text -- should be NULL for main entities
      ,FOREIGN KEY (sub, status_id) REFERENCES test.status(sub, status_id)
         MATCH SIMPLE ON UPDATE CASCADE  -- optionally enforce sub-status
    );
    

    とても安い いくつかの追加のNULL列を格納するには(メインエンティティ用):

    ところで、ドキュメントごと:

    デモデータ:

    INSERT INTO test.status VALUES
      (1, TRUE)
    , (2, TRUE)
    , (3, FALSE);     -- not valid for sub-entities
    
    INSERT INTO test.entity(entity_id, status_id, sub) VALUES
      (11, 1, TRUE)   -- sub-entity (can be main, UPDATES to status.sub cascaded)
    , (13, 3, FALSE)  -- entity  (cannot be sub,  UPDATES to status.sub cascaded)
    , (14, 2, NULL)   -- entity  (can    be sub,  UPDATES to status.sub NOT cascaded)
    , (15, 3, NULL)   -- entity  (cannot be sub,  UPDATES to status.sub NOT cascaded)
    

    SQLフィドル (テストを含む)。

    単一のFKの代替

    もう1つのオプションは、(status_id, sub)のすべての組み合わせを入力することです。 statusに テーブル(status_idごとに2つしか存在できません )そしてfk制約は1つだけです:

    CREATE TABLE test.status(
       status_id  integer
      ,sub        bool DEFAULT FALSE
      ,PRIMARY KEY (status_id, sub)
    );
    
    CREATE TABLE test.entity(
       entity_id  integer PRIMARY KEY
      ,status_id  integer NOT NULL  -- cannot be NULL in this case
      ,sub        bool NOT NULL     -- cannot be NULL in this case
      ,additional_col1 text
      ,additional_col2 text
      ,FOREIGN KEY (status_id, sub) REFERENCES test.status
         MATCH SIMPLE ON UPDATE CASCADE  -- optionally enforce sub-status
    );
    
    INSERT INTO test.status VALUES
      (1, TRUE)       -- can be sub ...
      (1, FALSE)      -- ... and main
    , (2, TRUE)
    , (2, FALSE)
    , (3, FALSE);     -- only main
    

    など

    関連する回答:

    すべてのテーブルを保持する

    質問に含まれていない何らかの理由で4つのテーブルすべてが必要な場合は、dba.SEの非常によく似た質問に対するこの詳細な解決策を検討してください。

    継承

    ...あなたが説明することの別のオプションかもしれません。 いくつかの主要な制限がある場合 。関連する回答:




    1. クエリセットobjをパラメータとして渡すときにCeleryがエラーを発生させる

    2. MySQLの異なる列を持つテーブルでの複数の結合の結果から重複を削除する

    3. SQLの制約

    4. Mysql/Phpmyadminのドイツ語ウムラウト