web-dev-qa-db-ja.com

テーブル内の特定の列を参照するすべてのテーブルをリストするSQL

私はPostgreSQLを使用しており、テーブルから特定の列を持つすべてのテーブルを外部キー/参照としてリストしようとしています。これはできますか?この情報はinformation_schemaのどこかに保存されていると確信していますが、クエリを開始する方法がわかりません。

50
Gaurav Dadhania
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'に対して外部キー制約を持つすべてのテーブルを一覧表示します

62
RichardTheKiwi

他のソリューションは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);
56
Tony K.

個人的には、列ではなく、参照された一意の制約に基づいてクエリを実行することを好みます。これは次のようになります。

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';
9
Anomie

このクエリには、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フォーラムのレーンとクローグ に感謝します。

8
vallismortis
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';
4
Lucas

外部キーの名前とテーブルの名前を回復するための簡単な要求:

SELECT CONSTRAINT_NAME, table_name
FROM
   information_schema.table_constraints 
WHERE table_schema='public' and constraint_type='FOREIGN KEY'
3
Fadid

psql clientを使用する場合、\d table_nameコマンドを発行するだけで、指定されたテーブルを参照しているテーブルを確認できます。リンクされたドキュメントページから:

\d[S+] [ pattern ]

各リレーション(テーブル、ビュー、マテリアライズドビュー、インデックス、シーケンス、または外部テーブル)またはpatternに一致する複合タイプについて、すべての列、それらのタイプ、テーブルスペース(デフォルトではない場合)および特別な属性を表示しますNOT NULLなどまたはデフォルト。関連するインデックス、制約、ルール、およびトリガーも表示されます。外部テーブルの場合、関連する外部サーバーも表示されます。

0
Eugene Yarmash