Manejo de Excepciones (Errores de tiempo de ejecución)
Puede manejar excepciones que se producen en tiempo de ejecución con código PL/SQL.
Consulte también: Referencia de lenguaje PL/SQL de Oracle Database para obtener más información sobre el manejo de errores PL/SQL
Acerca de las Excepciones y los Manejadores de Excepciones
Cuando se produce un error de tiempo de espera en el código PL/SQL, se emite una excepción. Si el subprograma (o bloque) en el que se emite la excepción tiene una parte de manejo de excepciones, el control las transferencias que se realizan a ella; de lo contrario, la ejecución parará.
Los errores de Tiempo de Ejecución se pueden producir por los fallos del diseño, los errores de codificación, los fallos del hardware y muchas otras fuentes.
Oracle Database tiene muchas excepciones predefinidas , que se emite automáticamente cuando un programa viola las reglas de la base de datos o excede los límites dependientes del sistema. Por ejemplo, si una sentencia SELECT INTO no devuelve ninguna línea, Oracle Database emite la excepción predefinida NO_DATA_FOUND. Para obtener un resumen de las excepciones PL/SQL predefinidas, consulte Referencia de lenguaje PL/SQL de Oracle Database.
PL/SQL le deja definir (declarar) sus propias excepciones. Una declaración de excepción tiene la siguientes sintaxis:
exception_name EXCEPTION;
A diferencia de una excepción predefinida, se debe emitir una excepción definida por usuario de forma explícita mediante la sentencia RAISE o el procedimiento DBMS_STANDARD.RAISE_APPLICATION_ERROR. Por ejemplo:
IF condition THEN RAISE exception_name;
Para obtener información sobre el procedimiento DBMS_STANDARD.RAISE_APPLICATION_ERROR, consulte Referencia de lenguaje PL/SQL de Oracle Database.
La parte que maneja excepciones de un subprograma contiene uno o más manejadores de excepciones. Un manejador de excepciones tiene la siguiente sintaxis:
WHEN { exception_name [ OR exception_name ]... | OTHERS } THEN
statement; [ statement; ]...
("Acerca de la Estructura de Subprograma" muestra dónde colocar la parte de manejo de excepciones de un subprograma).
Un identificador de excepciones WHEN OTHERS maneja errores de tiempo de ejecución inesperados. Si se utiliza, debe ser último. Por ejemplo:
EXCEPTION
WHEN exception_1 THEN
statement; [ statement; ]...
WHEN exception_2 OR exception_3 THEN
statement; [ statement; ]...
WHEN OTHERS THEN
statement; [ statement; ]...
RAISE; -- Reraise the exception (very important).
END;
Una alternativa al manejador de excepciones WHEN OTHERS es el pragma EXCEPTION_INIT que asocia un nombre de excepción definida por el usuario a un número Oracle Database.
Consulte además:
-
Referencia de lenguaje PL/SQL de Oracle Database para obtener más información sobre la sintaxis de declaración de excepciones
-
Referencia de lenguaje PL/SQL de Oracle Database para obtener más información sobre la sintaxis del manejador de excepciones
-
Referencia de lenguaje PL/SQL de Oracle Database para obtener más información sobre el pragma EXCEPTION_INIT
Cuándo Utilizar Manejadores de Excepciones
Utilice manejadores de excepciones solo en las siguientes situaciones.
-
Espera una excepción y desea manejarla.
Por ejemplo, espera que, finalmente, una sentencia SELECT INTO no devuelva ninguna fila, lo que provocará que Oracle Database emita la excepción predefinida NO_DATA_FOUND. Desea que el subprograma o bloque gestione esa excepción (que no es un error) y, a continuación, continúe, como en el Ejemplo 5-13.
-
Debe ceder o cerrar un recurso, como se muestra en el siguiente ejemplo.
... file := UTL_FILE.OPEN ... BEGIN statement statement]... -- If this code fails for any reason, EXCEPTION WHEN OTHERS THEN UTL_FILE.FCLOSE(file); -- then you want to close the file. RAISE; -- Reraise the exception (very important). END; UTL_FILE.FCLOSE(file); ... -
En el nivel superior del código, cuando desee registrar el error.
Por ejemplo, un proceso de cliente puede emitir este bloque:
BEGIN proc(...); EXCEPTION WHEN OTHERS THEN log_error_using_autonomous_transaction(...); RAISE; -- Reraise the exception (very important). END; /Como alternativa, el subprograma independiente al que llama el cliente puede incluir la misma lógica de manejo de excepciones, pero solo en el nivel superior.
Manejo de Excepciones Predefinidas
Puede gestionar excepciones predefinidas. En el Ejemplo 5-13 se muestra cómo cambiar el procedimiento EMP_EVAL.EVAL_DEPARTMENT para manejar la excepción predefinida NO_DATA_FOUND. Realice este cambio y compile el procedimiento cambiado. (Para ver un ejemplo de cómo cambiar el cuerpo del paquete, consulte "Tutorial: Declaración de Variables y Constantes en un Subprograma".)
Ejemplo 5-13 Manejo de la Excepción Predefinida NO_DATA_FOUND
PROCEDURE eval_department(dept_id IN employees.department_id%TYPE) AS
emp_cursor emp_refcursor_type;
current_dept departments.department_id%TYPE;
BEGIN
current_dept := dept_id;
FOR loop_c IN 1..3 LOOP
OPEN emp_cursor FOR
SELECT *
FROM employees
WHERE current_dept = eval_department.dept_id;
DBMS_OUTPUT.PUT_LINE
('Determining necessary evaluations in department #' ||
current_dept);
eval_loop_control(emp_cursor);
DBMS_OUTPUT.PUT_LINE
('Processed ' || emp_cursor%ROWCOUNT || ' records.');
CLOSE emp_cursor;
current_dept := current_dept + 10;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('The query did not return a result set');
END eval_department;
Consulte también: Referencia de lenguaje PL/SQL de Oracle Database para obtener más información sobre las excepciones predefinidas
Declaración y Manejo de Excepciones Definidas por el Usuario
Puede declarar y manejar excepciones definidas por el usuario. En el ejemplo 5-14 se muestra cómo cambiar la función EMP_EVAL.CALCULATE_SCORE para declarar y manejar dos excepciones definidas por el usuario, bad_weight y bad_score. Realice este cambio y compile la función cambiada. (Para ver un ejemplo de cómo cambiar el cuerpo del paquete, consulte "Tutorial: Declaración de Variables y Constantes en un Subprograma".)
Ejemplo 5-14 Manejo de excepciones definidas por el usuario
FUNCTION calculate_score ( evaluation_id IN scores.evaluation_id%TYPE
, performance_id IN scores.performance_id%TYPE )
RETURN NUMBER AS
weight_wrong EXCEPTION;
score_wrong EXCEPTION;
n_score scores.score%TYPE;
n_weight performance_parts.weight%TYPE;
running_total NUMBER := 0;
max_score CONSTANT scores.score%TYPE := 9;
max_weight CONSTANT performance_parts.weight%TYPE:= 1;
BEGIN
SELECT s.score INTO n_score
FROM SCORES s
WHERE evaluation_id = s.evaluation_id
AND performance_id = s.performance_id;
SELECT p.weight INTO n_weight
FROM PERFORMANCE_PARTS p
WHERE performance_id = p.performance_id;
BEGIN
IF (n_weight > max_weight) OR (n_weight < 0) THEN
RAISE weight_wrong;
END IF;
END;
BEGIN
IF (n_score > max_score) OR (n_score < 0) THEN
RAISE score_wrong;
END IF;
END;
running_total := n_score * n_weight;
RETURN running_total;
EXCEPTION
WHEN weight_wrong THEN
DBMS_OUTPUT.PUT_LINE(
'The weight of a score must be between 0 and ' || max_weight);
RETURN -1;
WHEN score_wrong THEN
DBMS_OUTPUT.PUT_LINE(
'The score must be between 0 and ' || max_score);
RETURN -1;
END calculate_score;
Consulte también: Referencia de lenguaje PL/SQL de Oracle Database para obtener más información sobre las excepciones definidas por el usuario