adplus-dvertising

Gestion d'exceptions en Oracle

Gestion d'exceptions en Oracle

Si un programme affiche un flux inhabituel et inattendu pendant l'exécution, ce qui peut entraîner l'arrêt anormal du programme, la situation est considérée comme une exception. Ces erreurs doivent être interceptées et traitées dans la section EXCEPTION du bloc PL/SQL. Les gestionnaires d'exceptions peuvent supprimer l'arrêt anormal avec une action alternative et sécurisée.

La gestion des exceptions est l'une des étapes importantes de la programmation d'une base de données. Les exceptions non gérées peuvent entraîner des pannes d'applications imprévues, avoir un impact sur la continuité des activités et frustrer les utilisateurs finaux.

Il existe deux types d'exceptions: définies par le système et définies par l'utilisateur. Alors que la base de données Oracle déclenche implicitement une exception définie par le système, une exception définie par l'utilisateur est explicitement déclarée et déclenchée dans l'unité de programme.

En outre, Oracle fournit deux fonctions utilitaires, SQLCODE et SQLERRM, pour récupérer le code d'erreur et le message de l'exception la plus récente.

Exceptions définies par le système

Comme son nom l'indique, les exceptions définies par le système sont définies et gérées implicitement par la base de données Oracle. Elles sont définis dans le package Oracle STANDARD. Chaque fois qu'une exception se produit dans un programme, la base de données récupère l'exception appropriée dans la liste disponible. Toutes les exceptions définies par le système sont associées à un code d'erreur négatif (sauf 1 à 100) et à un nom abrégé, qui est utilisé lors de la spécification des gestionnaires d'exceptions.
Par exemple, le programme PL/SQL suivant inclut une instruction SELECT pour sélectionner les détails de l'employé 8376. Il déclenche une exception NO_DATA_FOUND car l'ID d'employé 8376 n'existe pas.

DECLARE
    Nom VARCHAR2 (100);
    Salaire NUMBER;
    EMPID NUMBER := 8376;
BEGIN
    SELECT ENAME, SAL INTO Nom, Salaire FROM EMP WHERE EMPNO = EMPID;
END;
/
                            
 DECLARE
 *
 ERROR at line 1:
 ORA-01403: no data found
 ORA-06512: at line 8

Réécrivons le bloc PL/SQL précédent pour inclure une section EXCEPTION et gérer l'exception NO_DATA_FOUND:

DECLARE
    Nom VARCHAR2 (100);
    Salaire NUMBER;
    EMPID NUMBER := 8376;
BEGIN
    SELECT ENAME, SAL INTO Nom, Salaire FROM EMP WHERE EMPNO = EMPID;

EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE ('Aucun employé n existe avec l identifiant '||EMPID);
END;
/
                            
 Aucun employé n existe avec l identifiant 8376
 PL/SQL procedure successfully completed. 

Le tableau suivant présente certaines exceptions définies par le système, ainsi que leur nom abrégé et leur code d'erreur ORA:

ErreurNom d'exceptionSoulevéss quand
ORA-00001DUP_VAL_ON_INDEXUne valeur en double existe
ORA-01001INVALID_CURSORLe curseur n'est pas valide
ORA-010121NOT_LOGGED_ONL'utilisateur n'est pas connecté
ORA-01017LOGIN_DENIEDUne erreur système s'est produite
ORA-01017LOGIN_DENIEDUne erreur système s'est produite
ORA-01017LOGIN_DENIEDUne erreur système s'est produite
ORA-01403NO_DATA_FOUNDLa requête ne renvoie aucune donnée
ORA-01422TOO_MANY_ROWSUne requête sur une seule ligne renvoie plusieurs lignes
ORA-01476ZERO_DIVIDEUne tentative a été faite pour diviser un nombre par zéro
ORA-01722INVALID_NUMBERLe numéro est invalide
ORA-06504ROWTYPE_MISMATCHUne incompatibilité s'est produite dans le type de ligne
ORA-06511CURSOR_ALREADY_OPENLe curseur est déjà ouvert
ORA-06532COLLECTION_IS_NULLTravailler avec la collection NULL
ORA-06531SUBSCRIPT_OUTSIDE_LIMITIndex de collection hors de portée
>ORA-06533SUBSCRIPT_BEYOND_COUNTIndex de collection hors de compte

