PostgreSQL&;除零异常
我不能完全理解这一点。。我的函数如下所示:PostgreSQL&;除零异常,postgresql,plpgsql,Postgresql,Plpgsql,我不能完全理解这一点。。我的函数如下所示: create or replace function myfunc(integer, varchar(25), varchar(25), integer, integer) returns numeric as $$ declare var_return numeric; begin select sum(a+ b) / sum(a + b + c) from mytable where col1 = $1 and col2 = $2 and co
create or replace function myfunc(integer, varchar(25), varchar(25), integer, integer) returns numeric as $$
declare var_return numeric;
begin
select sum(a+ b) / sum(a + b + c)
from mytable
where col1 = $1
and col2 = $2
and col3 = $3
and col4 between $4 AND $5
into var_return;
exception when division_by_zero then return 0.0;
return coalesce(var_return, 0.0);
end;
$$ language plpgsql;
但是当我选择myfunc时(123,'foo','bar',1,10)代码>我明白了:
ERROR: control reached end of function without RETURN
CONTEXT: PL/pgSQL function "myfunc"
为什么会发生这种情况?显然,我想捕捉
select
语句遇到a+b+c
等于0并返回0的情况。EXCEPTION子句属于整个BEGIN块,并一直运行到末尾。也就是说,博士后理解您写了以下内容:
create or replace function myfunc(...) returns ... as $$
declare var_return numeric;
begin
select ...
into var_return; -- but no RETURN statement in this block
exception when division_by_zero then
return 0.0;
return coalesce(var_return, 0.0); -- this is part of the exception handler
end;
$$ language plpgsql;
将“返回合并…”移到异常行上方,然后重试。您确定处理了正确的异常吗 我想你还有一个例外 我会先试试(我总是把异常放在块的末尾,这样更容易阅读。)
您可以大大简化您的功能:
CREATE OR REPLACE FUNCTION myfunc(int, varchar(25), varchar(25), int, int)
RETURNS numeric AS
$BODY$
SELECT CASE WHEN abc = 0 THEN 0::numeric ELSE (ab/abc)::numeric END
FROM (
SELECT sum(a + b) AS ab, sum(a + b + c) AS abc
FROM mytable
WHERE col1 = $1
AND col2 = $2
AND col3 = $3
AND col4 BETWEEN $4 AND $5
) x;
$BODY$ language SQL;
要点
- 这是
,不是PL/pgSQL函数。您可以使用这两种方法中的任何一种,但对于这样的简单情况,您最好还是使用更简单的工具语言SQL
- @皮尔克罗准确地诊断出了你错误的原因。按照您的方式,
语句是异常处理程序的一部分,只有在发生异常时才会到达RETURN
- 如果
的数据类型应为a、b、c
或integer
,则可能需要在除法之前强制转换为数值,否则结果将强制转换为整数bigint
- 使用
语句避免被零除。这比异常处理便宜得多CASE
CREATE OR REPLACE FUNCTION myfunc(int, varchar(25), varchar(25), int, int)
RETURNS numeric AS
$BODY$
SELECT CASE WHEN abc = 0 THEN 0::numeric ELSE (ab/abc)::numeric END
FROM (
SELECT sum(a + b) AS ab, sum(a + b + c) AS abc
FROM mytable
WHERE col1 = $1
AND col2 = $2
AND col3 = $3
AND col4 BETWEEN $4 AND $5
) x;
$BODY$ language SQL;