Postgres:SQL列出表外键

有没有办法使用SQL来列出给定表的所有外键? 我知道表名/模式,我可以插入。

你可以通过information_schema表来做到这一点。 例如:

SELECT tc.constraint_name, tc.table_name, kcu.column_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name WHERE constraint_type = 'FOREIGN KEY' AND tc.table_name='mytable'; 

psql做到这一点,如果你启动psql:

 psql -E 

它会显示你到底在执行什么查询。 在find外键的情况下,它是:

 SELECT conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef FROM pg_catalog.pg_constraint r WHERE r.conrelid = '16485' AND r.contype = 'f' ORDER BY 1 

在这种情况下,16485是我正在查看的表的oid – 你可以通过将你的表名转换为regclass来得到这个表:

 WHERE r.conrelid = 'mytable'::regclass 

模式 – 限定表名称,如果它不是唯一的(或在您的search_path的第一个):

 WHERE r.conrelid = 'myschema.mytable'::regclass 

Ollyc的答案是好的,因为它不是Postgres特定的,但是,当外键引用多个列时,它会崩溃。 以下查询适用于任意数量的列,但严重依赖于Postgres扩展:

 select att2.attname as "child_column", cl.relname as "parent_table", att.attname as "parent_column", conname from (select unnest(con1.conkey) as "parent", unnest(con1.confkey) as "child", con1.confrelid, con1.conrelid, con1.conname from pg_class cl join pg_namespace ns on cl.relnamespace = ns.oid join pg_constraint con1 on con1.conrelid = cl.oid where cl.relname = 'child_table' and ns.nspname = 'child_schema' and con1.contype = 'f' ) con join pg_attribute att on att.attrelid = con.confrelid and att.attnum = con.child join pg_class cl on cl.oid = con.confrelid join pg_attribute att2 on att2.attrelid = con.conrelid and att2.attnum = con.parent 

对ollyc配方的扩展:

 CREATE VIEW foreign_keys_view AS SELECT tc.table_name, kcu.column_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name WHERE constraint_type = 'FOREIGN KEY'; 

然后:

SELECT * FROM foreign_keys_view WHERE table_name='YourTableNameHere' ;

检查你的解决scheme后,不要忘记标记这一点,当你罚款这有益的

http://errorbank.blogspot.com/2011/03/list-all-foreign-keys-references-for.html

 SELECT o.conname AS constraint_name, (SELECT nspname FROM pg_namespace WHERE oid=m.relnamespace) AS source_schema, m.relname AS source_table, (SELECT a.attname FROM pg_attribute a WHERE a.attrelid = m.oid AND a.attnum = o.conkey[1] AND a.attisdropped = false) AS source_column, (SELECT nspname FROM pg_namespace WHERE oid=f.relnamespace) AS target_schema, f.relname AS target_table, (SELECT a.attname FROM pg_attribute a WHERE a.attrelid = f.oid AND a.attnum = o.confkey[1] AND a.attisdropped = false) AS target_column FROM pg_constraint o LEFT JOIN pg_class c ON c.oid = o.conrelid LEFT JOIN pg_class f ON f.oid = o.confrelid LEFT JOIN pg_class m ON m.oid = o.conrelid WHERE o.contype = 'f' AND o.conrelid IN (SELECT oid FROM pg_class c WHERE c.relkind = 'r'); 

此查询也适用于复合键:

 select c.constraint_name , x.table_schema as schema_name , x.table_name , x.column_name , y.table_schema as foreign_schema_name , y.table_name as foreign_table_name , y.column_name as foreign_column_name from information_schema.referential_constraints c join information_schema.key_column_usage x on x.constraint_name = c.constraint_name join information_schema.key_column_usage y on y.ordinal_position = x.position_in_unique_constraint and y.constraint_name = c.unique_constraint_name order by c.constraint_name, x.ordinal_position 

我认为你在找什么和非常接近@ollyc写的是这样的:

 SELECT tc.constraint_name, tc.table_name, kcu.column_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name WHERE constraint_type = 'FOREIGN KEY' AND ccu.table_name='YourTableNameHere'; 

这将列出使用您指定的表作为外键的所有表

您可以使用PostgreSQL系统目录 。 也许你可以查询pg_constraint来请求外键。 您也可以使用信息模式

在PostgreSQL提示符下发出\d+ tablename ,除了显示表列的数据types外,它还会显示索引和外键。

对不起,没有注意到这条消息已被修剪。

为了扩展Martin的出色答案,这里有一个查询,它允许您根据父表进行过滤,并显示每个父表的子表的名称,以便您可以根据外键约束来查看所有从属表/列父表。

 select con.constraint_name, att2.attname as "child_column", cl.relname as "parent_table", att.attname as "parent_column", con.child_table, con.child_schema from (select unnest(con1.conkey) as "parent", unnest(con1.confkey) as "child", con1.conname as constraint_name, con1.confrelid, con1.conrelid, cl.relname as child_table, ns.nspname as child_schema from pg_class cl join pg_namespace ns on cl.relnamespace = ns.oid join pg_constraint con1 on con1.conrelid = cl.oid where con1.contype = 'f' ) con join pg_attribute att on att.attrelid = con.confrelid and att.attnum = con.child join pg_class cl on cl.oid = con.confrelid join pg_attribute att2 on att2.attrelid = con.conrelid and att2.attnum = con.parent where cl.relname like '%parent_table%' 

使用密钥所引用的主键的名称并查询information_schema:

 select table_name, column_name from information_schema.key_column_usage where constraint_name IN (select constraint_name from information_schema.referential_constraints where unique_constraint_name = 'TABLE_NAME_pkey') 

这里'TABLE_NAME_pkey'是外键引用的主键的名字。

