【问题标题】:Wrong Calculation by User-Defined SQL-Function用户定义的 SQL 函数计算错误
【发布时间】: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 的定义没有帮助。

【问题讨论】:

    标签: sql postgresql user-defined-functions postgresql-9.4


    【解决方案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

    【讨论】:

      【解决方案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 作为结果。

      【讨论】:

      • 太糟糕了,我没想到。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      • 2011-08-08
      • 2018-03-27
      • 2018-11-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      相关资源
      最近更新 更多