Los errores que se producen durante la ejecución de un bloque de código
PL/SQL pueden ser manejados a gusto del programador, es decir, si
durante la ejecución de una sentencia PLSQL se produce un error, podemos
hacer que el programa realice unas acciones u otras dependiendo del
tipo de error que se haya generado, esto es algo parecido a lo que se
puede hacer cuando programamos en
C++ o
Java. Para conseguir esto debemos añadir dentro del
bloque de código PL/SQL una sección para tratamiento de las excepciones.
Existen dos tipos de excepciones:
- Excepciones predefinidas
- Excepciones definidas por el usuario.
En este artículo voy a hablar sólo de las
excepciones predefinidas.
PL/SQL proporciona un gran número de excepciones
predefinidas que permiten controlar las condiciones de error más
habituales. Las excepciones predefinidas no necesitan ser declaradas y
son las siguientes:
DUP_VAL_ON_INDEX - Se produce cuando se intenta almacenar un valor ya existente en una columna que tiene restricción de índice único.
TIMEOUT_ON_RESOURCE - Se excedió el tiempo máximo de espera por un recurso en Oracle.
NOT_LOGGED_ON - El programa efectuó una llamada a Oracle sin estar conectado.
LOGIN_DENIED - El login o la contraseña utilizados para entrar en Oracle son inválidos.
NO_DATA_FOUND - Una sentencia
SELECT INTO no devolvió ningún registro.
TOO_MANY_ROWS - Una sentencia
SELECT INTO devolvió más de un registro.
ZERO_DIVIDE - Se ha ejecutado una división donde el divisor valía cero.
STORAGE_ERROR - Si no se dispone de más memoria o la memoria esta dañada.
PROGRAM_ERROR - Ocurrió un problema interno al ejecutar el código PL/SQL.
INVALID_NUMBER - Cuando falla la conversión de una cadena de caracteres hacia un número porque la cadena no representa un número válido.
VALUE_ERROR - Ocurrió un error
aritmético, de conversión o truncamiento. Por ejemplo, esto sucede
cuando se intenta dar un valor muy grande a una variable que no soporta
dicho tamaño.
ROWTYPE_MISMATCH - Los elementos
de una asignación (el valor a asignar y la variable que lo contendrá)
son de tipos incompatibles. También se presenta este error cuando un
parámetro pasado a un subprograma no es del tipo esperado.
SYS_INVALID_ROWID - Falla la conversión de una cadena de caracteres hacia un tipo
rowid porque la cadena no representa un número.
INVALID_CURSOR - Se efectuó una
operación no válida sobre un cursor. Suele ocurrir cuando un cursor no
está abierto y se ejecuta una sentencia para cerrar dicho cursor.
CURSOR_ALREADY_OPEN - Cuando se intenta abrir un cursor que ya estaba abierto. Hay que recordar que un cursor de tipo
FOR se abre automáticamente por lo que no se debe ejecutar la sentencia
OPEN.
ACCESS_INTO_NULL - Se intentó asignar un valor a los atributos de un objeto no inicializado.
COLLECTION_IS_NULL - Se intentó asignar un valor a una tabla anidada aún no inicializada.
SELF_IS_NULL - El parámetro
SELF (el primero que es pasado a un método
MEMBER) es nulo.
OTHERS - Cualquier otro tipo de error que pueda producirse. Cuando se utiliza la excepción
OTHERS,
cualquier excepción que no se haya tratado anteriormente se procesará
según la secuencia de instrucciones incluida dentro de la sección
OTHERS.
OTHERS debe ser la última excepción tratada dentro de la sección dedicada al tratamiento de excepciones.
La sintaxis de una sección para tratamiento de excepciones es como sigue:
BEGIN
[Secuencia de sentencias]
EXCEPTION
WHEN [nombre de la excepción 1] THEN
[Sentencias para tratar la excepción 1]
.................................................
WHEN [nombre de la excepción n] THEN
[Sentencias para tratar la excepción n]
WHEN OTHERS THEN
[Sentencias para tratar el resto de las excepciónes]
END;
En el siguiente ejemplo se utilizan las excepciones predefinidas
NO_DATA_FOUND,
TOO_MANY_ROWS y
OTHERS:
DECLARE
vprecio inventario.precio%TYPE;
BEGIN
[Otras sentencias]
BEGIN
SELECT precio FROM inventario
WHERE cantidad = 100
INTO vprecio;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE("No hay ningún artículo.");
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE("Hay más de un artículo.");
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE("Error, abortando ejecución.");
RAISE;
END;
[Otras sentencias]
END;
En este ejemplo si la sentencia
SELECT INTO fallase por no devolver ningún registro o por devolver más de uno, se
mandaría un mensaje de error a la pantalla
pero la ejecución del programa continuaría; por contra, para cualquier
otro error, aunque también se mandaría un mensaje de error a la
pantalla, la ejecución del programa se abortaría (comando
RAISE).