这是来自PostgreSQL邮件列表的Andreas Joseph Krogh的解决scheme: http : //www.postgresql.org/message-id/200811072134.44750.andreak@officenet.no

 SELECT source_table::regclass, source_attr.attname AS source_column, target_table::regclass, target_attr.attname AS target_column FROM pg_attribute target_attr, pg_attribute source_attr, (SELECT source_table, target_table, source_constraints[i] source_constraints, target_constraints[i] AS target_constraints FROM (SELECT conrelid as source_table, confrelid AS target_table, conkey AS source_constraints, confkey AS target_constraints, generate_series(1, array_upper(conkey, 1)) AS i FROM pg_constraint WHERE contype = 'f' ) query1 ) query2 WHERE target_attr.attnum = target_constraints AND target_attr.attrelid = target_table AND source_attr.attnum = source_constraints AND source_attr.attrelid = source_table; 

这个解决scheme处理引用多个列的外键,并避免重复(其他一些答案无法执行)。 我唯一改变的是variables名称。

以下是一个返回引用permission表的所​​有employee列的示例:

 SELECT source_column FROM foreign_keys WHERE source_table = 'employee'::regclass AND target_table = 'permission'::regclass; 

现有的答案没有给我的结果,我真正想要他们的forms。所以这里是我的(庞大)查询有关外键的信息。

一些注意事项:

  • 用于生成from_colsto_cols可以在Postgres 9.4和更高版本中使用WITH ORDINALITY而不是使用窗口函数的hackery来简化。
  • 这些相同的expression式依赖查询规划器不改变UNNEST返回的结果UNNEST 。 我不认为它会,但我没有任何多列外键在我的数据集进行testing。 添加9.4细节完全消除了这种可能性。
  • 查询本身需要Postgres 9.0或更高版本(8.x在集合函数中不允许ORDER BY
  • 如果您需要一个列数组而不是逗号分隔的string,请将STRING_AGGreplace为STRING_AGG

 SELECT c.conname AS constraint_name, (SELECT n.nspname FROM pg_namespace AS n WHERE n.oid=c.connamespace) AS constraint_schema, tf.name AS from_table, ( SELECT STRING_AGG(QUOTE_IDENT(a.attname), ', ' ORDER BY t.seq) FROM ( SELECT ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq, attnum FROM UNNEST(c.conkey) AS t(attnum) ) AS t INNER JOIN pg_attribute AS a ON a.attrelid=c.conrelid AND a.attnum=t.attnum ) AS from_cols, tt.name AS to_table, ( SELECT STRING_AGG(QUOTE_IDENT(a.attname), ', ' ORDER BY t.seq) FROM ( SELECT ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq, attnum FROM UNNEST(c.confkey) AS t(attnum) ) AS t INNER JOIN pg_attribute AS a ON a.attrelid=c.confrelid AND a.attnum=t.attnum ) AS to_cols, CASE confupdtype WHEN 'r' THEN 'restrict' WHEN 'c' THEN 'cascade' WHEN 'n' THEN 'set null' WHEN 'd' THEN 'set default' WHEN 'a' THEN 'no action' ELSE NULL END AS on_update, CASE confdeltype WHEN 'r' THEN 'restrict' WHEN 'c' THEN 'cascade' WHEN 'n' THEN 'set null' WHEN 'd' THEN 'set default' WHEN 'a' THEN 'no action' ELSE NULL END AS on_delete, CASE confmatchtype::text WHEN 'f' THEN 'full' WHEN 'p' THEN 'partial' WHEN 'u' THEN 'simple' WHEN 's' THEN 'simple' ELSE NULL END AS match_type, -- In earlier postgres docs, simple was 'u'nspecified, but current versions use 's'imple. text cast is required. pg_catalog.pg_get_constraintdef(c.oid, true) as condef FROM pg_catalog.pg_constraint AS c INNER JOIN ( SELECT pg_class.oid, QUOTE_IDENT(pg_namespace.nspname) || '.' || QUOTE_IDENT(pg_class.relname) AS name FROM pg_class INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid ) AS tf ON tf.oid=c.conrelid INNER JOIN ( SELECT pg_class.oid, QUOTE_IDENT(pg_namespace.nspname) || '.' || QUOTE_IDENT(pg_class.relname) AS name FROM pg_class INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid ) AS tt ON tt.oid=c.confrelid WHERE c.contype = 'f' ORDER BY 1; 
 SELECT r.conname ,ct.table_name ,pg_catalog.pg_get_constraintdef(r.oid, true) as condef FROM pg_catalog.pg_constraint r, information_schema.constraint_table_usage ct WHERE r.contype = 'f' AND r.conname = ct.constraint_name ORDER BY 1 

我写了一个喜欢和经常使用的解决scheme。 该代码位于http://code.google.com/p/pgutils/ 。 请参阅pgutils.foreign_keys视图。

不幸的是,这里的输出太罗嗦了。 但是,您可以在此处尝试使用公共版本的数据库,如下所示:

 $ psql -h unison-db.org -U PUBLIC -d unison -c 'select * from pgutils.foreign_keys; 

这至less与8.3一起工作。 如果需要,我预计在未来几个月内会更新它。

-Reece

我创build了一个小工具来查询,然后比较数据库模式:将PostgreSQL数据库模式转储到文本

有关于FK的信息,但ollyc响应给出了更多的细节。

注意:在阅读约束列时,不要忘记列的顺序!

 SELECT conname, attname FROM pg_catalog.pg_constraint c JOIN pg_catalog.pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = ANY (c.conkey) WHERE attrelid = 'schema.table_name'::regclass ORDER BY conname, array_position(c.conkey, a.attnum)