Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL&;除零异常_Postgresql_Plpgsql - Fatal编程技术网

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;
要点
  • 这是
    语言SQL
    ,不是PL/pgSQL函数。您可以使用这两种方法中的任何一种,但对于这样的简单情况,您最好还是使用更简单的工具

  • @皮尔克罗准确地诊断出了你错误的原因。按照您的方式,
    RETURN
    语句是异常处理程序的一部分,只有在发生异常时才会到达

  • 如果
    a、b、c
    的数据类型应为
    integer
    bigint
    ,则可能需要在除法之前强制转换为数值,否则结果将强制转换为整数

  • 使用
    CASE
    语句避免被零除。这比异常处理便宜得多


OP捕获了正确的异常,但返回语句位于错误的位置。@pilcrow是的,我刚刚意识到这一点。我尝试了他的代码,但硬编码了0的除法。即使返回值低于异常块,也能正确捕获异常。他的代码只有在除法为0时才起作用:-)
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;