テストセットアップ
制約名を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 こちら
したがって、これは理にかなっているようです。特に
すべて明確ですか?完全ではありません。
ただし
別の情報スキーマビューがあります 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}
関連:
- テーブル、フィールド、スキーマ名を使用して、参照されているテーブル名を検索します
- 参照フィールドを検索( s)外部キー制約の
- 外部キーを介して特定の行を参照するテーブルを見つけるにはどうすればよいですか?