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

2つの主キーを指す外部キーを作成するにはどうすればよいですか?

    FK制約のルール

    タイトルとテキストの最後にある質問に答えるには:

    「2つの主キーを参照する1つの外部キーを作成する方法を知りたいのですが。」

    それは不可能です。

    • 外部キー> 制約は1つのみを指すことができます テーブルと各テーブルは1つしか持つことができません 主キー 制約。

    • または、複数にすることもできます 外部キー 1つを参照する同じ列の制約 PRIMARY KEY それぞれ(異なる)テーブルの。 (めったに役に立ちません。)

    ただし 、単一のPKまたはFKができます 複数の列にまたがります。
    そして、FKは、PKだけでなく、ターゲット内の明示的に定義された一意の(セットの)列を参照できます。 マニュアル:

    複数列のPKまたは 一意 制約は、列タイプが一致する複数列のFK制約によってのみ参照できます。

    質問すること

    UNIQUEの列リストで同じ列を複数回使用することは許可されていないため またはPRIMARYKEY 制約、 FOREIGN KEYのターゲットリスト 同じ列を複数回使用することもできません。ただし、ソースで同じ列を複数回使用することを妨げるものは何もありません。 リスト。ここに、あなたが求めていることを実装する可能性があります(しかし、おそらくそうするつもりはありませんでした):

    " team_statisticsで テーブルteam_statistics.team_id matches.team_idを参照する外部キーである必要があります およびmatches.team_id1 "

    (team_id、team_id1)の組み合わせ テーブル内のmatches UNIQUEを定義する必要があります 。 team_statistics.team_idの値 team =team1の場合に制限されます テーブル内のmatches 論理的帰結として:

    ALTER TABLE matches
    ADD constraint matches_teams_groups_uni UNIQUE (team_id, team_id1);
    
    ALTER TABLE team_statistics
      ADD constraint team_statistics_team_group fkey
      FOREIGN KEY (team_id, team_id)  -- same column twice!
      REFERENCES matches(team_id, team_id1);

    特定の設定では意味があるかもしれませんが、あなたの設定では意味がありません。

    おそらく必要なもの

    私の知識に基づいた推測では、次のようなものが必要です:

    (match_id、team_id) テーブルteam_statisticsどちらかを参照する外部キーである必要があります (match_id、team_id) または (match_id、team_id1) テーブル内のmatches

    そして、それはFK制約と2つのテーブルだけでは不可能です。あなたはできた CHECKを悪用する 偽のIMMUTABLEによる制約 関数を作成し、 NOT VALID にします 。この回答の「チェック制約のある安い」の章を参照してください:

    しかし、それは高度なトリックであり、信頼性は低くなります。ここでの私の提案ではないので、詳しく説明するつもりはありません。 正規化 することをお勧めします 次のような便利な方法でスキーマを作成します。

    CREATE TABLE team (team_id serial PRIMARY KEY
                     , team text NOT NULL UNIQUE);     -- add more attributes for team
    
    CREATE TABLE match (match_id serial PRIMARY KEY);  -- add more attributes for match
    
    CREATE TABLE match_team (
       match_id  int  REFERENCES match  -- short notation for FK
     , team_id   int  REFERENCES team
     , home boolean                     -- TRUE for home team, FALSE for away team
     , innings_score int
     -- more attributes of your original "team_statistics"
     , PRIMARY KEY (match_id, team_id, home)  -- !!! (1st column = match_id)
     , UNIQUE (team_id, match_id)             -- optional, (1st column = team_id)
    );
    

    ホーム 試合のホームチームをマークしますが、PKに含めることにより、試合ごとに最大2チームに制限されます。 。 (PK列は NOT NULLで定義されています 暗黙的に。)

    オプションのUNIQUE (team_id、match_id)の制約 チームが自分たちと対戦するのを防ぎます。インデックス列の反転シーケンスを使用することにより(ルールの適用には関係ありません)、これはPKを補完するインデックスも提供します。これは通常も役立ちます。参照:

    あなたはできた 別のmatch_team_statisticsを追加します 、ただし、これは match_team のオプションの1:1拡張機能にすぎません。 今。または、 match_teamに列を追加するだけです。 。

    ビューを追加する場合があります 次のような一般的なディスプレイの場合:

    CREATE VIEW match_result AS
    SELECT m.match_id
         , concat_ws(' : ', t1.team, t2.team) AS home_vs_away_team
         , concat_ws(' : ', mt1.innings_score, mt2.innings_score) AS result
    FROM   match           m
    LEFT   JOIN match_team mt1 ON mt1.match_id = m.match_id AND mt1.home
    LEFT   JOIN team       t1  ON t1.team_id = mt1.team_id
    LEFT   JOIN match_team mt2 ON mt2.match_id = m.match_id AND NOT mt2.home
    LEFT   JOIN team       t2  ON t2.team_id = mt2.team_id;
    

    基本的なアドバイス:



    1. 非常に大きなテーブルでの(列ストア)圧縮の楽しみ–パート2

    2. GUIを使用してMySQLWorkbenchで現在の接続を表示する方法

    3. データベースでCloseが明示的に呼び出されることはありません

    4. 平日ごとのMysqlグループ、欠落している平日を記入