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

情報スキーマのreferential_constraints.unique_constraint_*列のNULL値

    テストセットアップ

    制約名をtest_def_abc_id_fkeyと想定します。 、Postgres11以前での設定から生じるデフォルト名。ただし、Postgres 12ではデフォルト名が改善されており、同じ設定で test_def_abc_id_abc_id2_fkeyが生成されることに注意してください。 。 Postgres 12のリリースノート:

    参照:

    db <> fiddle こちら

    それでは、明示的な名前 test_def_abc_fkeyを使用しましょう。 混乱を避けるためのFK制約の場合:

    CREATE TABLE test_abc (
      pk  int PRIMARY KEY
    , id  int NOT NULL
    , id2 int NOT NULL
    );
    
    CREATE UNIQUE INDEX test_abc_ids ON test_abc(id,id2);
    
    CREATE TABLE test_def (
      id      int PRIMARY KEY
    , abc_id  int
    , abc_id2 int
    , CONSTRAINT test_def_abc_fkey  -- !
         FOREIGN KEY (abc_id,abc_id2) REFERENCES test_abc(id,id2)
    );
    

    そして、その Postgres9.5-Postgres12で動作します。
    Postgres9.3でも。
    (私は実際の制約に間違った印象を持っていました 必要になります。)

    回答

    情報スキーマのクエリからの観察は次のとおりです。

    SELECT *
    FROM   information_schema.referential_constraints
    WHERE  constraint_name = 'test_def_abc_fkey';  -- unequivocal name
    

    行を取得しますが、3つのフィールド unique_constraint_catalog unique_constraint_schema およびunique_constraint_name NULLです 。

    説明は簡単そうです。これらの列は、マニュアルに記載されているように、次のように説明しています。

    ただし、 UNIQUE<はありません。 / code> 制約 UNIQUE インデックス UNIQUE 制約は、 UNIQUEを使用して実装されます Postgresのインデックス。制約はSQL標準で定義されており、インデックスは実装の詳細です。あなたが発見したもののような違いがあります。関連:

    実際のUNIQUEを使用した同じテスト 制約 期待どおりにデータを表示します:

    db <> fiddle こちら

    したがって、これは理にかなっているようです。特に情報スキーマ 以降 また、SQL標準化委員会によって定義されており、インデックスは標準化されておらず、制約のみが標準化されています。 (情報スキーマビューにインデックス情報はありません。)

    すべて明確ですか?完全ではありません。

    ただし

    別の情報スキーマビューがあります key_column_usage > 。その最後の列は次のように記述されています:

    太字 強調鉱山。ここでは、インデックス内の列の序数位置です。 とにかくリストされています:

    SELECT *
    FROM   information_schema.key_column_usage
    WHERE  constraint_name = 'test_def_abc_fkey';
    

    参照:

    db <> fiddle こちら

    一貫性がないようです。

    さらに悪いことに、マニュアル 実際のPRIMARYKEY またはUNIQUE FOREIGN KEYの作成には制約が必要になります 制約:

    ドキュメントのバグのようです ?ここで私がどこで間違っているのか誰にも指摘できない場合は、バグレポートを提出します。

    関連:

    ソリューション

    Postgresでは、システムカタログが実際の信頼できる情報源です。参照:

    したがって、このようなものを使用できます(fiddle にも追加したように 上記):

    SELECT c.conname
         , c.conrelid::regclass  AS fk_table, k1.fk_columns
         , c.confrelid::regclass AS ref_table, k2.ref_key_columns
    FROM   pg_catalog.pg_constraint c
    LEFT   JOIN LATERAL (
       SELECT ARRAY (
          SELECT a.attname
          FROM   pg_catalog.pg_attribute a
               , unnest(c.conkey) WITH ORDINALITY AS k(attnum, ord)
          WHERE  a.attrelid = c.conrelid
          AND    a.attnum = k.attnum
          ORDER  BY k.ord
          ) AS fk_columns
       ) k1 ON true
    LEFT   JOIN LATERAL (
       SELECT ARRAY (
          SELECT a.attname
          FROM   pg_catalog.pg_attribute a
               , unnest(c.confkey) WITH ORDINALITY AS k(attnum, ord)
          WHERE  a.attrelid = c.confrelid
          AND    a.attnum = k.attnum
          ORDER  BY k.ord
          ) AS ref_key_columns
       ) k2 ON true
    WHERE  conname = 'test_def_abc_fkey';
    

    返品:

    conname           | fk_table | fk_columns       | ref_table | ref_key_columns
    :---------------- | :------- | :--------------- | :-------- | :--------------
    test_def_abc_fkey | test_def | {abc_id,abc_id2} | test_abc  | {id,id2}       
    

    関連:




    1. C#でSQLクエリを直接実行する方法は?

    2. MySQLクレデンシャルをPHPスクリプトのどこに保存しますか?

    3. SQLクエリの結果を組み合わせる

    4. C#MySql CREATE USER