错误的计算由用户定义的SQL函数
问题描述:
我有一个功能,通过错误的计算由用户定义的SQL函数
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(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
的定义没有帮助。
答
更改函数的名称。
功能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作为结果。
答
允许浮点数作为参数,然后在计算时显式强制转换,否则在传递参数时有隐式转换。
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$;
✓
select my_div(sum(val), 3) from (select 1 as val UNION SELECT 4) x
| my_div | | -----: | | 2 |
dbfiddle here
太糟糕了,我没有想到这一点。谢谢。 – Bolpat