Exceptions définies par l'utilisateur

Oracle permet aux utilisateurs de créer des exceptions personnalisées, de spécifier des noms, d'associer des codes d'erreur et de déclencher des instructions conformément à la logique de mise en œuvre. Si les applications PL/SQL doivent normaliser la gestion des exceptions, non seulement pour contrôler le flux de programme anormal, mais également pour modifier la logique d'exécution du programme, vous devez utiliser des exceptions définies par l'utilisateur. Les exceptions définies par l'utilisateur sont déclenchées dans la section BEGIN..END du bloc à l'aide de l'instruction RAISE.

Il existe trois façons de déclarer des exceptions :

  •   Déclarez la variable de type EXCEPTION dans la section déclaration. Soulevez cette exception explicitement dans le corps du programme à l'aide de l'instruction RAISE. Gérez cette exception dans la section EXCEPTION. Notez qu'aucun code d'erreur n'est impliqué ici.
  •  Déclarez la variable EXCEPTION et associez-la à un numéro d'erreur standard à l'aide de PRAGMA EXCEPTION_INIT.
    Un Pragma est une directive adressée au compilateur pour manipuler le comportement de l'unité de programme pendant la compilation, et non au moment de l'exécution.
    PRAGMA EXCEPTION_INIT peut également être utilisé pour mapper une exception à une exception non prédéfinie. Ce sont des erreurs standard d'Oracle mais non définies comme des exceptions PL/SQL.
  •   Utilisez RAISE_APPLICATION_ERROR pour déclarer un numéro d'erreur et un message d'erreur dédiés.

Le bloc PL/SQL suivant déclare une exception définie par l'utilisateur et la déclenche dans le corps du programme:

DECLARE
    a NUMBER :=5;
    b NUMBER :=0;
    res NUMBER;
    /* Déclarer une exception ERREUR */
    ERREUR EXCEPTION;
BEGIN
    IF b=0 THEN
        RAISE ERREUR;
    END IF
    res:= a/b
    DBMS_OUTPUT.PUT_LINE('Le résultat est  : '||res);
    
EXCEPTION
    WHEN ERREUR THEN
        DBMS_OUTPUT.PUT_LINE ('La valeur de b doit être différente de zéro ');
END;
/
                            
 La valeur de b doit être différente de zéro
 PL/SQL procedure successfully completed. 

La procédure RAISE_APPLICATION_ERROR

RAISE_APPLICATION_ERROR est une procédure fournie par Oracle qui déclenche une exception définie par l'utilisateur avec un message d'exception personnalisé. L'exception peut être éventuellement prédéfinie dans la section déclaration du PL/SQL.
La syntaxe de la procédure RAISE_APPLICATION_ERROR est la suivante:

RAISE_APPLICATION_ERROR (numero_erreur, message_erreur[, {TRUE |FALSE}])
                            

Dans cette syntaxe, le paramètre numero_erreur est un paramètre obligatoire dont la valeur d'erreur est comprise entre 20000 et 20999. message_erreur est le message défini par l'utilisateur qui apparaît avec l'exception. Le dernier paramètre est un argument facultatif utilisé pour ajouter le code d'erreur d'exception à la pile d'erreurs actuelle.

Le programme PL/SQL suivant liste les employés qui ont rejoint l'organisation après la date donnée. Le programme doit lever une exception si la date d'embauche est antérieure à la date donnée. Le bloc utilise RAISE_APPLICATION_ERROR pour lever l'exception avec un code d'erreur 20005, et un message d'erreur approprié apparaît à l'écran :

DECLARE
    DATE_DONNEE DATE := '01-DEC-1981';
    CURSOR C IS SELECT empno, ename, hiredate FROM emp;
BEGIN
    FOR I IN C
    LOOP
        IF i.hiredate < DATE_DONNEE THEN
            RAISE_APPLICATION_ERROR (-20005,'Date d embauche antérieure à la date donnée !');
        ELSE
            DBMS_OUTPUT.PUT_LINE(i.ename||'a été embauché le'||i.hiredate);
        END IF;
    END LOOP;
END;
/
                            
 Error report -
 ORA-20005: Date d embauche antérieure à la date donnée !
 ORA-06512: at line 8 

Dans l'exemple précédent, notez que le nom de l'exception n'est pas utilisé pour créer le gestionnaire d'exception. Juste après que l'exception ait été levée par RAISE_APPLICATION_ERROR, le programme est terminé.
Si vous souhaitez avoir un gestionnaire d'exception spécifique pour les exceptions soulevées par RAISE_APPLICATION_ERROR, vous devez déclarer l'exception dans la section déclaration et associer le numéro d'erreur en utilisant PRAGMA EXCEPTION_INIT.

DECLARE
    DATE_DONNEE DATE := '01-DEC-1981';

    /*Déclarer la variable d'exception*/
    INVALID_EMP_DATES EXCEPTION;
    PRAGMA EXCEPTION_INIT(INVALID_EMP_DATES,-20005);

    CURSOR C IS SELECT empno, ename, hiredate FROM emp;
BEGIN
    FOR I IN C
    LOOP
        IF i.hiredate < DATE_DONNEE THEN
            RAISE INVALID_EMP_DATES;
        ELSE
            DBMS_OUTPUT.PUT_LINE(i.ename||'a été embauché le'||i.hiredate);
        END IF;
    END LOOP;
EXCEPTION
    WHEN INVALID_EMP_DATES THEN
        DBMS_OUTPUT.PUT_LINE(SQLERRM||'Date d embauche antérieure à la date donnée !');
END;
/
                            
 ORA-20005: Date d embauche antérieure à la date donnée
 PL/SQL procedure successfully completed. 

Propagation des exceptions

Jusqu'à présent, nous avons vu que, dès que l'exception est levée dans la section BEGIN d'un bloc PL/SQL, le contrôle saute à la section EXCEPTION et choisit le gestionnaire d'exception approprié. L'inexistence du gestionnaire d'exception peut conduire à la fin anormale du programme.

Dans le cas de blocs PL/SQL imbriqués, si l'exception est déclenchée dans un bloc interne, le contrôle du programme descend vers la section d'exception du bloc interne. Si le bloc interne gère l'exception, il est exécuté et le contrôle du programme retourne à l'instruction exécutable suivante dans le bloc externe.

Si le bloc interne ne gère pas l'exception, le contrôle de programme continue de rechercher le gestionnaire approprié et se propage à la section d'exception du bloc externe. L'exécution du bloc externe est ignorée et le contrôle du programme arrive directement dans la section d'exception. Le contrôle de programme continuera à propager l'exception non gérée dans les blocs externes jusqu'à ce que celle appropriée soit trouvée et gérée.

Par exemple, le programme PL/SQL suivant contient un bloc interne dans le bloc externe:

/*bloc externe*/
DECLARE
    ...
BEGIN
    /*Instructions exécutables de bloc externe*/
    ...
    /*bloc interne*/
    DECLARE
        ...
    BEGIN
        ...
        /*Instructions exécutables de bloc interne*/
        ...
    EXCEPTION
        /*Gestionnaires d'exceptions de bloc interne*/
    END;
    ...

    /*Instructions exécutables de bloc externe*/
EXCEPTION
    /*Gestionnaires d'exceptions de bloc exetrne*/
END;
                            

Si l'exception est déclenchée dans l'une des instructions /* Instructions exécutables de bloc interne */, le contrôle passe vers /* Gestionnaires d'exceptions de bloc interne */. Si le gestionnaire d'exceptions approprié n'est pas trouvé, il se propage directement aux /* gestionnaires d'exceptions de bloc externe */ et l'exécution de /* instructions exécutables de bloc externe */ est ignorée.

Lorsqu'ils travaillent avec des blocs PL/SQL imbriqués, les développeurs doivent être prudents lorsqu'ils codent la logique de traitement des exceptions. La propagation des exceptions doit être testée de manière approfondie afin de créer des applications à l'épreuve des défaillances.

Partager ce cours avec tes amis :
Rédigé par ESSADDOUKI Mostafa
ESSADDOUKI
The education of the 21st century opens up opportunities to not merely teach, but to coach, mentor, nurture and inspire.