Soporte de excepciones y mensajes de error
Cualquier error que se produzca en un procedimiento NZPLSQL finaliza de forma abrupta la ejecución del procedimiento e interrumpe la transacción circundante. El sistema vuelve al bucle principal para obtener la siguiente consulta de la aplicación cliente. No es posible detectar todas las excepciones, especialmente si esa acción deja la base de datos en un estado incorrecto.
Para detectar y procesar un error que se produce en un bloque de procedimiento, puede añadir una sección de manejo de excepciones al final del bloque utilizando la palabra clave EXCEPTION. Si no se producen errores, la sección de manejo de excepciones no se tiene en cuenta. En la sección de manejo de excepciones, puede especificar uno o más manejadores de excepciones utilizando cláusulas WHEN que especifican la excepción que debe coincidir y las sentencias que se deben ejecutar cuando se produce una coincidencia. Una sentencia EXCEPTION tiene el formato siguiente:
EXCEPTION
WHEN clause THEN
statements
[ WHEN ... ]
NZPLSQL admite dos cláusulas para el proceso de excepción:
- TRANSACTION_ABORTED
- Utilice la cláusula TRANSACTION_ABORTED para especificar las sentencias que desea ejecutar cuando se produce un error que hace que la transacción termine anormalmente. En este caso, se necesita un ROLLBACK para continuar. Asegúrese de que el mandato ROLLBACK es el primer mandato de las sentencias de manejo de excepciones.
- OTROS
- Utilice la cláusula OTHERS para especificar las sentencias a ejecutar cuando se produce cualquier error en el bloque de procedimiento. Los errores tales como un error de análisis de SQL no terminan anormalmente la transacción y, por consiguiente, no coincidirán con una cláusula TRANSACTION_ABORTED.
Puede especificar ambas cláusulas en un bloque de excepción, como en el siguiente ejemplo. Cuando se produce un error en el procedimiento, el código de procedimiento utiliza la primera cláusula de excepción coincidente y ejecuta las sentencias de dicha cláusula. Las cláusulas después de la coincidencia se ignoran. Como práctica recomendada, especifique la cláusula OTHERS en último lugar porque coincide con cualquier tipo de error.
EXCEPTION
WHEN TRANSACTION_ABORTED THEN
ROLLBACK;
statements_case1
RAISE ERROR 'Procedure failed: %', sqlerrm;
WHEN OTHERS THEN
statements_case2
RAISE NOTICE 'Caught error, continuing %', sqlerrm;
En este ejemplo, un error que termina anormalmente una transacción desencadena la cláusula TRANSACTION_ABORTED y el procedimiento almacenado ejecuta ROLLBACK, las sentencias en statements_case1 y genera el mensaje de error. Si el error no ha hecho que la transacción termine anormalmente, el proceso de excepción salta la cláusula OTHERS y el procedimiento almacenado ejecuta el conjunto statements_case2 y genera el mensaje de aviso. Si no había errores en el bloque, se saltan las sentencias de excepción.
La variable SQLERRM contiene el texto de un mensaje de error que se detecte. En ausencia de un bloque de excepción, la excepción se propaga hacia arriba al siguiente procedimiento almacenado de la pila de llamadas. Si sproc1 llama a sproc2, lo que genera una excepción, pero sproc2 no tiene un manejador de excepciones, el sistema busca un manejador en sproc1. El sistema también consulta las declaraciones de bloque incluidas.
create or replace procedure sp_except01() returns BOOL LANGUAGE
NZPLSQL AS
BEGIN_PROC
DECLARE
r record;
BEGIN
<<inner>>
BEGIN
SELECT * INTO r FROM NONEXISTENT;
END;
END;
END_PROC;
create or replace procedure sp_except02() returns BOOL LANGUAGE
NZPLSQL AS
BEGIN_PROC
BEGIN
CALL sp_except01();
END;
END_PROC;
create or replace procedure sp_except03() returns BOOL LANGUAGE
NZPLSQL AS
BEGIN_PROC
BEGIN
CALL sp_except02();
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'Caught exception';
END;
END_PROC;
En estos ejemplos, la excepción se genera en sp_except01, en el bloque interior. El sistema busca primero un manejador de excepciones para el bloque interior, que no se encuentra. El control pasa al contexto padre, que es el procedimiento sp_except01, y tampoco se encuentra en este ámbito ningún manejador de excepciones. Entonces el control pasa a sp_except02 y finalmente sp_except03, donde se encuentra y utiliza un manejador de excepciones.
Si no se detecta ninguna excepción en ningún nivel, se envían mensajes de registro a nivel de AVISO adicionales para proporcionar contexto acerca del error y dónde se ha producido (número de línea y tipo de sentencia, a menos que el error sea de una sentencia RAISE EXCEPTION).
CREATE PROCEDURE sp() RETURNS INTEGER LANGUAGE NZPLSQL AS
BEGIN_PROC
BEGIN
EXECUTE IMMEDIATE 'insert into NOTEXIST' || 'values(1,1)';
EXCEPTION WHEN OTHERS THEN
END;
END_PROC;
Suponiendo que NOTEXIST no existe en la base de datos, la consulta no visualiza ninguna salida de error porque el error lo ha tratado el manejador de excepciones.
CREATE PROCEDURE sp() RETURNS INTEGER LANGUAGE NZPLSQL AS
BEGIN_PROC
BEGIN
EXECUTE IMMEDIATE 'insert into NOTEXIST' || ' values(1,1)';
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'Got exception: %', SQLERRM;
END;
END_PROC;NOTICE: Got exception: ERROR: Relation 'NOTEXIST' does not exist