Varios Casos ejemplo para el tratamiento de Excepciones:
Transcripción
Varios Casos ejemplo para el tratamiento de Excepciones:
Ejemplificación de los Casos ejemplo para el tratamiento de Excepciones: Caso 1 Caso 2 DECLARE a EXCEPTION; BEGIN DBMS_OUTPUT.PUT_LINE('Inicio'); BEGIN RAISE a; DBMS_OUTPUT.PUT_LINE('Luego de raise a'); EXCEPTION WHEN a THEN DBMS_OUTPUT.PUT_LINE('a Se trata aquí'); END; DBMS_OUTPUT.PUT_LINE('El control va aquí'); END; / DECLARE a EXCEPTION; b EXCEPTION; BEGIN DBMS_OUTPUT.PUT_LINE('Inicio'); BEGIN RAISE b; EXCEPTION WHEN a THEN DBMS_OUTPUT.PUT_LINE('Se trata a'); END; DBMS_OUTPUT.PUT_LINE('Luego del subbloque'); EXCEPTION WHEN b THEN DBMS_OUTPUT.PUT_LINE('Se trata b aquí'); END; / Caso 3 Caso 4 DECLARE a EXCEPTION; b EXCEPTION; c EXCEPTION; BEGIN DBMS_OUTPUT.PUT_LINE('Inicio'); BEGIN RAISE c; EXCEPTION WHEN a THEN DBMS_OUTPUT.PUT_LINE('Se trata a'); END; DBMS_OUTPUT.PUT_LINE('Luego del subbloque'); EXCEPTION WHEN b THEN DBMS_OUTPUT.PUT_LINE('Se trata b'); END; / DECLARE val NUMBER(5):='hola'; BEGIN DBMS_OUTPUT.PUT_LINE('Inicio'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('No capturó errores en la declaración'); END; / Caso 5 Caso 6 BEGIN DBMS_OUTPUT.PUT_LINE('Inicio'); DECLARE x NUMBER(5):='Hola'; BEGIN DBMS_OUTPUT.PUT_LINE('Soy el subbloque'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('No capturó errores en la declaración'); END; DBMS_OUTPUT.PUT_LINE('Luego del subbloque'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Se trata aquí'); END; / DECLARE a EXCEPTION; b EXCEPTION; BEGIN DBMS_OUTPUT.PUT_LINE('Inicio'); RAISE a; EXCEPTION WHEN a THEN DBMS_OUTPUT.PUT_LINE('Estoy en a'); RAISE b; WHEN b THEN -- No captura a b DBMS_OUTPUT.PUT_LINE('Estoy en b'); END; / Caso 7 Caso 8 DECLARE a EXCEPTION; b EXCEPTION; BEGIN DBMS_OUTPUT.PUT_LINE('Inicio'); BEGIN RAISE a; EXCEPTION WHEN a THEN DBMS_OUTPUT.PUT_LINE('Estoy en a'); RAISE b; WHEN b THEN DBMS_OUTPUT.PUT_LINE('Estoy en b subbloque'); END; EXCEPTION WHEN b THEN DBMS_OUTPUT.PUT_LINE('Estoy en b externo'); END; / DECLARE a EXCEPTION; BEGIN DBMS_OUTPUT.PUT_LINE('Inicio'); RAISE a; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Por causa de a'); END; / Otros casos: a. Se declara una excepción con el mismo nombre en un bloque externo e interno. Se dispara en el interno y no se trata en el interno pero si en el externo. ¿Qué sucede? DECLARE w EXCEPTION; BEGIN DECLARE w EXCEPTION; BEGIN RAISE w; END; EXCEPTION WHEN w THEN DBMS_OUTPUT.PUT_LINE('Se generó w'); END; / Solución: Estas dos w's son excepciones diferentes y por lo tanto el bloque externo no la captura (de hecho la w interna NO es visible para el bloque externo). Lo siguiente tampoco funciona: BEGIN DECLARE w EXCEPTION; BEGIN RAISE w; EXCEPTION WHEN NO_DATA_FOUND THEN NULL; --Instrucción nula END; EXCEPTION WHEN w THEN DBMS_OUTPUT.PUT_LINE('Se generó w'); END; / w NO es conocida por el bloque externo como era de esperarse. b. Lo que si es válido es disparar desde el bloque interno una excepción externa incluso si se llama igual que una interna (recuérdese que se debe “nombrar” el bloque): <<externo>> --nombre del bloque DECLARE w EXCEPTION; BEGIN DECLARE w EXCEPTION; BEGIN RAISE externo.w; END; EXCEPTION WHEN w THEN DBMS_OUTPUT.PUT_LINE('Se generó w externa desde el bloque interno'); END; / c. Sin embargo si en un bloque interno se genera una excepción predefinida ésta si es capturada por el bloque externo (porque estas excepciones se pueden considerar como globales) BEGIN DECLARE a NUMBER; BEGIN a:= 7/0; --División por cero END; EXCEPTION WHEN ZERO_DIVIDE THEN DBMS_OUTPUT.PUT_LINE('Se dividió por cero'); END; / d. Sobre si desde la zona de excepción se puede "devolver" el control al bloque que disparó la excepción: DECLARE a EXCEPTION; BEGIN RAISE a; <<volver>> DBMS_OUTPUT.PUT_LINE('¡Ha retornado!'); EXCEPTION WHEN a THEN GOTO volver; END; / No es válido. Pero lo siguiente si es válido: DECLARE a EXCEPTION; BEGIN FOR k IN 1..10 LOOP DECLARE a EXCEPTION; BEGIN RAISE a; EXCEPTION WHEN a THEN DBMS_OUTPUT.PUT_LINE('Veces que se ha disparado a: '|| k); END; END LOOP; --El ciclo vuelve y "sube" y se ejecuta de nuevo el --subbloque... END; / Lo siguiente también es correcto: DECLARE dividendo NUMBER(3):= 4; divisor NUMBER(3); resultado NUMBER(3); BEGIN --A raiz de alguna operación se asigna un valor al divisor --en este caso para ejemplificar se asigna un cero divisor:= 0; <<volver>> BEGIN resultado := dividendo/divisor; DBMS_OUTPUT.PUT_LINE('La división fue '||resultado); EXCEPTION WHEN zero_divide THEN DBMS_OUTPUT.PUT_LINE('el divisor era cero, ¡se corregirá!'); divisor:= 2; GOTO volver; END; END; /