El manejo de errores es muy común en cualquier aplicación que estemos realizando, esto puede ser un proceso largo y tedioso si también contamos con los posibles errores de base de datos. Cuando trabajamos con Java, nos resulta más útil y rápido pasar estos mensajes o manejar excepciones a través de la base de datos directamente, nos evitamos cambiar a cada momento el código fuente por un simple mensaje.
Oracle nos permite manejar nuestras propias excepciones, asociando un número de error y un mensaje, igual como se haría con excepciones en otros lenguajes de programación. Este tipo de mensajes los podemos manejar con el procedimiento RAISE_APPLICATION_ERROR, esta opción solo está disponible en bloques PL/SQL y podemos usarlo fácilmente en funciones, procedimientos almacenados, triggers, etc. Se debe pasar dos parámetros, primero el número de error y segundo el mensaje, tomando en cuenta que en el número de error solo podemos establecer entre (-20000 y -20999), sí, es un número entero y en negativo, tendremos disponibles 1000 códigos de error para usar.
Imagínate que tienes una función que recibe y retorna números, si deseas colocar un límite, se podría manejar con un simple IF, luego se podría colocar que regrese NULL o cero (0) cuando no cumple la condición pero esto es un problema grave, primero, si es obligatorio que retorne un número, no se debería manejar NULL, si el cero no es indicativo si es un error o un número correcto, aparte tendrías que validar el NULL o cero en cada ocasión que uses la función, las excepciones serían perfectos para manejar esto.
Este es un ejemplo simple con funciones (Sería similar para procedimientos):
1 2 3 4 5 6 7 8 9 10 11 12 |
CREATE OR REPLACE FUNCTION evaluar_numero( numero NUMBER ) RETURN NUMBER AS BEGIN IF numero > 5 THEN raise_application_error(-20000,'El numero no puede ser mayor a 5'); END IF; RETURN numero; END; |
Este ejemplo es de un trigger, si tenemos una tabla clientes y queremos que no se pueda eliminar aquellos clientes que tengan una factura asociada y mostrar un mensaje adecuado para el tipo de error.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
CREATE OR REPLACE TRIGGER eliminar_clietne BEFORE DELETE ON clientes FOR EACH ROW DECLARE cant_facturas NUMERIC; exist_fact_exception EXCEPTION; PRAGMA AUTONOMOUS_TRANSACTION; BEGIN SELECT COUNT(*) INTO cant_facturas FROM facturas fact WHERE fact.id_cliente = :OLD.id_cliente; IF (cant_facturas > 0) THEN RAISE exist_fact_exception; END IF; EXCEPTION WHEN exist_fact_exception THEN raise_application_error (-20001, 'El cliente no puede ser eliminado debido a que tiene facturas asociadas'); END; |
Aunque también se puede manejar con una relación restrictiva, el foreign key no indica exactamente un mensaje adecuado ni cuál de todos falló, adicional puedes ir agregando y escalando la validación si tienes muchas más opciones que comprobar antes de eliminar.
Mensajes en Java
Al utilizar una herramienta como Toad para Oracle, nos mostraría el mensaje inmediatamente, si fuese por consola debes habilitar la impresión de mensajes por pantalla, en el caso de Java, se puede manejar de varias maneras, creando tus propias excepciones para cada error o una genérica para todos los mensajes y utilizando el clásico try-catch.
Lo más sencillo sería usar una genérica sin importar el tipo de excepción, la que realmente devuelve el error seria de tipo SQLException, o también si necesitas manipular el flujo según el tipo mensaje, se puede a través del código de la excepción.
1 2 3 4 5 6 7 |
try { // Consulta SQL }catch(SQLException e) { if(e.getErrorCode() == -20001) { // Muestra el error e.getMessage() } } |
Nota: El método getMessage devuelve una cadena larga que incluye el mensaje, para obtener solo el mensaje, se puede crear con algún tipo de string delimitador, tipo «|Mi mensaje|» y luego cortarlo con un substring para obtener el mensaje solamente.