PostgreSQL查询information_schema.tables时报relation不存在的问题求助
解决PostgreSQL中查询存在数据的public表时的42P01错误
首先,咱们来拆解你遇到的问题:你写的查询里,exists(select * from p.table_name)这部分有个关键错误——PostgreSQL会把p.table_name当作一个固定的表名字符串去查找,而不是把它当成information_schema.tables里的字段值来动态引用。数据库里根本没有叫p.table_name的表,所以才会抛出relation "p.table_name" does not exist的42P01错误。
你的需求应该是要列出public schema下所有包含至少一条数据的表吧?下面给你两种可行的解决方案:
方案1:使用系统统计视图(最简单)
PostgreSQL自带的pg_stat_user_tables视图里有n_live_tup字段,记录了表的活行数,我们可以直接用这个来判断表是否有数据,不需要动态SQL:
SELECT relname AS table_name FROM pg_stat_user_tables WHERE schemaname = 'public' AND n_live_tup > 0;
注意:这个视图的统计数据可能不是实时的,如果刚插入数据没更新统计,可以先执行
ANALYZE;刷新一下。
方案2:使用动态SQL(更精准,实时判断)
如果需要实时准确判断表是否有数据,可以用PL/pgSQL写一个函数,或者用DO块来执行动态查询:
方法A:创建一个函数返回结果
CREATE OR REPLACE FUNCTION get_non_empty_public_tables() RETURNS TABLE(table_name text) AS $$ DECLARE rec record; BEGIN FOR rec IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' LOOP EXECUTE format('SELECT 1 FROM %I LIMIT 1', rec.table_name) INTO table_name; IF FOUND THEN RETURN NEXT rec.table_name; END IF; END LOOP; END; $$ LANGUAGE plpgsql; -- 调用函数 SELECT * FROM get_non_empty_public_tables();
方法B:用DO块直接输出结果(适合临时查询)
DO $$ DECLARE rec record; BEGIN FOR rec IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' LOOP BEGIN EXECUTE format('SELECT 1 FROM %I LIMIT 1', rec.table_name); RAISE NOTICE '表 % 存在数据', rec.table_name; EXCEPTION WHEN OTHERS THEN -- 忽略不存在的表(虽然information_schema里的表应该都存在,但以防万一) CONTINUE; END; END LOOP; END $$;
这里用format('%I', rec.table_name)是为了处理表名包含特殊字符或者大小写敏感的情况,避免SQL注入和语法错误。
内容的提问来源于stack exchange,提问作者khanh huy
相关产品推荐
相关产品推荐

