Buscar..


Introducción

Oracle produce una variedad de excepciones. Es posible que se sorprenda de lo tedioso que puede ser que su código se detenga con un mensaje poco claro. Para mejorar la capacidad de su código PL / SQL para arreglarse fácilmente, es necesario manejar las excepciones en el nivel más bajo. Nunca oculte una excepción "debajo de la alfombra", a menos que esté aquí para guardar su parte del código solo para usted y para que nadie más lo pueda mantener.

Los errores predefinidos .

Manejo de excepciones

  1. ¿Qué es una excepción?

    La excepción en PL / SQL es un error creado durante la ejecución de un programa.

    Tenemos tres tipos de excepciones:

    • Excepciones definidas internamente
    • Excepciones predefinidas
    • Excepciones definidas por el usuario
  1. ¿Qué es una excepción de manejo?

    El manejo de excepciones es una posibilidad de mantener nuestro programa en ejecución incluso si aparece un error de tiempo de ejecución como resultado de, por ejemplo, errores de codificación, fallas de hardware. Evitamos que salga abruptamente.

Sintaxis

La sintaxis general para la sección de excepción:

declare
    declaration Section
begin
    some statements

exception
    when exception_one then
        do something
    when exception_two then
        do something
    when exception_three then
        do something
    when others then
        do something
end;

Una sección de excepción debe estar al final del bloque PL / SQL. PL / SQL nos da la oportunidad de anidar bloques, entonces cada bloque puede tener su propia sección de excepción, por ejemplo:

create or replace procedure nested_blocks
is
begin
    some statements
    begin
        some statements
        
    exception
        when exception_one then
            do something
    end;
exception 
    when exception_two then
        do something
end;

Si la excepción se generará en el bloque anidado, debe manejarse en la sección de excepción interna, pero si la sección de excepción interna no maneja esta excepción, esta excepción irá a la sección de excepción del bloque externo.

Excepciones definidas internamente

Una excepción definida internamente no tiene un nombre, pero tiene su propio código.

¿Cuándo usarlo?

Si sabe que la operación de su base de datos puede generar excepciones específicas a aquellas que no tienen nombres, puede darles nombres para que pueda escribir controladores de excepciones específicamente para ellos. De lo contrario, puede usarlos solo con others controladores de excepciones.

Sintaxis

declare 
    my_name_exc exception;
    pragma exception_init(my_name_exc,-37);
begin
    ...
exception 
    when my_name_exc then
        do something
end;

my_name_exc exception; Esa es la declaración del nombre de excepción.

pragma exception_init(my_name_exc,-37); Asigne un nombre al código de error de la excepción definida internamente.

Ejemplo

Tenemos un emp_id que es una clave primaria en la tabla emp y una clave externa en la tabla dept. Si intentamos eliminar emp_id cuando tiene registros secundarios, se lanzará una excepción con el código -2292.

create or replace procedure remove_employee
is
    emp_exception exception;
    pragma exception_init(emp_exception,-2292);
begin
    delete from emp where emp_id = 3;
exception
    when emp_exception then
        dbms_output.put_line('You can not do that!');
end;
/

La documentación de Oracle dice: "Una excepción definida internamente con un nombre declarado por el usuario sigue siendo una excepción definida internamente, no una excepción definida por el usuario".

Excepciones predefinidas

Las excepciones predefinidas son excepciones definidas internamente pero tienen nombres. La base de datos Oracle eleva este tipo de excepciones automáticamente.

Ejemplo

create or replace procedure insert_emp
is
begin
    insert into emp (emp_id, ename) values ('1','Jon');

exception
    when dup_val_on_index then
        dbms_output.put_line('Duplicate value on index!');
end;
/

A continuación se muestran ejemplos de excepciones con sus códigos:

Nombre de excepción Código de error
DATOS NO ENCONTRADOS -1403
ACCESS_INTO_NULL -6530
CASE_NOT_FOUND -6592
ROWTYPE_MISMATCH -6504
TOO_MANY_ROWS -1422
CERO_DIVIDIR -1476

Lista completa de nombres de excepciones y sus códigos en el sitio web de Oracle.

Excepciones definidas por el usuario

Como el nombre sugiere, los usuarios crean excepciones definidas por el usuario. Si desea crear su propia excepción, debe:

  1. Declarar la excepción
  2. Levántalo de tu programa
  3. Crea un manejador de excepciones adecuado para atraparlo.

Ejemplo

Quiero actualizar todos los salarios de los trabajadores. Pero si no hay trabajadores, levante una excepción.

create or replace procedure update_salary
is
    no_workers exception;
    v_counter number := 0;
begin
    select count(*) into v_counter from emp;
    if v_counter = 0 then
        raise no_workers;
    else
        update emp set salary = 3000;
    end if;

    exception
        when no_workers then
            raise_application_error(-20991,'We don''t have workers!');                
end;
/

¿Qué significa raise ?

Las excepciones son generadas por el servidor de la base de datos automáticamente cuando es necesario, pero si lo desea, puede generar explícitamente cualquier excepción mediante el uso de raise .

