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’);