2017-11-17 133 views
1

我有一个功能,通过错误的计算由用户定义的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的定义没有帮助。

回答

1

更改函数的名称。

功能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作为结果。

+0

太糟糕了,我没有想到这一点。谢谢。 – Bolpat

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$; 
select my_div(sum(val), 3) 
from (select 1 as val UNION SELECT 4) x 
 
| my_div | 
| -----: | 
|  2 | 

dbfiddle here

相关问题