用户定义的 SQL 函数计算错误
Posted
技术标签:
【中文标题】用户定义的 SQL 函数计算错误【英文标题】:Wrong Calculation by User-Defined SQL-Function 【发布时间】:2017-11-17 23:52:39 【问题描述】:我有一个由
定义的函数CREATE OR REPLACE FUNCTION public.div(dividend INTEGER, divisor INTEGER)
RETURNS INTEGER
LANGUAGE 'sql'
IMMUTABLE
LEAKPROOF
STRICT
SECURITY DEFINER
PARALLEL SAFE
AS $BODY$
SELECT ($1 + $2/2) / $2;
$BODY$;
它应该计算一个商业四舍五入的结果。大多数时候,它可以完成工作。我不知道为什么,但是select div(5, 3)
给了我正确的答案,而当一个参数由聚合计算时却没有,例如select div(sum(val), 3) from (select 1 as val UNION SELECT 4) list
足以触发它。
如何修复div
?我不想强制转换每个输入。
顺便说一句,使用SELECT (cast($1 as integer) + cast($2 as integer)/2) / cast($2 as integer);
作为div
的定义没有帮助。
【问题讨论】:
【参考方案1】:允许浮点数作为参数,然后在计算时显式转换,否则在传递参数时会进行隐式转换。
✓CREATE OR REPLACE FUNCTION my_div(dividend FLOAT, divisor FLOAT) RETURNS INTEGER LANGUAGE 'sql' IMMUTABLE -- LEAKPROOF -- not allowed at dbfiddle.uk STRICT SECURITY DEFINER PARALLEL SAFE AS $BODY$ SELECT --($1 + $2/2) / $2; (cast($1 as integer) + cast($2 as integer)/2) / cast($2 as integer) $BODY$;
| my_div | | -----: | | 2 |select my_div(sum(val), 3) from (select 1 as val UNION SELECT 4) x
dbfiddle here
【讨论】:
【参考方案2】:更改函数的名称。
函数div(numeric, numeric)是一个内置的Postgres函数,你想调用哪个函数存在歧义:
select div(5, 3) -- calls your function public.div(integer, integer)
select div(5::bigint, 3) -- calls pg_catalog.div(numeric, numeric)
在第二种情况下,参数必须被解析,系统函数被选为第一个。
请注意,函数 sum(integer)
会给出 bigint 作为结果。
【讨论】:
太糟糕了,我没想到。谢谢。以上是关于用户定义的 SQL 函数计算错误的主要内容,如果未能解决你的问题,请参考以下文章