Exceptions
Transcription
Exceptions
LES BASES DE DONNÉES CHAPITRE 5 PL/SQL - LES EXCEPTIONS [email protected] IUT Dijon – IQ – S2 – 2015/2016 Gestion des erreurs en PL/SQL : les exceptions 2 Pour éviter qu’un programme s’arrête à la première erreur, on prévoit les erreurs potentielles et on associe à chacun de ces cas une exception. Une erreur entraîne automatiquement un débranchement vers la section EXCEPTION Permet d’affecter un traitement approprié aux erreurs survenues lors de l’exécution du bloc PL/SQL [DECLARE] -- déclaration BEGIN -- traitements [EXCEPTION] -- Gestion des erreurs END ; / Gestion des erreurs en PL/SQL : les exceptions 3 2 mécanismes peuvent déclencher une exception Le programmeur désire dérouter son programme dans le bloc des exceptions sous certaines conditions → Exceptions utilisateur Les erreurs levées par Oracle → Exceptions internes BEGIN … IF (…) THEN RAISE EXCEPTION_1 ; … SELECT … INTO … FROM … ; … EXCEPTION WHEN EXCEPTION_1 THEN … WHEN NO_DATA_FOUND THEN … WHEN OTHERS THEN … END; Sortie du bloc après exécution du traitement de l’erreur Gestion des erreurs en PL/SQL : les exceptions 4 Exceptions internes Lorsqu’une erreur Oracle se produit, une exception est levée automatiquement → on parle d’exceptions internes Ces exceptions peuvent être récupérées dans la section EXCEPTION d’un bloc PL/SQL. Les erreurs internes génèrent des exceptions qui ont un numéro. En plus, Oracle a donné un nom aux exceptions qui se produisent le plus souvent → exceptions prédéfinies (e.g. ZERO_DIVIDE, NO_DATA_FOUND) Exemples d’exceptions internes prédéfinies Nom Numéro SQLCODE Explication CURSOR_ALREADY_OPEN ORA-06511 -6511 tentative d'ouvrir un curseur déjà ouvert LOGIN_DENIED ORA-01017 -1017 mauvais login/pwd lors de la connexion NO_DATA_FOUND ORA-01403 +100 Un SELECT…INTO qui ne retourne aucune ligne TOO_MANY_ROWS ORA-01422 -1422 Un SELECT…INTO qui retourne plusieurs lignes ZERO_DIVIDE ORA-01476 -1476 division par zéro DUP_VAL_ON_INDEX ORA-00001 -1 insertion d’une ligne en doublon Gestion des erreurs en PL/SQL : les exceptions 5 Exceptions internes Si l’exception a un nom prédéfini, on peut la récupérer par son nom dans la section EXCEPTION. Exemple DUP_VAL_ON_INDEX DECLARE l_num NUMBER := 123; BEGIN INSERT INTO ETUDIANT VALUES(l_num, 'Michel', 12, 500); EXCEPTION WHEN DUP_VAL_ON_INDEX THEN DBMS_OUTPUT.PUT_LINE(l_num|| ' déjà utilisé'); END ; Exemple ZERO_DIVIDE DECLARE numerateur NUMBER := 10; denominateur NUMBER := 0; ratio NUMBER; BEGIN ratio := numerateur / denominateur; DBMS_OUTPUT.PUT_LINE('ratio = ' || ratio); EXCEPTION WHEN ZERO_DIVIDE THEN DBMS_OUTPUT.PUT_LINE('denominateur doit etre diff de 0'); ratio := 0; END; ETUDIANT NumEtu NomEtu Moy TailleLycee Gestion des erreurs en PL/SQL : les exceptions 6 Exceptions internes Si l’exception a un nom prédéfini, on peut la récupérer par son nom dans la section EXCEPTION Exemple NO_DATA_FOUND et TOO_MANY_ROWS ACCEPT g_NomEtu PROMPT 'Entrer le nom de l’étudiant à afficher : ' DECLARE l_num ETUDIANT.NumEtu%TYPE; BEGIN SELECT NumEtu INTO l_num FROM ETUDIANT WHERE NomEtu = '&g_NomEtu'; DBMS_OUTPUT.PUT_LINE('&g_NomEtu' || 'a l''ID ' || l_num); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('&g_NomEtu' || ' n''existe pas'); WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE('Il existe plusieurs' || ' &g_NomEtu'); END ; ETUDIANT NumEtu NomEtu Moy TailleLycee Gestion des erreurs en PL/SQL : les exceptions 7 Exceptions internes 1. Si l’exception interne n’a pas de nom prédéfini, on peut la récupérer dans la section par défaut (clause OTHERS) ou avec un pragma EXCEPTION_INIT. Utilisation de la section par défaut (clause OTHERS) La clause OTHERS permet de récupérer toutes les exceptions qui n’ont pas de nom. C’est une section optionnelle, qui récupère les exceptions qui n’ont pas été récupérées par les clauses précédentes. L’utilisation de OTHERS garantit que toutes les exceptions seront récupérées. On utilise en général les fonctions SQLCODE et SQLERRM pour avoir des informations sur l’erreur. BEGIN -- do something bad EXCEPTION WHEN <exception_predefinies> THEN -- traitement de l’exception interne prédéfinie WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Erreur Oracle ' || SQLERRM || '(' || SQLCODE || ')'); END ; Gestion des erreurs en PL/SQL : les exceptions 8 Exceptions internes 1. Si l’exception interne n’a pas de nom prédéfini, on peut la récupérer dans la section par défaut (clause OTHERS) ou avec un pragma EXCEPTION_INIT. Utilisation de la section par défaut (clause OTHERS) o On peut aussi utiliser le code pour sélectionner une erreur dans la section par défaut BEGIN DELETE FROM ETUDIANT WHERE NumEtu = 123; EXCEPTION WHEN OTHERS THEN IF SQLCODE = -02292 THEN DBMS_OUTPUT.PUT_LINE('Violation de contrainte d''intégrité. L''étudiant est présent dans la table CANDIDATER.'); ELSE DBMS_OUTPUT.PUT_LINE('Erreur Oracle ' || SQLERRM || '(' || SQLCODE || ')'); END IF; END ; CANDIDATER NumEtu NomIUT Dept Decision ETUDIANT NumEtu NomEtu Moy TailleLycee Gestion des erreurs en PL/SQL : les exceptions 9 Exceptions internes 2. Si l’exception interne n’a pas de nom prédéfini, on peut la récupérer dans la section par défaut (clause OTHERS) ou avec un pragma EXCEPTION_INIT. Utilisation du pragma EXCEPTION_INIT o Un pragma est une directive traitée par le compilateur au moment de la compilation et non pas au moment de l’exécution. o Le pragma EXCEPTION_INIT associe un nom d’exception à un numéro d’erreur Oracle. On pourra ensuite récupérer l’erreur par son nom dans la section EXCEPTION. o Il faut déclarer le pragma dans la section déclarative du bloc PL/SQL PRAGMA EXCEPTION_INIT(<nomException>, <codeErreur>); o <nomException> est une exception précédemment déclarée et <codeErreur> est un nombre négatif. Gestion des erreurs en PL/SQL : les exceptions 10 Exceptions internes 2. Si l’exception interne n’a pas de nom prédéfini, on peut la récupérer dans la section par défaut (clause OTHERS) ou avec un pragma EXCEPTION_INIT. Utilisation du pragma EXCEPTION_INIT Exemple DECLARE e_moyenne_null EXCEPTION; PRAGMA EXCEPTION_INIT(e_moyenne_null, -1400); BEGIN INSERT INTO ETUDIANT(123, ‘Bob’, NULL, 800); EXCEPTION WHEN e_moyenne_null THEN DBMS_OUTPUT.PUT_LINE(‘null interdit pour la moyenne’); END; ETUDIANT NumEtu NomEtu Moy TailleLycee Gestion des erreurs en PL/SQL : les exceptions 11 Exceptions utilisateur Permet de traiter les erreurs applicatives Syntaxe DECLARE … <nomException> EXCEPTION; … BEGIN … IF(<anomalie>) THEN RAISE <nomException>; END IF; … EXCEPTION WHEN <nomException> THEN (<traitement de l’erreur>); [WHEN OTHERS THEN <traitement>] END; Gestion des erreurs en PL/SQL : les exceptions 12 Exceptions utilisateur Exemple : Augmenter la moyenne de 10% d’un étudiant dont l’identifiant est saisi au clavier ACCEPT g_NumEtu PROMPT 'Entrez le numéro de l''étudiant à aider : ' DECLARE l_moy ETUDIANT.Moy%TYPE; l_Nom ETUDIANT.NomEtu%TYPE; e_MoyIndefinie EXCEPTION; BEGIN SELECT NomEtu, Moy INTO l_Nom, l_moy FROM ETUDIANT WHERE NumEtu = &g_NumEtu; IF (l_Moy IS NULL) THEN RAISE e_MoyIndefinie; ELSE UPDATE ETUDIANT SET Moy = l_Moy*1.1 WHERE NumEtu = &g_NumEtu; END IF; DBMS_OUTPUT.PUT_LINE( l_nom || ' a maintenant une moyenne de : ' || l_Moy*1.1); EXCEPTION WHEN e_MoyIndefinie THEN DBMS_OUTPUT.PUT_LINE( l_nom || ' a la moyenne par défaut : 10'); UPDATE ETUDIANT SET Moy = 10 WHERE NumEtu = &g_NumEtu; END; ETUDIANT NumEtu NomEtu Moy TailleLycee Gestion des erreurs en PL/SQL : les exceptions 13 Exceptions utilisateur On peut utiliser l’attribut %NOTFOUND du curseur implicite Exemple : suppression d’un étudiant dont l’identifiant est saisi au clavier ACCEPT g_NumEtu PROMPT 'Entrez le numéro de l''étudiant à supprimer : ' DECLARE e_EtudiantIntrouvable EXCEPTION; BEGIN DELETE FROM ETUDIANT WHERE NumEtu = &g_NumEtu; IF (SQL%NOTFOUND) THEN RAISE e_EtudiantIntrouvable; END IF; DBMS_OUTPUT.PUT_LINE( ' Etudiant &g_NumEtu supprimé'); EXCEPTION WHEN e_EtudiantIntrouvable THEN DBMS_OUTPUT.PUT_LINE( 'L''étudiant &g_NumEtu n''existe pas'); END; ETUDIANT NumEtu NomEtu Moy TailleLycee Gestion des erreurs en PL/SQL : les exceptions 14 Mécanisme générale de propagation d’une erreur Si une erreur dans le sous bloc se déclenche : BEGIN … BEGIN … 1- déclenchement EXCEPTION WHEN … THEN … … WHEN … THEN … END; 2- Recherche de l’exception 3.a - Exception trouvée -> suite du programme … EXCEPTION WHEN … THEN … END; 3.b - Exception non trouvée -> Recherche de l’exception Gestion des erreurs en PL/SQL : les exceptions 15 La procédure RAISE_APPLICATION_ERROR La procédure RAISE_APPLICATION_ERROR permet de définir ses propres messages et code d’erreur. RAISE_APPLICATION_ERROR(<numErreur>, <messageErreur>) <numErreur> : valeur définie par l’utilisateur pour l’exception (entre -20000 et -20999) <messageErreur> : message décrivant l’erreur La procédure RAISE_APPLICATION_ERROR interrompt le programme et retourne le numéro et le message d’erreur qui peuvent être récupéré par le programme appelant (SQLCODE et SQLERRM). 1. Appel du sous programme … monErreur EXCEPTION; PRAGMA EXCEPTION_INIT(monErreur, -20100); BEGIN … -- Appel du sous programme … EXCEPTION WHEN monErreur THEN … END; … BEGIN … RAISE_APPLICATION_ERROR(-20100, ‘oops’); … END; 2. Retour avec SQLCODE(-20100) et SQLERRM(‘oops’);