如何遍历Redshift表获取行数?存储过程执行报错求助
问题描述
需要遍历指定schema下的表以获取各表行数,尝试使用CTE语句时因无法混合不同节点失败:
WITH tables_i_want AS ( SELECT *, table_schema||'.'||table_name as tbl FROM temp.redshift_mod_dates WHERE table_schema = 'whatever' ) SELECT nspname FROM pg_catalog.pg_class AS c JOIN pg_catalog.pg_namespace AS ns ON c.relnamespace = ns.oid INNER JOIN tables_i_want as tiw ON tiw.tbl = c.oid AND relname not like 'pg_%'
随后尝试编写存储过程,但执行时出现语法错误:
CREATE OR REPLACE PROCEDURE f_test() LANGUAGE plpgsql AS $$ DECLARE full_table_name1 VARCHAR; full_table_name VARCHAR; BEGIN FOR full_table_name IN (SELECT table_schema||'.'||table_name as full_table_name FROM temp.redshift_mod_dates WHERE table_schema = 'whatever') LOOP EXECUTE 'SELECT INTO temp.redshift_tables_with_cnt %, COUNT(*) FROM %', full_table_name; RAISE INFO '%', full_table_name; END LOOP; END; $$;
错误信息:
[42601] ERROR: syntax error at or near "$1" Where: SQL statement in PL/PgSQL function "f_test" near line 5
寻求正确实现遍历表获取行数的方法及存储过程报错的解决办法。
一、存储过程报错修复方案
上述存储过程存在两个核心问题:
- 动态SQL参数替换逻辑错误:PL/pgSQL中
EXECUTE不支持%作为占位符,且表名属于标识符,直接拼接会引发语法错误或SQL注入风险,需用format()函数安全处理。 - 数据插入语法错误:
SELECT INTO用于创建新表并插入数据,若目标表已存在,应使用INSERT INTO ... SELECT ...语法。
修复后的存储过程:
CREATE OR REPLACE PROCEDURE f_test() LANGUAGE plpgsql AS $$ DECLARE full_table_name VARCHAR; BEGIN -- 可选:清空目标表,避免重复数据 TRUNCATE TABLE temp.redshift_tables_with_cnt; FOR full_table_name IN ( SELECT table_schema||'.'||table_name FROM temp.redshift_mod_dates WHERE table_schema = 'whatever' ) LOOP -- 用format函数安全拼接SQL:%L处理字符串字面量,%I处理标识符 EXECUTE format( 'INSERT INTO temp.redshift_tables_with_cnt (table_name, row_count) SELECT %L, COUNT(*) FROM %I', full_table_name, full_table_name ); RAISE INFO '已处理表: %', full_table_name; END LOOP; END; $$;
前置要求:确保目标表已创建,结构如下:
CREATE TABLE temp.redshift_tables_with_cnt (table_name VARCHAR(256), row_count BIGINT);
二、高效获取表行数的替代方案(无需遍历查询)
Redshift提供系统视图直接维护表行数统计,比逐表执行COUNT(*)效率高数十倍,优先推荐以下两种方式:
方法1:使用svv_table_info(最准确)
该视图由Redshift自动更新,行数统计精度高:
SELECT schemaname||'.'||tablename AS full_table_name, rows AS row_count FROM svv_table_info WHERE schemaname = 'whatever' AND tablename IN ( SELECT table_name FROM temp.redshift_mod_dates WHERE table_schema = 'whatever' );
方法2:使用pg_class系统表(统计信息有延迟)
依赖PostgreSQL原生统计字段,适合对实时性要求不高的场景:
SELECT ns.nspname||'.'||c.relname AS full_table_name, c.reltuples::BIGINT AS row_count FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace ns ON c.relnamespace = ns.oid WHERE ns.nspname = 'whatever' AND c.relname IN ( SELECT table_name FROM temp.redshift_mod_dates WHERE table_schema = 'whatever' ) AND c.relkind = 'r'; -- 仅筛选普通用户表
内容的提问来源于stack exchange,提问作者jayykaa
相关产品推荐
相关产品推荐

