SQL列出引用表中特定列的所有表

Gau*_*nia 53 sql database postgresql foreign-keys

我正在使用PostgreSQL,我试图将表中具有特定列的所有表列为外键/引用.可以这样做吗?我确定这些信息存储在某个地方,information_schema但我不知道如何开始查询它.

Ric*_*iwi 66

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'
Run Code Online (Sandbox Code Playgroud)

这使用完整的目录/模式/名称三元组来标识所有3个information_schema视图中的db表.您可以根据需要删除一个或两个.

该查询列出了对表'd'中的列'a'具有外键约束的所有表

  • 我看到了问题.`R`应该是`INFORMATION_SCHEMA.KEY_COLUMN_USAGE`,而不是`INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE`. (2认同)
  • 较旧的模式不适用于此,因为PostgreSQL过去没有以独特的方式命名约束.请参阅我的PostgreSQL特定答案. (2认同)

Ton*_* K. 56

其他解决方案不保证在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');
Run Code Online (Sandbox Code Playgroud)

如果你想以另一种方式(列出特定表所引用的所有内容),那么只需将最后一行更改为:

where c.conrelid = (select oid from pg_class where relname = 'TARGET_TABLE_NAME');
Run Code Online (Sandbox Code Playgroud)

哦,由于实际问题是针对特定列,您可以使用以下列指定列名:

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);
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是正确的答案 - 这是一个比选择的答案更准确的答案. (5认同)
  • 如果您有相同名称但在不同模式中的表,则需要在where where条件中进行过滤:`where c.confrelid =(从pg_class中选择oid,其中relname ='TARGET_TABLE_NAME'和relnamespace =(从pg_namespace中选择oid,其中nspname ='SCHEMA_NAME' ))` (2认同)

Ano*_*mie 9

就个人而言,我更喜欢基于引用的唯一约束而不是列进行查询.这看起来像这样:

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';
Run Code Online (Sandbox Code Playgroud)

这是一个允许按列名查询的版本:

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';
Run Code Online (Sandbox Code Playgroud)


val*_*tis 8

此查询需要引用的表名列名,并生成包含外键两侧的结果集.

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';
Run Code Online (Sandbox Code Playgroud)

示例结果集:

confrelid |         fcol         |   conrelid    |     col
----------+----------------------+---------------+-------------
 my_table | my_referenced_column | some_relation | source_type
 my_table | my_referenced_column | some_feature  | source_type
Run Code Online (Sandbox Code Playgroud)

所有归功于Lane和Krogh在PostgreSQL论坛上.

  • 这应该是公认的答案 (2认同)

小智 5

恢复外键名称以及表名称的简单请求:

SELECT CONSTRAINT_NAME, table_name
FROM
   information_schema.table_constraints 
WHERE table_schema='public' and constraint_type='FOREIGN KEY'
Run Code Online (Sandbox Code Playgroud)