pg \d 在不同模式下有同名表时注意事项
一、背景
众所周知,pg在同一个数据库里面可以用Schema进行隔离,不同的Schema允许存在相同表名,但是在\d的时候又无法查出。
由上图可以注意到test1和test2中都有t1表,但是在\d的时候只有test1中的t1显示出来了,test2中没显示出来,是我们test2中t1创建失败了吗???
在我们删除test1中的t1表之后test2中才能被查询出来。
结论:之后我又进行了测试发现,在不同的Schema中如果存在相同表名,会根据search_path中的顺序进行显示,test1在search_path中比test2靠前,所以\d 的时候test1显示,test2不显示。
那么为什么会出现以上这种问题呢?我又带着疑问去寻找答案。
二、寻找原因
以pgsql -E的方式进入
查看到\d的sql之后从\d的sql入手分析原因
以下是改过\d sql之后的正常sql。
SELECT n.nspname as "Schema",
c.relname as "Name",
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type",
pg_catalog.pg_get_userbyid(c.relowner) as "Owner"
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam
WHERE c.relkind IN ('r','p','v','m','S','f','')
AND n.nspname <> 'pg_catalog'
AND n.nspname !~ '^pg_toast'
AND n.nspname <> 'information_schema'
ORDER BY 1,2;
最终查询出来结果。
声明:以上只是个人测试使用,不知道删除原来的最后一个条件会对原本的查询逻辑产生什么负面影响,官方这样设计肯定有自己的道理。
三、其他查看方法
SELECT * FROM pg_stat_user_tables;
SELECT * FROM pg_tables;
SELECT * FROM information_schema.tables;
或者可以指定模式进行查找
SELECT relname AS table_name
FROM pg_class
WHERE relkind = 'r' AND relnamespace IN (
SELECT oid FROM pg_namespace WHERE nspname = 'public'
);