私はPostgreSQLを使用しており、テーブルから特定の列を持つすべてのテーブルを外部キー/参照としてリストしようとしています。これはできますか?この情報はinformation_schema
のどこかに保存されていると確信していますが、クエリを開始する方法がわかりません。
select R.TABLE_NAME
from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE u
inner join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS FK
on U.CONSTRAINT_CATALOG = FK.UNIQUE_CONSTRAINT_CATALOG
and U.CONSTRAINT_SCHEMA = FK.UNIQUE_CONSTRAINT_SCHEMA
and U.CONSTRAINT_NAME = FK.UNIQUE_CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE R
ON R.CONSTRAINT_CATALOG = FK.CONSTRAINT_CATALOG
AND R.CONSTRAINT_SCHEMA = FK.CONSTRAINT_SCHEMA
AND R.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
WHERE U.COLUMN_NAME = 'a'
AND U.TABLE_CATALOG = 'b'
AND U.TABLE_SCHEMA = 'c'
AND U.TABLE_NAME = 'd'
これは、完全なカタログ/スキーマ/名前トリプレットを使用して、3つのinformation_schemaビューすべてからdbテーブルを識別します。必要に応じて1つまたは2つドロップできます。
クエリは、テーブル 'd'の列 'a'に対して外部キー制約を持つすべてのテーブルを一覧表示します
他のソリューションはpostgresqlでの動作が保証されていません。constraint_nameが一意であることが保証されていないためです。したがって、誤検知が発生します。 PostgreSQLは、「$ 1」のような馬鹿げた制約に名前を付けていました。アップグレードを通じて保守してきた古いデータベースを持っている場合は、おそらくそれらのいくつかがまだ残っています。
この質問はAT PostgreSQLであり、それが使用しているものなので、内部postgresテーブルpg_classおよびpg_attributeを照会してより正確な結果を取得できます。
注:FKは複数の列に配置できるため、参照列(pg_attributeのattnum)はARRAYであり、これが回答でarray_aggを使用する理由です。
プラグインが必要なのは、TARGET_TABLE_NAMEのみです。
select
(select r.relname from pg_class r where r.oid = c.conrelid) as table,
(select array_agg(attname) from pg_attribute
where attrelid = c.conrelid and ARRAY[attnum] <@ c.conkey) as col,
(select r.relname from pg_class r where r.oid = c.confrelid) as ftable
from pg_constraint c
where c.confrelid = (select oid from pg_class where relname = 'TARGET_TABLE_NAME');
他の方法(特定のテーブルが参照するすべてのものをリストする)にしたい場合は、最後の行を次のように変更します。
where c.conrelid = (select oid from pg_class where relname = 'TARGET_TABLE_NAME');
ああ、実際の質問は特定の列を対象とすることだったので、次のように列名を指定できます。
select (select r.relname from pg_class r where r.oid = c.conrelid) as table,
(select array_agg(attname) from pg_attribute
where attrelid = c.conrelid and ARRAY[attnum] <@ c.conkey) as col,
(select r.relname from pg_class r where r.oid = c.confrelid) as ftable
from pg_constraint c
where c.confrelid = (select oid from pg_class where relname = 'TARGET_TABLE_NAME') and
c.confkey @> (select array_agg(attnum) from pg_attribute
where attname = 'TARGET_COLUMN_NAME' and attrelid = c.confrelid);
個人的には、列ではなく、参照された一意の制約に基づいてクエリを実行することを好みます。これは次のようになります。
SELECT rc.constraint_catalog,
rc.constraint_schema||'.'||tc.table_name AS table_name,
kcu.column_name,
match_option,
update_rule,
delete_rule
FROM information_schema.referential_constraints AS rc
JOIN information_schema.table_constraints AS tc USING(constraint_catalog,constraint_schema,constraint_name)
JOIN information_schema.key_column_usage AS kcu USING(constraint_catalog,constraint_schema,constraint_name)
WHERE unique_constraint_catalog='catalog'
AND unique_constraint_schema='schema'
AND unique_constraint_name='constraint name';
以下は、列名によるクエリを許可するバージョンです。
SELECT rc.constraint_catalog,
rc.constraint_schema||'.'||tc.table_name AS table_name,
kcu.column_name,
match_option,
update_rule,
delete_rule
FROM information_schema.referential_constraints AS rc
JOIN information_schema.table_constraints AS tc USING(constraint_catalog,constraint_schema,constraint_name)
JOIN information_schema.key_column_usage AS kcu USING(constraint_catalog,constraint_schema,constraint_name)
JOIN information_schema.key_column_usage AS ccu ON(ccu.constraint_catalog=rc.unique_constraint_catalog AND ccu.constraint_schema=rc.unique_constraint_schema AND ccu.constraint_name=rc.unique_constraint_name)
WHERE ccu.table_catalog='catalog'
AND ccu.table_schema='schema'
AND ccu.table_name='name'
AND ccu.column_name='column';
このクエリには、only参照されるtable nameおよびcolumn name、および外部キーの両側を含む結果セットを生成します。
select confrelid::regclass, af.attname as fcol,
conrelid::regclass, a.attname as col
from pg_attribute af, pg_attribute a,
(select conrelid,confrelid,conkey[i] as conkey, confkey[i] as confkey
from (select conrelid,confrelid,conkey,confkey,
generate_series(1,array_upper(conkey,1)) as i
from pg_constraint where contype = 'f') ss) ss2
where af.attnum = confkey and af.attrelid = confrelid and
a.attnum = conkey and a.attrelid = conrelid
AND confrelid::regclass = 'my_table'::regclass AND af.attname = 'my_referenced_column';
結果セットの例:
confrelid | fcol | conrelid | col
----------+----------------------+---------------+-------------
my_table | my_referenced_column | some_relation | source_type
my_table | my_referenced_column | some_feature | source_type
PostgreSQLフォーラムのレーンとクローグ に感謝します。
SELECT
main_table.table_name AS main_table_table_name,
main_table.column_name AS main_table_column_name,
main_table.constraint_name AS main_table_constraint_name,
info_other_table.table_name AS info_other_table_table_name,
info_other_table.constraint_name AS info_other_table_constraint_name,
info_other_table.column_name AS info_other_table_column_name
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE main_table
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS other_table
ON other_table.unique_constraint_name = main_table.constraint_name
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE info_other_table
ON info_other_table.constraint_name = other_table.constraint_name
WHERE main_table.table_name = 'MAIN_TABLE_NAME';
外部キーの名前とテーブルの名前を回復するための簡単な要求:
SELECT CONSTRAINT_NAME, table_name
FROM
information_schema.table_constraints
WHERE table_schema='public' and constraint_type='FOREIGN KEY'
psql
clientを使用する場合、\d table_name
コマンドを発行するだけで、指定されたテーブルを参照しているテーブルを確認できます。リンクされたドキュメントページから:
\d[S+] [ pattern ]
各リレーション(テーブル、ビュー、マテリアライズドビュー、インデックス、シーケンス、または外部テーブル)または
pattern
に一致する複合タイプについて、すべての列、それらのタイプ、テーブルスペース(デフォルトではない場合)および特別な属性を表示しますNOT NULL
などまたはデフォルト。関連するインデックス、制約、ルール、およびトリガーも表示されます。外部テーブルの場合、関連する外部サーバーも表示されます。