今天有开发的同事咨询在执行函数报错的问题,主要问题出现在更改入参上,仿照这个函数,创建以下测试函数,用来重现错误信息,数据库版本 8.4。
创建测试函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
CREATE OR REPLACE FUNCTION func_create_daily_table(table_name character varying, table_num integer) RETURNS void LANGUAGE plpgsql AS $function$ declare today char(8); v_childtable character varying; begin IF table_num is null then table_num :=1; END IF; for i in 0 .. table_num loop v_childtable := table_name || '_' || to_char(current_date + i, 'YYYYMMDD') ; execute 'create table ' || v_childtable || '(like ' || table_name || ' including all ) inherits (' || table_name || ')'; end loop; end; $function$;
|
报错信息
1
|
psql:creaet_func.sql:129: ERROR: "$2" is declared CONSTANT
|
备注:这里提示入参 $1 被定义成常量,且不能修改,报错的数据库版本为 8.4,接下来在 9.0 版本测试。
9.0 版本测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
[pg90@redhatB ~]$ psql francs francs psql (9.0.9) Type "help" for help. francs=> CREATE OR REPLACE FUNCTION func_create_daily_table(table_name character varying, table_num integer) francs-> RETURNS void francs-> LANGUAGE plpgsql francs-> AS $function$ francs$> declare francs$> today char(8); francs$> v_childtable character varying; francs$> begin francs$> francs$> IF table_num is null then francs$> table_num :=1; francs$> END IF; francs$> francs$> for i in 0 .. table_num loop francs$> v_childtable := table_name || '_' || to_char(current_date + i, 'YYYYMMDD') ; francs$> execute 'create table ' || v_childtable || '(like ' || table_name || ' including all ) inherits (' || table_name || ')'; francs$> end loop; francs$> end; francs$> $function$; CREATE FUNCTION
|
备注:在9.0 版本测试是正常的,猜测可能是 8.4 版本的一个 bug ,但在官网邮件列表里没有查到明确定位是bug 的信息,唯一相关的内容是以下这个帖子,遇到的问题类似,但下面用到了参数 ALIAS ,情况不太一样,有兴趣的朋友可以看下。
解决方法
主要有两种解决方法:
1. 在函数中额外使用中转变量,将入参的值先赋给中转变量,然后再去修改中转变量的值。
2. 升级数据库版本。
参考
原创文章,作者:506227337,如若转载,请注明出处:https://blog.ytso.com/237997.html