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.
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
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 $$