Recherche…


Introduction

Oracle produit diverses exceptions. Vous serez peut-être surpris de voir à quel point il peut être fastidieux d’arrêter votre code avec un message peu clair. Pour améliorer la capacité de votre code PL / SQL à être corrigé facilement, il est nécessaire de gérer les exceptions au niveau le plus bas. Ne cachez jamais une exception "sous le tapis", sauf si vous êtes ici pour garder votre morceau de code uniquement pour vous et pour que personne d'autre ne le maintienne.

Les erreurs prédéfinies .

Gestion des exceptions

  1. Qu'est-ce qu'une exception?

    Une exception dans PL / SQL est une erreur créée lors de l'exécution du programme.

    Nous avons trois types d'exceptions:

    • Exceptions définies en interne
    • Exceptions prédéfinies
    • Exceptions définies par l'utilisateur
  1. Qu'est-ce qu'une gestion des exceptions?

    La gestion des exceptions est une possibilité de garder notre programme en cours d’exécution même s’il apparaît une erreur d’exécution résultant, par exemple, d’erreurs de codage, de pannes matérielles.

Syntaxe

La syntaxe générale pour la section des exceptions:

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;

Une section d'exception doit figurer à la fin du bloc PL / SQL. PL / SQL nous donne la possibilité d’implanter des blocs, puis chaque bloc peut avoir sa propre section d’exception, par exemple:

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 l'exception est déclenchée dans le bloc imbriqué, elle doit être gérée dans la section d'exception interne, mais si la section d'exception interne ne gère pas cette exception, cette exception ira dans la section d'exception du bloc externe.

Exceptions définies en interne

Une exception définie en interne n'a pas de nom, mais elle a son propre code.

Quand l'utiliser?

Si vous savez que votre opération de base de données peut générer des exceptions spécifiques, celles qui n'ont pas de nom, alors vous pouvez leur donner des noms afin que vous puissiez écrire des gestionnaires d'exceptions spécifiques pour eux. Sinon, vous ne pouvez les utiliser qu'avec d' others gestionnaires d'exceptions.

Syntaxe

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; c'est la déclaration de nom d'exception.

pragma exception_init(my_name_exc,-37); attribuer un nom au code d'erreur de l'exception définie en interne.

Exemple

Nous avons un emp_id qui est une clé primaire dans la table emp et une clé étrangère dans la table dept. Si nous essayons de supprimer emp_id quand il a des enregistrements enfants, une exception sera lancée avec le code -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 documentation Oracle indique: "Une exception définie en interne avec un nom déclaré par l'utilisateur est toujours une exception définie en interne, et non une exception définie par l'utilisateur."

Exceptions prédéfinies

Les exceptions prédéfinies sont des exceptions définies en interne, mais elles ont des noms. La base de données Oracle soulève automatiquement ce type d'exceptions.

Exemple

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;
/

Vous trouverez ci-dessous des exemples, des noms d’exceptions avec leurs codes:

Nom d'exception Code d'erreur
AUCUNE DONNÉE DISPONIBLE -1403
ACCESS_INTO_NULL -6530
CASE_NOT_FOUND -6592
ROWTYPE_MISMATCH -6504
TOO_MANY_ROWS -1422
ZERO_DIVIDE -1476

Liste complète des noms d'exception et de leurs codes sur le site Web Oracle.

Exceptions définies par l'utilisateur

Comme son nom l'indique, les exceptions définies par l'utilisateur sont créées par les utilisateurs. Si vous souhaitez créer votre propre exception, vous devez:

  1. Déclarer l'exception
  2. Soulevez-le de votre programme
  3. Créez un gestionnaire d'exceptions approprié pour l'attraper.

Exemple

Je veux mettre à jour tous les salaires des travailleurs. Mais s'il n'y a pas de travailleurs, faites une exception.

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'est-ce que cela signifie raise ?

Les exceptions sont déclenchées automatiquement par le serveur de base de données en cas de besoin, mais si vous le souhaitez, vous pouvez générer explicitement toute exception à l'aide de raise .

Procédure raise_application_error(error_number,error_message);

  • error_number doit être compris entre -20000 et -20999
  • message d'erreur_message à afficher en cas d'erreur.

Définir une exception personnalisée, l'élever et voir d'où elle provient

Pour illustrer cela, voici une fonction qui a 3 comportements différents "erronés"

  • le paramètre est complètement stupide: nous utilisons une expression définie par l'utilisateur
  • le paramètre a une faute de frappe: nous utilisons l'erreur standard NO_DATA_FOUND Oracle
  • une autre affaire, mais pas traitée

N'hésitez pas à l'adapter à vos normes:

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;
/

Donner sur une base de données régulière:

[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

Rappelez-vous que cette exception concerne les cas rares . J'ai vu des applications qui ont soulevé une exception à chaque accès, simplement pour demander le mot de passe de l'utilisateur, en disant "non connecté" ... tant de déchets de calcul.

Gestion des exceptions d'erreur de connexion

Chaque erreur Oracle standard est associée à un numéro d'erreur. Il est important de prévoir ce qui pourrait mal tourner dans votre code. Ici, pour une connexion à une autre base de données, cela peut être:

  • -28000 compte est verrouillé
  • -28001 mot de passe expiré
  • -28002 période de grâce
  • -1017 mauvais utilisateur / mot de passe

Voici un moyen de tester ce qui ne va pas avec l'utilisateur utilisé par le lien de la base de données:

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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow