Manejo de excepciones en PL/SQL

Una excepción es un error que interrumpe el flujo normal de las instrucciones del programa. PL/SQL nos proporciona el bloque de excepción que genera la excepción, lo que ayuda al programador a encontrar la falla y resolverla.

Hay dos tipos de excepciones definidas en PL/SQL

  1. Excepción definida por el usuario.
  2. Excepciones definidas por el sistema.

Sintaxis para escribir una excepción

WHEN exception THEN 
    statement;

Sección de declaraciones DECLARE ;

BEGIN
comando(s) ejecutable(s);

EXCEPCIÓN
CUANDO excepción1 ENTONCES
instrucción1;
CUANDO excepción2 ENTONCES
instrucción2;
[CUANDO otros ENTONCES]
/* código de manejo de excepciones predeterminado */

FINAL;

Nota:
Cuando otra palabra clave debe usarse solo al final del bloque de manejo de excepciones, ya que no se ejecutará ninguna parte de manejo de excepciones presente más adelante, ya que el control saldrá del bloque después de ejecutar CUANDO OTROS.

  1. Excepciones definidas por el sistema:

  2. Estas excepciones están predefinidas en PL/SQL y se generan CUANDO se viola cierta regla de la base de datos.
    Las excepciones definidas por el sistema se dividen en dos categorías:

    1. Excepciones del sistema con nombre.
    2. Excepciones del sistema sin nombre.
  • Excepciones del sistema con nombre: tienen un nombre predefinido por el sistema como ACCESS_INTO_NULL, DUP_VAL_ON_INDEX, LOGIN_DENIED, etc. La lista es bastante grande.

    Así que discutiremos algunas de las excepciones más utilizadas:

    Vamos a crear una mesa frikis.

    create table geeks(g_id int , g_name varchar(20), marks int); 
    insert into geeks values(1, 'Suraj',100);
    insert into geeks values(2, 'Praveen',97);
    insert into geeks values(3, 'Jessie', 99);
    

    1. NO_DATA_FOUND : se genera CUANDO una declaración SELECT INTO no devuelve filas. Por ejemplo:

      DECLARE
         temp varchar(20);
        
      BEGIN
         SELECT g_id into temp from geeks where g_name='GeeksforGeeks';
        
      exception
         WHEN no_data_found THEN
            dbms_output.put_line('ERROR');
            dbms_output.put_line('there is no name as');
            dbms_output.put_line('GeeksforGeeks in geeks table');
      end;

      Producción:

      ERROR
      there is no name as GeeksforGeeks in geeks table
      
    2. TOO_MANY_ROWS : se genera CUANDO una declaración SELECT INTO devuelve más de una fila.

      DECLARE
         temp varchar(20);
        
      BEGIN
        
      -- raises an exception as SELECT 
      -- into trying to return too many rows
         SELECT g_name into temp from geeks;
         dbms_output.put_line(temp);
        
      EXCEPTION
         WHEN too_many_rows THEN
            dbms_output.put_line('error trying to SELECT too many rows');
        
      end;

      Producción:

      error trying to SELECT too many rows
      
    3. VALUE_ERROR : este error se genera CUANDO se ejecuta una declaración que resultó en un error aritmético, numérico, de string, de conversión o de restricción. Este error se debe principalmente a un error del programador o a una entrada de datos no válida.

      DECLARE
         temp number;   
        
      BEGIN
         SELECT g_name  into temp from geeks where g_name='Suraj';
         dbms_output.put_line('the g_name is '||temp);
        
      EXCEPTION
         WHEN value_error THEN
         dbms_output.put_line('Error');
         dbms_output.put_line('Change data type of temp to varchar(20)');
        
      END;

      Producción:

      Error
      Change data type of temp to varchar(20)
      
    4. ZERO_DIVIDE = genera una excepción AL dividir con cero.

      DECLARE
         a int:=10;
         b int:=0;
         answer int;
        
      BEGIN
         answer:=a/b;
         dbms_output.put_line('the result after division is'||answer);
        
      exception
         WHEN zero_divide THEN
            dbms_output.put_line('dividing by zero please check the values again');
            dbms_output.put_line('the value of a is '||a);
            dbms_output.put_line('the value of b is '||b);
      END;

      Producción:

      dividing by zero please check the values again
      the value of a is 10
      the value of b is 0
      
  • Excepciones del sistema sin nombre: Oracle no proporciona el nombre de algunas excepciones del sistema llamadas excepciones del sistema sin nombre. Estas excepciones no ocurren con frecuencia. Estas excepciones tienen un código de dos partes y un mensaje asociado .
    La forma de manejar estas excepciones es asignarles un nombre usando la sintaxis Pragma EXCEPTION_INIT :
    PRAGMA EXCEPTION_INIT(exception_name, -error_number);
    

    error_number están predefinidos y tienen un rango de enteros negativos de -20000 a -20999.

    Ejemplo:

    DECLARE
       exp exception;
       pragma exception_init (exp, -20015);
       n int:=10;
      
    BEGIN 
       FOR i IN 1..n LOOP
          dbms_output.put_line(i*i);
             IF i*i=36 THEN
                RAISE exp;
             END IF;
       END LOOP;
      
    EXCEPTION
       WHEN exp THEN
          dbms_output.put_line('Welcome to GeeksforGeeks');
      
    END;

    Producción:

    1
    4
    9
    16
    25
    36
    Welcome to GeeksforGeeks
    

  • Excepciones definidas por el usuario:
    este tipo de usuarios puede crear sus propias excepciones de acuerdo con la necesidad y para generar estas excepciones se utiliza explícitamente el comando de generación.

    Ejemplo:

    • Divide el entero no negativo x por y de modo que el resultado sea mayor o igual a 1.

      De la pregunta dada podemos concluir que existen dos excepciones

      • La división sea cero.
      • Si el resultado es mayor o igual a 1 significa que y es menor o igual a x.

      DECLARE
         x int:=&x; /*taking value at run time*/
         y int:=&y;
         div_r float;
         exp1 EXCEPTION;
         exp2 EXCEPTION;
        
      BEGIN
         IF y=0 then
             raise exp1;
        
         ELSEIF y > x then
            raise exp2;
        
         ELSE
            div_r:= x / y;
            dbms_output.put_line('the result is '||div_r);
        
         END IF;
        
      EXCEPTION
         WHEN exp1 THEN
            dbms_output.put_line('Error');
            dbms_output.put_line('division by zero not allowed');
        
         WHEN exp2 THEN
            dbms_output.put_line('Error');
            dbms_output.put_line('y is greater than x please check the input');
        
      END;
      Input 1: x = 20
               y = 10
      
      Output: the result is 2
      
      Input 2: x = 20
               y = 0
      
      Output:
      Error
      division by zero not allowed
      
      Input 3: x=20
               y = 30
      
      Output:<.em>
      Error
      y is greater than x please check the input
      

    RAISE_APPLICATION_ERROR :
    se utiliza para mostrar mensajes de error definidos por el usuario con un número de error cuyo rango está entre -20000 y -20999. Cuando se ejecuta RAISE_APPLICATION_ERROR, devuelve un mensaje de error y un código de error que tiene el mismo aspecto que el error integrado de Oracle.

    Ejemplo:

    DECLARE
        myex EXCEPTION;
        n NUMBER :=10;
      
    BEGIN
        FOR i IN 1..n LOOP
        dbms_output.put_line(i*i);
            IF i*i=36 THEN
            RAISE myex;
            END IF;
        END LOOP;
      
    EXCEPTION
        WHEN myex THEN
            RAISE_APPLICATION_ERROR(-20015, 'Welcome to GeeksForGeeks');
      
    END;

    Producción:

    Error report:
    ORA-20015: Welcome to GeeksForGeeks
    ORA-06512: at line 13
    
    1
    4
    9
    16
    25
    36
    
    
    

    Nota: La salida se basa en el desarrollador de Oracle Sql, el orden de salida puede cambiar SI está ejecutando este código en otro lugar.

    Reglas de alcance en el manejo de excepciones :

    1. No podemos DECLARAR una excepción dos veces, pero podemos DECLARAR la misma excepción en dos bloques diferentes.
    2. Las excepciones DECLARADAS dentro de un bloque son locales para ese bloque y globales para todos sus sub-bloques.

    Como un bloque solo puede hacer referencia a excepciones locales o globales, los bloques que lo encierran no pueden hacer referencia a excepciones DECLARADAS en un subbloque.
    Si volvemos a DECLARAR una excepción global en un subbloque, la declaración local prevalece, es decir, el alcance de local es mayor.

    Ejemplo:

    DECLARE
       GeeksforGeeks EXCEPTION;
       age NUMBER:=16;
    BEGIN
      
       --  sub-block BEGINs 
       DECLARE       
            
          -- this declaration prevails 
          GeeksforGeeks  EXCEPTION;  
          age NUMBER:=22;
        
       BEGIN
          IF age > 16 THEN
             RAISE GeeksforGeeks; /* this is not handled*/
          END IF;
         
       END;          
       -- sub-block ends
      
    EXCEPTION
      -- Does not handle raised exception 
      WHEN GeeksforGeeks THEN
        DBMS_OUTPUT.PUT_LINE
          ('Handling  GeeksforGeeks exception.');
        
      WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE
          ('Could not recognize exception GeeksforGeeks  in this scope.');
    END;

    Producción:

    Could not recognize exception GeeksforGeeks  in this scope.
    
  • ventajas:

    • El manejo de excepciones es muy útil para el manejo de errores, sin él tenemos que emitir el comando en cada punto para verificar los errores de ejecución:
      Ejemplo:
      Select ..
      .. check for 'no data found' error
      Select ..
      .. check for 'no data found' error
      Select .. 
      .. check for 'no data found' error
      

      Aquí podemos ver que no es robusto ya que el procesamiento de errores no está separado del procesamiento normal y SI nos perdemos alguna línea en el código, puede conducir a algún otro tipo de error.

    • Con el manejo de excepciones, manejamos errores sin escribir declaraciones varias veces e incluso podemos manejar diferentes tipos de errores en un bloque de excepción:
      Ejemplo:
      BEGIN
         SELECT ...
         SELECT ...
         SELECT ...
          .
          .
          .
      exception 
         WHEN NO_DATA_FOUND THEN  /* catches all 'no data found' errors */
           ...
         WHEN ZERO_DIVIDE THEN    /* different types of */
         WHEN value_error THEN    /* errors handled in same block */
         ...   
       

    Del código anterior podemos concluir que el manejo de excepciones

    1. Mejora la legibilidad al permitirnos aislar las rutinas de manejo de errores y, por lo tanto, brindar robustez.
    2. Brinda confiabilidad , en lugar de verificar diferentes tipos de errores en cada punto, simplemente podemos escribirlos en un bloque de excepción y SI existe un error, se generará una excepción, lo que ayudará al programador a descubrir el tipo de error y eventualmente resolverlo.

    Usos : uno de los usos reales de excepción se puede encontrar en el sistema de reserva de trenes en línea.
    Al completar el código de la estación para reservar el boleto, SI ingresamos un código incorrecto, nos muestra la excepción de que el código no existe en la base de datos.

    Referencia: Puede encontrar la lista de todas las excepciones predefinidas aquí.
    Número total de excepciones predefinidas

    Publicación traducida automáticamente

    Artículo escrito por SrjSunny y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *