如何在PostgreSQL中列出所有带有引用的列,就像在MySQL中一样?

3

嗨,我一直在搜索互联网,但似乎找不到解决方法...

我正在尝试列出postgresql中所有带有引用的列。 在mysql中,查询语句如下:

select table_schema, table_name, column_name, referenced_table_schema, referenced_table_name, referenced_column_name from informatioN_schema.key_column_usage where table_schema = '(Table Schema)';

结果如下:

setandlog    | access      | kode_privilege  | NULL                    | NULL                  | NULL
setandlog    | access      | kode_feature    | NULL                    | NULL                  | NULL
setandlog    | access      | kode_app        | NULL                    | NULL                  | NULL
setandlog    | access      | kode_credential | NULL                    | NULL                  | NULL
setandlog    | access      | username        | NULL                    | NULL                  | NULL
setandlog    | access      | kode_credential | setandlog               | cred_access           | kode_credential
setandlog    | access      | kode_privilege  | setandlog               | cred_access           | kode_privilege
setandlog    | access      | kode_feature    | setandlog               | cred_access           | kode_feature
setandlog    | access      | kode_app        | setandlog               | cred_access           | kode_app
setandlog    | access      | username        | setandlog               | login                 | username

但是当我尝试在PostgreSQL中使用以下查询时:

select r.table_schema as table_schema, r.table_name as table_name, r.column_name as column_name, u.table_schema as referenced_table_schema, u.table_name as referenced_table_name, u.column_name as referenced_column_name
from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE as u
inner join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as 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 as R
    ON R.CONSTRAINT_CATALOG = FK.CONSTRAINT_CATALOG
    AND R.CONSTRAINT_SCHEMA = FK.CONSTRAINT_SCHEMA
    AND R.CONSTRAINT_NAME = FK.CONSTRAINT_NAME

结果不像在MySQL查询中我所期望的那样......以下是结果:

setandlog    | access            | kode_credential          | setandlog               | cred_access           | kode_credential
setandlog    | access            | kode_privilege           | setandlog               | cred_access           | kode_credential
setandlog    | access            | kode_feature             | setandlog               | cred_access           | kode_credential
setandlog    | access            | kode_app                 | setandlog               | cred_access           | kode_credential
setandlog    | access            | kode_credential          | setandlog               | cred_access           | kode_privilege
setandlog    | access            | kode_privilege           | setandlog               | cred_access           | kode_privilege
setandlog    | access            | kode_feature             | setandlog               | cred_access           | kode_privilege
setandlog    | access            | kode_app                 | setandlog               | cred_access           | kode_privilege
setandlog    | access            | kode_credential          | setandlog               | cred_access           | kode_feature
setandlog    | access            | kode_privilege           | setandlog               | cred_access           | kode_feature
setandlog    | access            | kode_feature             | setandlog               | cred_access           | kode_feature
setandlog    | access            | kode_app                 | setandlog               | cred_access           | kode_feature
setandlog    | access            | kode_credential          | setandlog               | cred_access           | kode_app
setandlog    | access            | kode_privilege           | setandlog               | cred_access           | kode_app
setandlog    | access            | kode_feature             | setandlog               | cred_access           | kode_app
setandlog    | access            | kode_app                 | setandlog               | cred_access           | kode_app
setandlog    | access            | username                 | setandlog               | login                 | username

看起来有很多冗余数据……

当我检查查询时,在INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS表中的UNIQUE_CONSTRAINT_NAME没有任何差异……

有人能帮我解决这个问题吗?

1个回答

2

你在这里遇到的问题是引用的表有一个由多个列组成的PRIMARY KEY

PRIMARY KEY(kode_credential, kode_privilege, kode_feature, kode_app)

这四列与其他表连接后,您将获得笛卡尔积:每个外键中的每个列都有4行。您需要在key_column_usage视图中使用列ordinal_position(引用表中约束列的位置 - 在您的情况下为access)和position_in_unique_constraint(引用表中的约束列 - cred_access),并进行自连接,如下所示:

SELECT k1.table_schema,
       k1.table_name,
       k1.column_name,
       k2.table_schema AS referenced_table_schema,
       k2.table_name AS referenced_table_name,
       k2.column_name AS referenced_column_name
FROM information_schema.key_column_usage k1
JOIN information_schema.referential_constraints fk USING (constraint_schema, constraint_name)
JOIN information_schema.key_column_usage k2
  ON k2.constraint_schema = fk.unique_constraint_schema
 AND k2.constraint_name = fk.unique_constraint_name
 AND k2.ordinal_position = k1.position_in_unique_constraint;

MySQL可以在没有像上面那样的特定连接的情况下完成这项操作,这真是一种“神奇”的能力。让人想知道还有哪些幕后操作...


不过,当我使用 select * from pg_constraint where contype = 'f'; 时,我得到了一个名为 conkey 的列,其值为 '{2,3,4,5}',以及一个名为 confkey 的列,其值为 '{1,2,3,4}',从中可以看出 position_in_unique_constraint 是否代表了 confkey?无论如何,它都像魅力一样工作!谢谢:D - Raqasyinov
是的,正确的。information_schema视图是建立在系统目录上的,并且它使用恰好这个表pg_constraint来填充视图和两个数组对应于ordinal_positionposition_in_unique_constraint - Patrick
我明白了...所以基本上information_schema中的大多数表都是基于pg_catalog表的...你能给我一些参考资料/书籍,让我学习information_schemapg_catalog之间的关系吗?非常感谢您的帮助 :) - Raqasyinov
我认为PG目录上没有任何书籍,但您可以随时在网上搜索相关材料。information_schema是ANSI标准,在任何一本好的SQL书籍中都应该有描述。总的来说,通过实践和探索学习,就像您现在所做的那样。这正是我学习并撰写上述答案的方式。 - Patrick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接