PostgreSQL 9.5:异常处理

17

我有一个名为employee的表格,有两列,并创建了两个功能来进行插入和更新操作。这两个功能将通过另一个名为udf_3()的函数来调用。

我想在第三个函数上做异常处理,即udf_3(),应该提供给我哪个函数出错的详细信息。

--表格employee

create table employee
(
 id int,
 name varchar(10)
);

--功能 1: udf_1() 用于插入。

create or replace function udf_1()
returns void as
$body$
begin

        insert into employee values(1,'Mak');
end;
$body$
language plpgsql;

--功能 2: udf_2() 用于更新。

create or replace function udf_2()
returns void as
$body$
begin

        update employee
        set a_id = 99
        where name = 'Mak';

end;
$body$
language plpgsql;

--函数 3:udf_3() 用于调用以上所有函数。

create or replace function udf_3()
returns int as
$body$
begin
    perform udf_1();

    perform udf_2();

    return 0;

    exception 
    when others then
        RAISE INFO 'Error Name:%',SQLERRM;
        RAISE INFO 'Error State:%', SQLSTATE;
        return -1;

end;
$body$
language plpgsql;

--函数调用:

select * from udf_3();

异常:

INFO:  Error Name:column "a_id" of relation "employee" does not exist
INFO:  Error State:42703

问题:我能够得到异常但是无法知道哪个函数抛出了异常。

1个回答

25
根据文档, 在异常处理程序中,可以使用“GET STACKED DIAGNOSTICS”命令获取有关当前异常的信息。
示例: https://www.postgresql.org/docs/9.5/static/plpgsql-control-structures.html#PLPGSQL-EXCEPTION-DIAGNOSTICS
create or replace function udf_3()
returns int as
$body$
declare
    err_context text;
begin
    perform udf_1();

    perform udf_2();

    return 0;

    exception 
    when others then
        GET STACKED DIAGNOSTICS err_context = PG_EXCEPTION_CONTEXT;
        RAISE INFO 'Error Name:%',SQLERRM;
        RAISE INFO 'Error State:%', SQLSTATE;
        RAISE INFO 'Error Context:%', err_context;
        return -1;

end;
$body$
language plpgsql;

将显示以下内容:

INFO: Error Context:SQL: "SELECT udf_1()"

但这只是错误的文本表示。您的逻辑不应该依赖它。最好使用自定义错误代码来处理异常逻辑(并在函数中引发有意义的异常,以便稍后捕获和处理)。
更新: 另一个解决方案是将代码分成不同的块,可以分别捕获异常。在这种情况下,您知道哪个块引发了异常:
DO $$
BEGIN

    -- Block 1
    BEGIN
        -- any code that might raise an exception
        RAISE EXCEPTION 'Exception 1'; -- for example
    EXCEPTION 
    WHEN others THEN    
        RAISE INFO 'Caught in Block 1';
    END;

    -- Block 2
    BEGIN
        -- any code that might raise an exception
        RAISE EXCEPTION 'Exception 2'; -- for example
    EXCEPTION 
    WHEN others THEN    
        RAISE INFO 'Caught in Block 2';
    END;

END $$

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接