用户定义的 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$;
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 作为结果。

【讨论】:

太糟糕了,我没想到。谢谢。

以上是关于用户定义的 SQL 函数计算错误的主要内容,如果未能解决你的问题,请参考以下文章

无法在 sql 中创建用户定义的函数来计算距离

scala用户定义函数在spark sql中不起作用

用户定义函数内的 Sql Server 表结构

在 SQL Server 中计算中位数的函数

SQL Server2008窗口计算

SQL SERVER数据库编程:创建并执行用户自定义函数Avg_grade,完成:计算全体学生某门功课的平均成绩