PostgreSQL 9.5: tratamento de excepções

tenho uma tabela chamada empregado com duas colunas, e criei duas funções para operações de inserção e actualização. Estas duas funções serão chamadas através de outro function which named as udf_3 ().

Eu quero fazer tratamento de excepção na terceira função que é udf_3() que deve dê-me os detalhes de qual função tem erro.

--Quadro: employee

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

--função 1: udf_1() utilizado para insercao.

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

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

--função 2: udf_2() usado para actualização.

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

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

end;
$body$
language plpgsql;

--função 3: udf_3() costumava chamar todas as funções acima.

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;

--Chamada De Funções:

select * from udf_3();

excepção:

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

problema : Eu sou capaz de obter a exceção Mas não sou capaz de obter de qual função eu tenho exceção.

Author: Daniel L. VanDenBosch, 2016-11-25

1 answers

De acordo com a documentação

Dentro de um manipulador de excepções, pode-se também obter informações sobre a excepção actual usando o comando GET STACKED DIAGNOSTICS

Https://www.postgresql.org/docs/9.5/static/plpgsql-control-structures.html#PLPGSQL-EXCEPTION-DIAGNOSTICS

Exemplo:

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;

Irá mostrar o seguinte:

INFO: Error Context:SQL: "SELECT udf_1()"
Mas isto é apenas uma representação textual do erro. A sua lógica não deve depender dela. É é melhor usar códigos de erro personalizados para lidar com a lógica de exceção (e criar exceções significativas em suas funções que você pode pegar e lidar mais tarde).

Actualizar:

Outra solução é separar o seu código em blocos diferentes para os quais pode apanhar excepções separadamente. Neste caso, sabe de que bloco foi levantada a excepção:

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 $$
 2
Author: AlexM, 2018-08-21 16:18:28