用户定义的 SQL-函数计算错误
Wrong Calculation by User-Defined SQL-Function
我有一个由
定义的函数
CREATE OR REPLACE FUNCTION public.div(dividend INTEGER, divisor INTEGER)
RETURNS INTEGER
LANGUAGE 'sql'
IMMUTABLE
LEAKPROOF
STRICT
SECURITY DEFINER
PARALLEL SAFE
AS $BODY$
SELECT ( + /2) / ;
$BODY$;
它应该计算一个商业四舍五入的结果。大多数时候,它完成了工作。我不知道为什么,但是 select div(5, 3)
给了我正确的答案,而当一个参数是由聚合计算时却没有,例如select div(sum(val), 3) from (select 1 as val UNION SELECT 4) list
足以触发它。
我该如何修复 div
?我不想投射每一个输入。
顺便说一句,使用 SELECT (cast( as integer) + cast( as integer)/2) / cast( 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 --( + /2) / ;
(cast( as integer) + cast( as integer)/2) / cast( as integer)
$BODY$;
✓
select my_div(sum(val), 3)
from (select 1 as val UNION SELECT 4) x
| my_div |
| -----: |
| 2 |
dbfiddle here
我有一个由
定义的函数CREATE OR REPLACE FUNCTION public.div(dividend INTEGER, divisor INTEGER)
RETURNS INTEGER
LANGUAGE 'sql'
IMMUTABLE
LEAKPROOF
STRICT
SECURITY DEFINER
PARALLEL SAFE
AS $BODY$
SELECT ( + /2) / ;
$BODY$;
它应该计算一个商业四舍五入的结果。大多数时候,它完成了工作。我不知道为什么,但是 select div(5, 3)
给了我正确的答案,而当一个参数是由聚合计算时却没有,例如select div(sum(val), 3) from (select 1 as val UNION SELECT 4) list
足以触发它。
我该如何修复 div
?我不想投射每一个输入。
顺便说一句,使用 SELECT (cast( as integer) + cast( as integer)/2) / cast( 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 --( + /2) / ; (cast( as integer) + cast( as integer)/2) / cast( as integer) $BODY$;
✓
select my_div(sum(val), 3) from (select 1 as val UNION SELECT 4) x
| my_div | | -----: | | 2 |
dbfiddle here