如何让PostgreSQL的icase函数支持整数与数值混合参数?
问题场景
已通过以下SQL创建public.icase函数:
CREATE OR REPLACE FUNCTION public.icase( cond1 boolean, res1 anyelement, cond2 boolean, res2 anyelement, conddefault anyelement) RETURNS anyelement LANGUAGE 'sql' IMMUTABLE PARALLEL UNSAFE AS $BODY$ SELECT CASE WHEN $1 THEN $2 WHEN $3 THEN $4 ELSE $5 END; $BODY$;
执行查询 select icase( false, 0, false, 0.,0.) 时抛出错误:
function icase(boolean, integer, boolean, numeric, numeric) does not exist
需要让该函数支持整数与数值类型的混合参数。
问题原因
PostgreSQL 的 anyelement 是严格多态类型,要求所有声明为 anyelement 的参数必须是完全相同的数据类型,无法自动兼容可隐式转换的类型。当传入整数(integer)和数值(numeric)混合参数时,数据库找不到匹配类型签名的函数,因此报错。
解决方法
将函数参数的 anyelement 替换为 anycompatible 类型——这是兼容多态类型,允许数据库对兼容的数据类型进行隐式转换,从而支持整数与数值的混合传入:
CREATE OR REPLACE FUNCTION public.icase( cond1 boolean, res1 anycompatible, cond2 boolean, res2 anycompatible, conddefault anycompatible) RETURNS anycompatible LANGUAGE 'sql' IMMUTABLE PARALLEL UNSAFE AS $BODY$ SELECT CASE WHEN $1 THEN $2 WHEN $3 THEN $4 ELSE $5 END; $BODY$;
修改后重新执行原查询,数据库会自动将整数 0 转换为 numeric 类型,函数可正常执行并返回结果。
替代方案(手动类型转换)
如果不想修改函数,也可以在调用时显式转换参数类型,确保所有结果参数类型一致:
select icase( false, 0::numeric, false, 0.,0.);
内容的提问来源于stack exchange,提问作者Andrus
相关产品推荐
相关产品推荐