Procedimiento raise_application_error(error_number,error_message);

  • error_number debe estar entre -20000 y -20999
  • mensaje de error mensaje que se muestra cuando se produce un error.

Defina una excepción personalizada, levántela y vea de dónde viene.

Para ilustrar esto, aquí hay una función que tiene 3 comportamientos "incorrectos" diferentes

  • el parámetro es completamente estúpido: usamos una expresión definida por el usuario
  • el parámetro tiene un error tipográfico: utilizamos el error NO_DATA_FOUND estándar de Oracle
  • otro caso, pero no manejado

Siéntete libre de adaptarlo a tus estándares:

DECLARE
  this_is_not_acceptable EXCEPTION;
  PRAGMA EXCEPTION_INIT(this_is_not_acceptable, -20077);
  g_err varchar2 (200) := 'to-be-defined';
  w_schema all_tables.OWNER%Type;

  PROCEDURE get_schema( p_table in Varchar2, p_schema out Varchar2)
  Is 
    w_err varchar2 (200) := 'to-be-defined';
  BEGIN
    w_err := 'get_schema-step-1:';
    If (p_table = 'Delivery-Manager-Is-Silly') Then
      raise this_is_not_acceptable;
    end if;
    w_err := 'get_schema-step-2:';
    Select owner Into p_schema 
      From all_tables
     where table_name like(p_table||'%');
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
    -- handle Oracle-defined exception
     dbms_output.put_line('[WARN]'||w_err||'This can happen. Check the table name you entered.');
  WHEN this_is_not_acceptable THEN
    -- handle your custom error
     dbms_output.put_line('[WARN]'||w_err||'Please don''t make fun of the delivery manager.');
  When others then
     dbms_output.put_line('[ERR]'||w_err||'unhandled exception:'||sqlerrm);
     raise;    
  END Get_schema;  

BEGIN
  g_err := 'Global; first call:';
  get_schema('Delivery-Manager-Is-Silly', w_schema);
  g_err := 'Global; second call:';
  get_schema('AAA', w_schema);
  g_err := 'Global; third call:';
  get_schema('', w_schema);
  g_err := 'Global; 4th call:';
  get_schema('Can''t reach this point due to previous error.', w_schema);
  
EXCEPTION
  When others then
     dbms_output.put_line('[ERR]'||g_err||'unhandled exception:'||sqlerrm);
  -- you may raise this again to the caller if error log isn't enough.
--  raise;
END;
/

Dar en una base de datos regular:

[WARN]get_schema-step-1:Please don't make fun of the delivery manager.
[WARN]get_schema-step-2:This can happen. Check the table name you entered.
[ERR]get_schema-step-2:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows
[ERR]Global; third call:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows

Recuerde que la excepción está aquí para manejar casos raros . Vi aplicaciones que generaron una excepción en cada acceso, solo para solicitar la contraseña del usuario, diciendo "no conectado" ... tanto desperdicio de cómputo.

Manejo de excepciones de error de conexión

Cada error estándar de Oracle está asociado con un número de error. Es importante anticipar lo que podría salir mal en su código. Aquí para una conexión a otra base de datos, puede ser:

  • -28000 cuenta está bloqueada
  • -28001 contraseña caducada
  • -28002 periodo de gracia
  • -1017 usuario incorrecto / contraseña

Aquí hay una manera de probar qué falla con el usuario que usa el enlace de la base de datos:

declare
  v_dummy number;
begin
  -- testing db link
  execute immediate 'select COUNT(1) from [email protected]' into v_dummy ;
  -- if we get here, exception wasn't raised: display COUNT's result
  dbms_output.put_line(v_dummy||' users on PASS db');

EXCEPTION
  -- exception can be referred by their name in the predefined Oracle's list
    When LOGIN_DENIED 
    then  
        dbms_output.put_line('ORA-1017 / USERNAME OR PASSWORD INVALID, TRY AGAIN');
    When Others 
    then 
  -- or referred by their number: stored automatically in reserved variable SQLCODE    
        If  SQLCODE = '-2019'
        Then    
          dbms_output.put_line('ORA-2019 / Invalid db_link name');
        Elsif SQLCODE = '-1035'
        Then
          dbms_output.put_line('ORA-1035 / DATABASE IS ON RESTRICTED SESSION, CONTACT YOUR DBA');        
        Elsif SQLCODE = '-28000'
        Then
          dbms_output.put_line('ORA-28000 / ACCOUNT IS LOCKED. CONTACT YOUR DBA');
        Elsif SQLCODE = '-28001'
        Then
          dbms_output.put_line('ORA-28001 / PASSWORD EXPIRED. CONTACT YOUR DBA FOR CHANGE');
        Elsif SQLCODE  = '-28002'
        Then
          dbms_output.put_line('ORA-28002 / PASSWORD IS EXPIRED, CHANGED IT');
        Else
   -- and if it's not one of the exception you expected
          dbms_output.put_line('Exception not specifically handled');
          dbms_output.put_line('Oracle Said'||SQLCODE||':'||SQLERRM);
        End if;
END;
/


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow