2017-11-17 131 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

相關問題