Redshift创建函数报错:PL/pgSQL语言不支持,如何解决?
解决Amazon Redshift中"Language plpgsql not supported for CREATE FUNCTION"报错
报错原因
Amazon Redshift不支持使用PL/pgSQL语言创建自定义函数(UDF),它仅支持SQL和Python作为UDF的开发语言。PL/pgSQL是PostgreSQL的过程化扩展语言,但Redshift基于PostgreSQL做了大量裁剪优化,未将PL/pgSQL纳入UDF支持范围。
不过Redshift支持用PL/pgSQL编写存储过程(Stored Procedure),这是适配你原有逻辑的最优方案。
解决方案1:改用PL/pgSQL存储过程
将原函数改写为存储过程(注意使用CREATE PROCEDURE而非CREATE FUNCTION),同时修正原代码中table_schema.table_name的变量引用错误,添加quote_ident避免SQL注入风险:
CREATE OR REPLACE PROCEDURE update_tablename_tablecounts(c_date TEXT) AS $$ DECLARE table_name TEXT; schema_name TEXT; row_count INT; BEGIN -- 创建临时表存储统计结果 CREATE TEMP TABLE temp_table ( table_name TEXT UNIQUE, row_count INT ); -- 遍历目标表 FOR table_name, schema_name IN SELECT table_name, table_schema FROM information_schema.tables WHERE table_schema = 'MMO_MMO_proc_' || c_date AND table_name IN ('elig_59_v02', 'prvtonet_6_v03', 'prvtonet_6_v03_pass0','prvtonet_6_v03_pass1','prvtonet_6_v03_final','roster_final') LOOP -- 动态统计单表行数 EXECUTE 'SELECT COUNT(*) FROM ' || quote_ident(schema_name) || '.' || quote_ident(table_name) INTO row_count; -- 插入临时表,存储带schema的完整表名 INSERT INTO temp_table (table_name, row_count) VALUES (schema_name || '.' || table_name, row_count); END LOOP; -- 创建目标统计表(若不存在) CREATE TABLE IF NOT EXISTS table_counter ( table_name TEXT, row_count INT ); -- 将临时表数据插入目标表 INSERT INTO table_counter SELECT * FROM temp_table; -- 清理临时表 DROP TABLE temp_table; END; $$ LANGUAGE plpgsql;
执行存储过程的方式:
CALL update_tablename_tablecounts('20240101'); -- 替换为实际日期参数
解决方案2:纯SQL实现(无过程化逻辑)
如果不需要循环逻辑,可直接用UNION ALL拼接各表的统计语句,适合固定表名的场景:
-- 先创建目标表(若不存在) CREATE TABLE IF NOT EXISTS table_counter ( table_name TEXT, row_count INT ); -- 动态拼接日期参数,执行统计插入 PREPARE insert_table_counts(text) AS INSERT INTO table_counter SELECT 'MMO_MMO_proc_' || $1 || '.elig_59_v02' AS table_name, COUNT(*) AS row_count FROM "MMO_MMO_proc_" || $1 || ".elig_59_v02" UNION ALL SELECT 'MMO_MMO_proc_' || $1 || '.prvtonet_6_v03' AS table_name, COUNT(*) AS row_count FROM "MMO_MMO_proc_" || $1 || ".prvtonet_6_v03" UNION ALL SELECT 'MMO_MMO_proc_' || $1 || '.prvtonet_6_v03_pass0' AS table_name, COUNT(*) AS row_count FROM "MMO_MMO_proc_" || $1 || ".prvtonet_6_v03_pass0" UNION ALL SELECT 'MMO_MMO_proc_' || $1 || '.prvtonet_6_v03_pass1' AS table_name, COUNT(*) AS row_count FROM "MMO_MMO_proc_" || $1 || ".prvtonet_6_v03_pass1" UNION ALL SELECT 'MMO_MMO_proc_' || $1 || '.prvtonet_6_v03_final' AS table_name, COUNT(*) AS row_count FROM "MMO_MMO_proc_" || $1 || ".prvtonet_6_v03_final" UNION ALL SELECT 'MMO_MMO_proc_' || $1 || '.roster_final' AS table_name, COUNT(*) AS row_count FROM "MMO_MMO_proc_" || $1 || ".roster_final"; -- 传入日期参数执行 EXECUTE insert_table_counts('20240101'); -- 释放预处理语句 DEALLOCATE insert_table_counts;
内容的提问来源于stack exchange,提问作者True Gentleman
相关产品推荐
相关产品推荐

