{"id":682,"date":"2019-05-13T21:21:37","date_gmt":"2019-05-14T01:51:37","guid":{"rendered":"http:\/\/gregorgonzalez.com.ve\/blog\/?p=682"},"modified":"2019-05-13T21:24:12","modified_gmt":"2019-05-14T01:54:12","slug":"manejo-de-excepciones-en-oracle","status":"publish","type":"post","link":"https:\/\/gregorgonzalez.com.ve\/blog\/manejo-de-excepciones-en-oracle\/","title":{"rendered":"Manejo de excepciones en Oracle"},"content":{"rendered":"<p>El manejo de errores es muy com\u00fan en cualquier aplicaci\u00f3n que estemos realizando, esto puede ser un proceso largo y tedioso si tambi\u00e9n contamos con los posibles errores de base de datos. Cuando trabajamos con Java, nos resulta m\u00e1s \u00fatil y r\u00e1pido pasar estos mensajes o manejar excepciones a trav\u00e9s de la base de datos directamente, nos evitamos cambiar a cada momento el c\u00f3digo fuente por un simple mensaje.<\/p>\n<p>Oracle nos permite manejar nuestras propias excepciones, asociando un n\u00famero de error y un mensaje, igual como se har\u00eda con excepciones en otros lenguajes de programaci\u00f3n. Este tipo de mensajes los podemos manejar con el procedimiento <strong>RAISE_APPLICATION_ERROR<\/strong>, esta opci\u00f3n solo est\u00e1 disponible en bloques<strong> PL\/SQL<\/strong> y podemos usarlo f\u00e1cilmente en funciones, procedimientos almacenados, triggers, etc. Se debe pasar dos par\u00e1metros, primero el n\u00famero de error y segundo el mensaje, tomando en cuenta que en el n\u00famero de error solo podemos establecer entre (<strong>-20000<\/strong> y <strong>-20999<\/strong>), s\u00ed, es un n\u00famero entero y en negativo, tendremos disponibles <strong>1000<\/strong> c\u00f3digos de error para usar.<\/p>\n<p>Imag\u00ednate que tienes una funci\u00f3n que recibe y retorna n\u00fameros, si deseas colocar un l\u00edmite, se podr\u00eda manejar con un simple IF, luego se podr\u00eda colocar que regrese NULL o cero (0) cuando no cumple la condici\u00f3n pero esto es un problema grave, primero, si es obligatorio que retorne un n\u00famero, no se deber\u00eda manejar NULL, si el cero no es indicativo si es un error o un n\u00famero correcto, aparte tendr\u00edas que validar el NULL o cero en cada ocasi\u00f3n que uses la funci\u00f3n, las excepciones ser\u00edan perfectos para manejar esto.<\/p>\n<p>Este es un ejemplo simple con funciones (Ser\u00eda similar para procedimientos):<\/p>\n<pre class=\"lang:plsql decode:true \">CREATE OR REPLACE FUNCTION evaluar_numero(\r\n    numero NUMBER\r\n)\r\n    RETURN NUMBER\r\nAS    \r\nBEGIN\r\n    IF numero &gt; 5 THEN\r\n        raise_application_error(-20000,'El numero no puede ser mayor a 5');\r\n    END IF;\r\n\r\n    RETURN numero;\r\nEND;<\/pre>\n<p>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.<\/p>\n<pre class=\"lang:default decode:true \">CREATE OR REPLACE TRIGGER eliminar_clietne\r\n    BEFORE DELETE \r\n    ON clientes    FOR EACH ROW\r\nDECLARE\r\n    cant_facturas             NUMERIC;\r\n    exist_fact_exception      EXCEPTION;\r\n    PRAGMA AUTONOMOUS_TRANSACTION;\r\nBEGIN\r\n        SELECT COUNT(*)\r\n            INTO cant_facturas\r\n            FROM facturas fact\r\n        WHERE fact.id_cliente = :OLD.id_cliente;\r\n\t\t\r\n        IF (cant_facturas &gt; 0)\r\n        THEN\r\n            RAISE exist_fact_exception;\r\n        END IF;\r\n\r\nEXCEPTION\r\n    WHEN exist_fact_exception\r\n    THEN\r\n        raise_application_error (-20001, 'El cliente no puede ser eliminado debido a que tiene facturas asociadas');\r\nEND;<\/pre>\n<p>Aunque tambi\u00e9n se puede manejar con una relaci\u00f3n restrictiva, el foreign key no indica exactamente un mensaje adecuado ni cu\u00e1l de todos fall\u00f3, adicional puedes ir agregando y escalando la validaci\u00f3n si tienes muchas m\u00e1s opciones que comprobar antes de eliminar.<\/p>\n<h3>Mensajes en Java<\/h3>\n<p>Al utilizar una herramienta como Toad para Oracle, nos mostrar\u00eda el mensaje inmediatamente, si fuese por consola debes habilitar la impresi\u00f3n 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\u00e9rica para todos los mensajes y utilizando el cl\u00e1sico try-catch.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-683 aligncenter\" src=\"http:\/\/gregorgonzalez.com.ve\/blog\/wp-content\/uploads\/toad-error.jpg\" alt=\"\" width=\"433\" height=\"187\" srcset=\"https:\/\/gregorgonzalez.com.ve\/blog\/wp-content\/uploads\/toad-error.jpg 433w, https:\/\/gregorgonzalez.com.ve\/blog\/wp-content\/uploads\/toad-error-300x130.jpg 300w\" sizes=\"(max-width: 433px) 100vw, 433px\" \/><\/p>\n<p>Lo m\u00e1s sencillo ser\u00eda usar una gen\u00e9rica sin importar el tipo de excepci\u00f3n, la que realmente devuelve el error seria de tipo SQLException, o tambi\u00e9n si necesitas manipular el flujo seg\u00fan el tipo mensaje, se puede a trav\u00e9s del c\u00f3digo de la excepci\u00f3n.<\/p>\n<pre class=\"lang:java decode:true \">try {\r\n    \/\/ Consulta SQL\r\n}catch(SQLException e) {\r\n    if(e.getErrorCode() == -20001) {\r\n        \/\/ Muestra el error e.getMessage()\r\n    }\r\n}<\/pre>\n<p>Nota: El m\u00e9todo getMessage devuelve una cadena larga que incluye el mensaje, para obtener solo el mensaje, se puede crear con alg\u00fan tipo de string delimitador, tipo \u00ab|Mi mensaje|\u00bb y luego cortarlo con un substring para obtener el mensaje solamente.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>El manejo de errores es muy com\u00fan en cualquier aplicaci\u00f3n que estemos realizando, esto puede ser un proceso largo y tedioso si tambi\u00e9n contamos con los posibles errores de base de datos. Cuando trabajamos con Java, nos resulta m\u00e1s \u00fatil y r\u00e1pido pasar estos mensajes o manejar excepciones a trav\u00e9s de la base de datos [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":660,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[239],"tags":[244,228,243],"_links":{"self":[{"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/posts\/682"}],"collection":[{"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/comments?post=682"}],"version-history":[{"count":3,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/posts\/682\/revisions"}],"predecessor-version":[{"id":686,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/posts\/682\/revisions\/686"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/media\/660"}],"wp:attachment":[{"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/media?parent=682"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/categories?post=682"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/tags?post=682"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}