SlideShare une entreprise Scribd logo
Dernière version → http://www.irit.fr/~Guillaume.Cabanac/enseignement/m2106/cm5.pdf
M2106 : Programmation et administration
des bases de données
Cours 5/6 – Exceptions et curseurs
Guillaume Cabanac
guillaume.cabanac@univ-tlse3.fr
version du 19 février 2020
Exceptions et curseurs
1 Exceptions
2 Extraction de données
Affectation
Curseur manuel
Curseur semi-automatique
Curseur automatique
3 Exceptions liées à l’extraction de données
M2106 – Cours 5/6 – Exceptions et curseurs 2 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Exceptions et curseurs
1 Exceptions
2 Extraction de données
Affectation
Curseur manuel
Curseur semi-automatique
Curseur automatique
3 Exceptions liées à l’extraction de données
M2106 – Cours 5/6 – Exceptions et curseurs 3 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Exceptions prédéfinies
Définition
Une exception est une erreur logicielle détectée à l’exécution du programme.
Le traitement de l’exception est réalisé via le gestionnaire d’exceptions. Une
exception non traitée remonte la pile des appels de sous-programmes et
cause l’arrêt du programme avec un code d’erreur.
En PL/SQL, chaque bloc begin ... end peut définir un gestionnaire
d’exception dans la section nommée exception.
Quelques exceptions sont prédéfinies :
Exception Code Description
case_not_found ORA-06592 Aucun des choix d’un case sans else ne convient.
invalid_number ORA-01722 Échec de conversion (var)char2 → number
value_error ORA-06502 Erreur d’arithmétique sur un number.
zero_divide ORA-01476 Division par zéro.
. . . . . . . . .
M2106 – Cours 5/6 – Exceptions et curseurs 4 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Rappel du principe de propagation des exceptions
(et qu’il n’existe pas l’entrée OTHERS), l’exception se propage successivement au niveau des
blocs EXCEPTION contenus dans le code appelant (ou englobant), jusqu’à ce qu’une entrée
corresponde (ou l’entrée OTHERS). Si aucun des blocs d’erreurs ne peut traiter l’exception, le
programme principal se termine anormalement en renvoyant une erreur. La figure suivante
illustre ce processus :
Notez que lorsque l’exception se propage à un bloc englobant, les actions exécutables restantes
de ce bloc sont ignorées. Un des avantages de ce mécanisme est de pouvoir gérer des excep-
Figure 7-8 Propagation des exceptions
Scénario de gestion d’exceptions (Soutou & Teste, 2008, p. 331)
M2106 – Cours 5/6 – Exceptions et curseurs 5 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Traitement d’une exception levée par le système
declare
vTmp number ;
vRes number ;
begin
-- il se trouve que vTmp prend la valeur 0...
...
select count (*)/vTmp into vRes from ... ;
...
exception
when zero_divide then
-- interception de l'exception zero_divide ici
when ... then
...
when others then
-- traitement d'une exception non interceptée préalablement
dbms_output.put_line('Erreur inconnue '|| sqlcode ||' : '|| sqlerrm) ;
end ;
/
NB : Dans un bloc exception, deux variables système sont consultables :
sqlcode Le code d’erreur de l’exception prédéfinie ou personnalisée (ORA-XXXXX).
sqlerrm Le message d’erreur correspondant au sqlcode.
M2106 – Cours 5/6 – Exceptions et curseurs 6 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Exceptions personnalisées
Définition
Le programmeur peut définir ses propres exceptions qui seront levées avec
l’instruction raise ou la procédure raise_application_error.
-- Création d'une exception personnalisée et déclenchement avec raise
declare
-- déclaration de l'exception en la nommant
aucunInscrit exception ;
-- association d'un code d'erreur dans [ -20999 ; -20000] à l'exception
pragma exception_init(aucunInscrit , -20001) ;
begin
...
if vNb = 0 then
-- déclenchement de l'exception
raise aucunInscrit ;
end if ;
...
end ;
-- Création et déclenchement d'une exception personnalisée avec raise_application_error
begin
if vNb = 0 then
-- déclenchement de l'exception
raise_application_error (-20001, 'Aucun chien n''est inscrit ') ;
end if ;
end ;
M2106 – Cours 5/6 – Exceptions et curseurs 7 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
raise et raise_application_error
artie II PL/SQL
Déclencheurs
Les déclencheurs (triggers) existent depuis la version 6 d’Oracle. Ils sont compilables depuis
la version 7.3 (auparavant, ils étaient évalués lors de l’exécution). Depuis la version 8, il existe
un nouveau type de déclencheur (INSTEAD OF) qui permet la mise à jour de vues multitables.
La plupart des déclencheurs peuvent être vus comme des programmes résidents associés à un
événement particulier (insertion, modification d’une ou de plusieurs colonnes, suppression)
Figure 7-10 Utilisation de RAISE_APPLICATION_ERROR
Scénario de gestion d’exceptions (Soutou & Teste, 2008, p. 332)
M2106 – Cours 5/6 – Exceptions et curseurs 8 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
raise et raise_application_error
artie II PL/SQL
Déclencheurs
Les déclencheurs (triggers) existent depuis la version 6 d’Oracle. Ils sont compilables depuis
la version 7.3 (auparavant, ils étaient évalués lors de l’exécution). Depuis la version 8, il existe
un nouveau type de déclencheur (INSTEAD OF) qui permet la mise à jour de vues multitables.
La plupart des déclencheurs peuvent être vus comme des programmes résidents associés à un
événement particulier (insertion, modification d’une ou de plusieurs colonnes, suppression)
Figure 7-10 Utilisation de RAISE_APPLICATION_ERROR
Scénario de gestion d’exceptions (Soutou & Teste, 2008, p. 332)
" Attention à bien distinguer un message destiné à l’utilisateur (put_line)
d’une erreur logicielle (raise et raise_application_error).
M2106 – Cours 5/6 – Exceptions et curseurs 8 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
raise et raise_application_error
artie II PL/SQL
Déclencheurs
Les déclencheurs (triggers) existent depuis la version 6 d’Oracle. Ils sont compilables depuis
la version 7.3 (auparavant, ils étaient évalués lors de l’exécution). Depuis la version 8, il existe
un nouveau type de déclencheur (INSTEAD OF) qui permet la mise à jour de vues multitables.
La plupart des déclencheurs peuvent être vus comme des programmes résidents associés à un
événement particulier (insertion, modification d’une ou de plusieurs colonnes, suppression)
Figure 7-10 Utilisation de RAISE_APPLICATION_ERROR
Scénario de gestion d’exceptions (Soutou & Teste, 2008, p. 332)
" Attention à bien distinguer un message destiné à l’utilisateur (put_line)
d’une erreur logicielle (raise et raise_application_error).
AFormellement interdit : signaler une erreur par un message (put_line).
M2106 – Cours 5/6 – Exceptions et curseurs 8 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Exceptions et curseurs
1 Exceptions
2 Extraction de données
Affectation
Curseur manuel
Curseur semi-automatique
Curseur automatique
3 Exceptions liées à l’extraction de données
M2106 – Cours 5/6 – Exceptions et curseurs 9 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Extraction de données
Cadrage
Il existe deux façons d’extraire des données en PL/SQL :
← Affectation
Affectation de valeurs
Extrait une seule ligne
1 syntaxe :
select ... into ... from
 Curseur
Boucle sur un résultat
Extrait plusieurs lignes
3 syntaxes :
1 manuel : open ...
2 semi-autom. : cursor ...
3 automatique : for ...
M2106 – Cours 5/6 – Exceptions et curseurs 10 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Extraction de données
Cadrage
Il existe deux façons d’extraire des données en PL/SQL :
← Affectation
Affectation de valeurs
Extrait une seule ligne
1 syntaxe :
select ... into ... from
 Curseur
Boucle sur un résultat
Extrait plusieurs lignes
3 syntaxes :
1 manuel : open ...
2 semi-autom. : cursor ...
3 automatique : for ...
ANe pas utiliser une affectation pour plusieurs lignes!
Déclenche l’exception too_many_rows à l’exécution. . .
M2106 – Cours 5/6 – Exceptions et curseurs 10 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Extraction de données
Cadrage
Il existe deux façons d’extraire des données en PL/SQL :
← Affectation
Affectation de valeurs
Extrait une seule ligne
1 syntaxe :
select ... into ... from
 Curseur
Boucle sur un résultat
Extrait plusieurs lignes
3 syntaxes :
1 manuel : open ...
2 semi-autom. : cursor ...
3 automatique : for ...
ANe pas utiliser une affectation pour plusieurs lignes!
Déclenche l’exception too_many_rows à l’exécution. . .
 Éviter l’utilisation d’un curseur pour une seule ligne.
M2106 – Cours 5/6 – Exceptions et curseurs 10 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Exceptions et curseurs
1 Exceptions
2 Extraction de données
Affectation
Curseur manuel
Curseur semi-automatique
Curseur automatique
3 Exceptions liées à l’extraction de données
M2106 – Cours 5/6 – Exceptions et curseurs 11 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Affectation
Syntaxes
select * into variableRowType from ... -- var %rowtype
select A[, ..., Z] into var1[, ..., varZ] from ... -- var %type , number ...
declare
vTatouage chien.tatouage %type default 1664 ; -- stocke une valeur
vUnChien chien %rowtype ; -- stocke une ligne
vMaxPrime participation.prime %type ;
vNbSup100 number ;
vDernierConc concours.dateC %type ;
begin
-- Affectation de l'intégralité d'une ligne dans un %rowtype
select * into vUnChien from chien where tatouage = 1664 ; -- rowtype : on récupère nom  sexe
-- Affectation d'une valeur dans un %type
select max(prime) into vMaxPrime from participation where tatouage = 1664 ;
-- Affectation de 2 valeurs
select count (*), max(dateC) into vNbSup100 , vDernierConc
from participation p, concours c
where p.idC = c.idC
and tatouage = 1664 and prime  100 ;
-- Affichage du résultat
dbms_output.put_line(vUnChien.nom||' '||'de sexe '
|| case vUnChien.sexe when 'M' then 'masculin ' else 'féminin' end
|| ' dont le plus gros gain est de '|| vMaxPrime ||' e. Gains supérieurs à'
|| ' 100 e : '|| vNbSup100 ||'. Dernier bon concours : '|| vDernierConc) ;
end ;
/
-- Iench de sexe féminin dont le plus gros gain est de 1234 e. Gains supérieurs à 100 e : 1. 
Dernier bon concours : 30-SEP -13
M2106 – Cours 5/6 – Exceptions et curseurs 12 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Exceptions et curseurs
1 Exceptions
2 Extraction de données
Affectation
Curseur manuel
Curseur semi-automatique
Curseur automatique
3 Exceptions liées à l’extraction de données
M2106 – Cours 5/6 – Exceptions et curseurs 13 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Curseur manuel
Les instructions utilisées
Instruction Description
cursor nomCur is requête ; Déclare le curseur.
open nomCur ; Ouvre le curseur en chargeant les lignes en
mémoire centrale. Aucune exception levée si
la requête ne renvoie aucune ligne.
fetch nomCur into var1, ..., varN ; Avance d’une ligne et affecte les valeurs de la
ligne aux variables.
close nomCur ; Ferme le curseur.
nomCur%isOpen true si le curseur est ouvert, false sinon.
nomCur%notFound true si le dernier fetch n’a pas renvoyé de
ligne (fin de curseur), false sinon.
nomCur%found true si le dernier fetch a renvoyé une ligne,
false sinon.
nomCur%rowCount Nombre de lignes parcourues jusqu’à présent.
M2106 – Cours 5/6 – Exceptions et curseurs 14 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Curseur manuel
Cycle de vie
cursor Déclaration du nom du curseur et de la requête.
open Ouverture du curseur et exécution de la requête.
fetch Récupération des lignes, une par une.
close Fermeture du curseur et libération des ressources.
http://www.dbanotes.com/wp-content/uploads/2011/06/Introduction-to-Oracle-11g-Cursors_img_2-1024x221.jpg
M2106 – Cours 5/6 – Exceptions et curseurs 15 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Curseur manuel
Exemple 1 : curseur manuel
-- Exemple d'utilisation d'un curseur manuel
create procedure hallOfFame as
cursor curTopChiens is select c.tatouage , nom , count(classement) totClass
from chien c, participation p
where c.tatouage = p.tatouage
and classement is not null
group by c.tatouage , nom
order by 3, 2 ;
vTopChien curTopChiens %rowtype ;
begin
dbms_output.put_line('Hall of Fame de la Société Canine ') ;
open curTopChiens ;
-- Récupérer le premier chien
fetch curTopChiens into vTopChien ;
while curTopChiens %found loop
dbms_output.put('Numéro '|| curTopChiens %rowcount ||' : '|| vTopChien.nom) ;
dbms_output.put(' ('|| vTopChien.tatouage ||') avec '|| vTopChien.totClass ||' classement ') ;
if vTopChien.totClass  1 then
dbms_output.put('s') ;
end if ;
dbms_output.new_line ;
-- Passer au chien suivant (NE PAS L'OUBLIER !!!)
fetch curTopChiens into vTopChien ;
end loop ;
close curTopChiens ; -- NE PAS l'OUBLIER !!!
end hallOfFame ;
/
call hallOfFame () ;
-- Hall of Fame de la Société Canine
-- Numéro 1 : Iench (1664) avec 1 classement
-- Numéro 2 : Cerbère (666) avec 7 classements
M2106 – Cours 5/6 – Exceptions et curseurs 16 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Curseur manuel
Exemple 2 : affectation et curseur manuel paramétré
create procedure afficherParticipants(pIdC in concours.idC %type) as
cursor curPart(pcSexe in chien.sexe %type) is select p.tatouage
from participation p, chien c
where p.tatouage = c.tatouage
and idC = pIdC -- paramètre de la procédure
and sexe = pcSexe -- paramètre du curseur
order by classement nulls last , tatouage ;
vUnChien chien.tatouage %type ;
vVille concours.ville %type ;
vDateC concours.dateC %type ;
vDotation number ; -- car la longueur peut dépasser concours.prime %type
begin
select ville , dateC , sum(prime) into vVille , vDateC , vDotation
from concours c, participation p
where c.idC = p.idC
and c.idC = pIdC
group by c.idC , ville , dateC ;
dbms_output.put_line('Concours de '|| vVille ||' du '|| vDateC) ;
dbms_output.put_line('Dotation : '|| vDotation) ;
-- Liste des participants
open curPart('F') ;
-- Récupérer le premier chien
fetch curPart into vUnChien ;
dbms_output.put_line('Classement des chiennes ') ;
while curPart %found loop
dbms_output.put_line(curPart%rowCount ||'. '|| vUnChien) ;
fetch curPart into vUnChien ; -- Passer au chien suivant (NE PAS L'OUBLIER !!!)
end loop ;
close curPart ; -- NE PAS l'OUBLIER !!!
-- Idem pour les chiens mâles : open curPart('M') ; etc
end afficherParticipants ;
/
call afficherParticipants (10) ;
M2106 – Cours 5/6 – Exceptions et curseurs 17 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Exceptions et curseurs
1 Exceptions
2 Extraction de données
Affectation
Curseur manuel
Curseur semi-automatique
Curseur automatique
3 Exceptions liées à l’extraction de données
M2106 – Cours 5/6 – Exceptions et curseurs 18 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Curseur semi-automatique
Exemple 1 : curseur semi-automatique
Le choc des simplifications
variable %rowtype, open, fetch, close → for
NB : ne pas déclarer la variable utilisée dans le for :-)
-- Exemple d'utilisation d'un curseur semi -automatique
create procedure hallOfFame as
cursor curTopChiens is select c.tatouage , nom , count(classement) totClass
from chien c, participation p
where c.tatouage = p.tatouage
and classement is not null
group by c.tatouage , nom
order by 3, 2 ;
begin
dbms_output.put_line('Hall of Fame de la Société Canine ') ;
for vTopChien in curTopChiens loop
dbms_output.put('Numéro '|| curTopChiens %rowcount ||' : '|| vTopChien.nom) ;
dbms_output.put(' ('|| vTopChien.tatouage ||') avec '|| vTopChien.totClass ||' classement ') ;
if vTopChien.totClass  1 then
dbms_output.put('s') ;
end if ;
dbms_output.new_line ;
end loop ;
end hallOfFame ;
/
call hallOfFame () ;
-- Hall of Fame de la Société Canine
-- Numéro 1 : Iench (1664) avec 1 classement
-- Numéro 2 : Cerbère (666) avec 7 classements
M2106 – Cours 5/6 – Exceptions et curseurs 19 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Curseur semi-automatique
Exemple 2 : affectation et curseur semi-automatique paramétré
create procedure afficherParticipants(pIdC in concours.idC %type) as
-- Définition d'un curseur paramétré avec Sexe
cursor curPart(pcSexe in chien.sexe %type) is select p.tatouage
from participation p, chien c
where p.tatouage = c.tatouage
and idC = pIdC -- paramètre de la procédure
and sexe = pcSexe -- paramètre du curseur
order by classement nulls last , tatouage ;
vVille concours.ville %type ;
vDateC concours.dateC %type ;
vDotation number ; -- car la longueur peut dépasser concours.prime %type
begin
select ville , dateC , sum(prime) into vVille , vDateC , vDotation
from concours c, participation p
where c.idC = p.idC
and c.idC = pIdC
group by c.idC , ville , dateC ;
dbms_output.put_line('Concours de '|| vVille ||' du '|| vDateC) ;
dbms_output.put_line('Dotation : '|| vDotation) ;
-- Liste des participants
dbms_output.put_line('Classement des chiennes ') ;
for vUneChienne in curPart('F') loop
dbms_output.put_line(curPart%rowCount ||'. '|| vUneChienne.tatouage) ;
end loop ;
dbms_output.put_line('Classement des chiens ') ;
for vUnChien in curPart('M') loop
dbms_output.put_line(curPart%rowCount ||'. '|| vUnChien.tatouage) ;
end loop ;
end afficherParticipants ;
/
call afficherParticipants (10) ;
M2106 – Cours 5/6 – Exceptions et curseurs 20 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Exceptions et curseurs
1 Exceptions
2 Extraction de données
Affectation
Curseur manuel
Curseur semi-automatique
Curseur automatique
3 Exceptions liées à l’extraction de données
M2106 – Cours 5/6 – Exceptions et curseurs 21 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Curseur automatique
Exemple 1 : curseur automatique
Le choc des simplifications 2 : le retour
cursor → requête dans le for.
-- Exemple d'utilisation d'un curseur automatique
create procedure hallOfFame as
vI number := 0 ; -- Il n'y a plus de déclaration de curseur ici
begin
dbms_output.put_line('Hall of Fame de la Société Canine ') ;
for vTopChien in (select c.tatouage , nom , count(classement) totClass
from chien c, participation p
where c.tatouage = p.tatouage
and classement is not null
group by c.tatouage , nom
order by 3, 2)
loop
vI := vI + 1 ; -- remplace %rowcount car on n'y a plus accès
dbms_output.put('Numéro '||vI||' : '|| vTopChien.nom) ;
dbms_output.put(' ('|| vTopChien.tatouage ||') avec '|| vTopChien.totClass ||' classement ') ;
if vTopChien.totClass  1 then
dbms_output.put('s') ;
end if ;
dbms_output.new_line ;
end loop ;
end hallOfFame ;
/
call hallOfFame () ;
-- Hall of Fame de la Société Canine
-- Numéro 1 : Iench (1664) avec 1 classement
-- Numéro 2 : Cerbère (666) avec 7 classements
M2106 – Cours 5/6 – Exceptions et curseurs 22 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Curseur automatique
Exemple 2 : affectation et curseur automatique paramétré par synchronisation
Le paramétrage du curseur se fait désormais via la synchronisation sur pIdC.
create procedure afficherParticipants(pIdC in concours.idC %type) as
vVille concours.ville %type ;
vDateC concours.dateC %type ;
vDotation number ; -- car la longueur peut dépasser concours.prime %type
vI number := 0 ;
begin
select ville , dateC , sum(prime) into vVille , vDateC , vDotation
from concours c, participation p
where c.idC = p.idC
and c.idC = pIdC
group by c.idC , ville , dateC ;
dbms_output.put_line('Concours de '|| vVille ||' du '|| vDateC) ;
dbms_output.put_line('Dotation : '|| vDotation) ;
-- Liste des participants
dbms_output.put_line('Classement des chiennes ') ;
for vUneChienne in (select p.tatouage
from participation p, chien c
where p.tatouage = c.tatouage
and idC = pIdC -- paramètre de la procédure
and sexe = 'F' -- il n'y a plus de paramètre passé au curseur
order by classement nulls last , tatouage)
loop
vI := vI + 1 ; -- remplace %rowCount car on n'y a plus accès
dbms_output.put_line(vI||'. '|| vUneChienne.tatouage) ;
end loop ;
dbms_output.put_line('Classement des chiens ') ;
vI := 0 ;
for vUnChien in (select ... and sexe = 'M'... -- gros inconvénient : copier/coller !!!
end afficherParticipants ;
/
call afficherParticipants (10) ;
M2106 – Cours 5/6 – Exceptions et curseurs 23 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Bilan sur les 3 types de curseurs
Curseur manuel
ACode long
ABugs potentiels dus aux divers oublis quasi-inévitables
M2106 – Cours 5/6 – Exceptions et curseurs 24 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Bilan sur les 3 types de curseurs
Curseur manuel
ACode long
ABugs potentiels dus aux divers oublis quasi-inévitables
Curseur semi-automatique
© 4 instructions en moins!
 La requête est parfois « loin » (déclaration) de son utilisation (boucle)
M2106 – Cours 5/6 – Exceptions et curseurs 24 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Bilan sur les 3 types de curseurs
Curseur manuel
ACode long
ABugs potentiels dus aux divers oublis quasi-inévitables
Curseur semi-automatique
© 4 instructions en moins!
 La requête est parfois « loin » (déclaration) de son utilisation (boucle)
Curseur automatique
© Encore 1 instruction en moins!
© La requête et son utilisation sont couplées dans la boucle
 Pas de réutilisation de requête, contrairement au curseur déclaré
M2106 – Cours 5/6 – Exceptions et curseurs 24 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Conseil d’un ami qui vous veut du bien
ANe réinventez pas la roue!
« Il n’y a rien de plus inutile que de faire avec efficacité
quelque chose qui ne doit pas être fait du tout. » — Peter Drucker
http://www.videouniversity.com/files/reinventing_wheel.jpg
M2106 – Cours 5/6 – Exceptions et curseurs 25 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Conseil d’un ami qui vous veut du bien
ANe réinventez pas la roue!
« Il n’y a rien de plus inutile que de faire avec efficacité
quelque chose qui ne doit pas être fait du tout. » — Peter Drucker
http://www.videouniversity.com/files/reinventing_wheel.jpg
Ne recodez pas avec des boucles les sélections, les jointures, les
regroupements. . . Exploitez la puissance de SQL!
M2106 – Cours 5/6 – Exceptions et curseurs 25 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Sometimes less is more!
-- À NE PAS FAIRE : réinventer la roue !!! Ça fonctionne mais c'est sous -optimal , peu maintenable
create function gainsMalesToulousainsKO return number as
pVille adherent.ville %type ;
vTotalGains number := 0 ;
begin
for ch in (select * from chien) loop
if ch.sexe = 'M' then
-- vérifie qu 'il est à Toulouse
select ville into pVille from adherent where idA = ch.idA ;
if pVille = 'Toulouse ' then
for pa in (select * from participation) loop
if ch.tatouage = pa.tatouage then
vTotalGains := vTotalGains + pa.prime ; -- Ce code est une HORREUR !
end if ; -- Ne faites ** surtout pas** ça
end loop ;
end if ;
end if ;
end loop ;
return vTotalGains ;
end gainsMalesToulousainsKO ;
/
M2106 – Cours 5/6 – Exceptions et curseurs 26 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Sometimes less is more!
-- À NE PAS FAIRE : réinventer la roue !!! Ça fonctionne mais c'est sous -optimal , peu maintenable
create function gainsMalesToulousainsKO return number as
pVille adherent.ville %type ;
vTotalGains number := 0 ;
begin
for ch in (select * from chien) loop
if ch.sexe = 'M' then
-- vérifie qu 'il est à Toulouse
select ville into pVille from adherent where idA = ch.idA ;
if pVille = 'Toulouse ' then
for pa in (select * from participation) loop
if ch.tatouage = pa.tatouage then
vTotalGains := vTotalGains + pa.prime ; -- Ce code est une HORREUR !
end if ; -- Ne faites ** surtout pas** ça
end loop ;
end if ;
end if ;
end loop ;
return vTotalGains ;
end gainsMalesToulousainsKO ;
/
-- Exploitation judicieuse de SQL , encapulation dans une fonction
create function gainsMalesToulousainsOK return number as
vTotalGains number ;
begin
-- calcul du résultat en pur SQL
select nvl(sum(prime), 0) into vTotalGains
from chien ch, participation pa, adherent ad
where ch.tatouage = pa.tatouage
and ch.idA = ad.idA
and ville = 'Toulouse '
and sexe = 'M' ;
return vTotalGains ;
end gainsMalesToulousainsOK ;
/
M2106 – Cours 5/6 – Exceptions et curseurs 26 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Exceptions et curseurs
1 Exceptions
2 Extraction de données
Affectation
Curseur manuel
Curseur semi-automatique
Curseur automatique
3 Exceptions liées à l’extraction de données
M2106 – Cours 5/6 – Exceptions et curseurs 27 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Exceptions prédéfinies liées à l’extraction de données
Parmi les exceptions prédéfinies, on trouve également :
Exception Code Description
dup_val_on_index ORA-00001 Violation de contrainte unique : UN ou PK
no_data_found ORA-01403 Requête ne retournant aucun résultat
rowtype_mismatch ORA-06504 Incompatibilité de types lors d’une affectation
too_many_rows ORA-01422 Requête retournant plusieurs lignes (select into A)
ORA-01400 Tentative d’insertion d’une valeur null non autorisée
ORA-01407 Tentative de màj d’une valeur null non autorisée
ORA-02290 Transgression d’une contrainte check
ORA-02291 Tentative d’insertion d’une valeur de FK inexistante
ORA-02292 Tentative de suppression d’une valeur de FK pointée
M2106 – Cours 5/6 – Exceptions et curseurs 28 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Exceptions prédéfinies liées à l’extraction de données
Parmi les exceptions prédéfinies, on trouve également :
Exception Code Description
dup_val_on_index ORA-00001 Violation de contrainte unique : UN ou PK
no_data_found ORA-01403 Requête ne retournant aucun résultat
rowtype_mismatch ORA-06504 Incompatibilité de types lors d’une affectation
too_many_rows ORA-01422 Requête retournant plusieurs lignes (select into A)
ORA-01400 Tentative d’insertion d’une valeur null non autorisée
ORA-01407 Tentative de màj d’une valeur null non autorisée
ORA-02290 Transgression d’une contrainte check
ORA-02291 Tentative d’insertion d’une valeur de FK inexistante
ORA-02292 Tentative de suppression d’une valeur de FK pointée
 Certaines erreurs ne sont pas associées à des exceptions prédéfinies.
On est donc forcé de les intercepter :
soit en déclarant une exception et en la liant au code d’erreur associé (pragma),
soit dans le cas others du bloc exception (en testant pour être sûr de bien avoir été
déclenché par l’exception attendue).
M2106 – Cours 5/6 – Exceptions et curseurs 28 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Exceptions prédéfinies liées à l’extraction de données : exemple
create procedure ajouterParticipation(pTatouage in participation.tatouage %type ,
pConcours in participation.idC %type ,
pClass in participation.classement %type ,
pPrime in participation.prime %type) as
fkInexistante exception ;
pragma exception_init(fkInexistante , -2291) ; -- associe un nom à cette exception prédéfinie
-- ORA -02291: integrity constraint FK... violated - parent key not found
vTestException number ;
begin
insert into participation values(pTatouage , pConcours , pClass , pPrime) ;
exception
when fkInexistante then -- PB de FK... oui , mais laquelle ?
if sqlerrm like '%FK_PARTICIPATION_TATOUAGE%' escape '' then
raise_application_error (-20001, 'Erreur : tatouage '|| pTatouage ||' inexistant.') ;
elsif sqlerrm like '%FK_PARTICIPATION_IDC%' escape '' then
raise_application_error (-20002, 'Erreur : concours '|| pConcours ||' inexistant.') ;
else
raise_application_error (-20003, 'Erreur fatale (FK transgressée inconnue).') ;
end if ;
when dup_val_on_index then
raise_application_error (-20004, 'Part. au conc. '|| pConcours ||' déjà notée pour '|| pTatouage) ;
end ajouterParticipation ;
/
call ajouterParticipation (99, 10, 2, 512) ;
-- SQL Error: ORA -20001: Erreur : tatouage 99 inexistant.
call ajouterParticipation (51, 99, 2, 512) ;
-- SQL Error: ORA -20002: Erreur : concours 99 inexistant.
call ajouterParticipation (666, 10, 2, 512) ;
-- SQL Error: ORA -20004: Part. au conc. 10 déjà notée pour 666
M2106 – Cours 5/6 – Exceptions et curseurs 29 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Compléments
322 © Éditions Eyrolles
Plusieurs erreurs
Le tableau suivant décrit une procédure qui gère deux erreurs : aucun pilote n’est associé à la
compagnie de code passé en paramètre (NO_DATA_FOUND) et plusieurs pilotes le sont (TOO_
MANY_ROWS). Le programme se termine correctement si la requête retourne une seule ligne
(cas de la compagnie de code 'CAST').
La trace de l’exécution de cette procédure est la suivante :
SQL EXECUTE procException1('AF');
Tableau 7-20 Deux exceptions traitées
Code PL/SQL Commentaires
CREATE PROCEDURE procException1 (p_comp IN VARCHAR2) IS
var1 Pilote.nom%TYPE;
BEGIN
SELECT nom INTO var1 FROM Pilote
WHERE comp = p_comp;
DBMS_OUTPUT.PUT_LINE('Le pilote de la compagnie '
|| p_comp || ' est ' || var1);
Requête déclenchant
potentiellement deux
exceptions prévues.
DBMS_OUTPUT.PUT_LINE('La compagnie ' ||
p_comp || ' n''a aucun pilote!');
Aucun résultat renvoyé.
DBMS_OUTPUT.PUT_LINE('La compagnie ' ||
p_comp || ' a plusieurs pilotes!');
END;
Plusieurs résultats
renvoyés.
EXCEPTION
WHEN NO_DATA_FOUND THEN
WHEN TOO_MANY_ROWS THEN
Scénario de gestion d’exceptions (Soutou  Teste, 2008, p. 322)
M2106 – Cours 5/6 – Exceptions et curseurs 30 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Compléments
Partie II PL/SQL
Imbrication de blocs d’erreurs
Le tableau suivant décrit une procédure qui inclut un bloc d’exceptions imbriqué au code prin-
Tableau 7-21 Une exception traitée pour deux instructions
Code PL/SQL Commentaires
CREATE PROCEDURE procException2
(p_brevet IN VARCHAR2, p_heures IN NUMBER) IS
var1 Pilote.nom%TYPE;
requete NUMBER := 1;
BEGIN
SELECT nom INTO var1 FROM Pilote
WHERE brevet = p_brevet;
DBMS_OUTPUT.PUT_LINE('Le pilote de ' ||
p_brevet || ' est ' || var1);
Requêtes déclenchant
potentiellement une
exception prévue.
requete := 2;
SELECT nom INTO var1 FROM Pilote
WHERE nbHVol = p_heures;
DBMS_OUTPUT.PUT_LINE('Le pilote ayant ' ||
p_heures || ' heures est ' || var1);
IF requete = 1 THEN
DBMS_OUTPUT.PUT_LINE('Pas de pilote de brevet : '
|| p_brevet);
ELSE
DBMS_OUTPUT.PUT_LINE('Pas de pilote ayant ce
nombre d''heures de vol : ' || p_heures);
END IF;
DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' ||
SQLERRM || ' (' || SQLCODE || ')');
END;
Aucun résultat.
Traitement pour savoir
quelle requête a déclenché
l’exception.
Autre erreur.
EXCEPTION
WHEN NO_DATA_FOUND THEN
WHEN OTHERS THEN
SOUTOU Livre Page 324 Vendredi, 25. janvier 2008 1:08 13
Scénario de gestion d’exceptions (Soutou  Teste, 2008, p. 324)
M2106 – Cours 5/6 – Exceptions et curseurs 31 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Compléments
chapitre n° 7 Programmation avancée
Exception utilisateur
Il est possible de définir ses propres exceptions. Cela pour bénéficier des blocs de traitements
d’erreurs et aborder une erreur applicative comme une erreur renvoyée par la base. Cela
Tableau 7-22 Bloc d’exceptions imbriqué
Code PL/SQL Commentaires
CREATE PROCEDURE procException3
(p_brevet IN VARCHAR2, p_heures IN NUMBER) IS
var1 Pilote.nom%TYPE;
BEGIN
BEGIN
SELECT nom INTO var1 FROM Pilote
WHERE brevet = p_brevet;
DBMS_OUTPUT.PUT_LINE('Le pilote de ' || p_brevet
|| ' est ' || var1);
DBMS_OUTPUT.PUT_LINE('Pas de pilote de brevet : '
|| p_brevet);
DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' ||
SQLERRM || ' (' || SQLCODE || ')');
END;
Bloc imbriqué.
Gestion des exceptions
de la première requête.
SELECT nom INTO var1 FROM Pilote
WHERE nbHVol = p_heures ;
DBMS_OUTPUT.PUT_LINE('Le pilote ayant ' || p_heures ||
' heures est ' || var1);
Suite du traitement.
DBMS_OUTPUT.PUT_LINE('Pas de pilote ayant ce nombre
d''heures de vol : ' || p_heures);
DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' ||
SQLERRM || ' (' || SQLCODE || ')');
END;
Gestion des exceptions
de la deuxième requête.
EXCEPTION
WHEN NO_DATA_FOUND THEN
WHEN OTHERS THEN
EXCEPTION
WHEN NO_DATA_FOUND THEN
WHEN OTHERS THEN
SOUTOU Livre Page 325 Vendredi, 25. janvier 2008 1:08 13
Scénario de gestion d’exceptions (Soutou  Teste, 2008, p. 325)
M2106 – Cours 5/6 – Exceptions et curseurs 32 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Compléments
326 © Éditions Eyrolles
Dans notre exemple, programmons les deux exceptions suivantes :
● erreur_piloteTropJeune qui va interdire l’insertion des pilotes ayant moins de
200 heures de vol ;
● erreur_piloteTropExpérimenté qui va interdire l’insertion des pilotes ayant plus
de 20 000 heures de vol.
Le tableau suivant décrit cette procédure qui intercepte ces deux erreurs applicatives :
La trace de l’exécution de cette procédure où l’on passe des valeurs en paramètres qui déclen-
chent les deux exceptions est la suivante :
Tableau 7-23 Exceptions utilisateur
Code PL/SQL Commentaires
CREATE PROCEDURE saisiePilote
(p_brevet IN VARCHAR2,p_nom IN VARCHAR2,
p_nbHVol IN NUMBER, p_comp IN VARCHAR2) IS
Déclaration de l’exception.
BEGIN
INSERT INTO Pilote (brevet,nom,nbHVol,comp)
VALUES (p_brevet,p_nom,p_nbHVol,p_comp);
IF p_nbHVol  200 THEN
END IF;
IF p_nbHVol  20000 THEN
END IF;
COMMIT;
Corps du traitement
(validation).
EXCEPTION
ROLLBACK;
DBMS_OUTPUT.PUT_LINE ('Désolé, le pilote manque
d''expérience');
ROLLBACK;
DBMS_OUTPUT.PUT_LINE ('Désolé, le pilote a
trop d''expérience');
WHEN OTHERS THEN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' || SQLERRM
|| '(' || SQLCODE || ')');
END;
Gestion de l’exception.
Gestion des autres
exceptions.
erreur_piloteTropJeune EXCEPTION;
erreur_piloteTropExpérimenté EXCEPTION;
RAISE erreur_piloteTropJeune;
RAISE erreur_piloteTropExpérimenté;
WHEN erreur_piloteTropJeune THEN
WHEN erreur_piloteTropExpérimenté THEN
Scénario de gestion d’exceptions (Soutou  Teste, 2008, p. 326)
M2106 – Cours 5/6 – Exceptions et curseurs 33 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Compléments
lève pas l’exception NO_DATA_FOUND pour les instructions UPDATE et DELETE. Ce qui est en
théorie valable (aucune action sur la base peut ne pas être considérée comme une erreur), en
pratique il est utile de connaître le code retour de l’instruction de mise à jour.
Considérons à nouveau la procédure détruitCompagnie en prenant en compte l’erreur
applicative erreur_compagnieInexistante qui intercepte une suppression non réalisée.
Le test du curseur implicite de cette instruction déclenche l’exception utilisateur associée.
L’exécution de cette procédure où l’on passe un code compagnie inexistant fait maintenant
dérouler la section des exceptions.
Tableau 7-24 Utilisation du curseur implicite
Code PL/SQL Commentaires
CREATE OR REPLACE PROCEDURE détruitCompagnie
(p_comp IN VARCHAR2) IS Déclaration des exceptions.
BEGIN
DELETE FROM Compagnie WHERE comp = p_comp;
IF THEN
END IF;
COMMIT;
DBMS_OUTPUT.PUT_LINE('Compagnie '||p_comp|| ' détruite.');
Corps du traitement
(validation).
EXCEPTION
THEN
DBMS_OUTPUT.PUT_LINE ('Désolé, il reste encore un
pilote à la compagnie ' || p_comp);
THEN
DBMS_OUTPUT.PUT_LINE ('La compagnie ' || p_comp ||
' n''existe pas dans la base!');
THEN
DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' || SQLERRM ||
'(' || SQLCODE || ')');
END;
Gestion des exceptions.
Gestion des autres
exceptions.
erreur_ilResteUnPilote EXCEPTION;
PRAGMA EXCEPTION_INIT(erreur_ilResteUnPilote , -2292);
erreur_compagnieInexistante EXCEPTION;
SQL%NOTFOUND
RAISE erreur_compagnieInexistante;
WHEN erreur_ilResteUnPilote
WHEN erreur_compagnieInexistante
WHEN OTHERS
Scénario de gestion d’exceptions (Soutou  Teste, 2008, p. 327)
M2106 – Cours 5/6 – Exceptions et curseurs 34 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Le mécanisme de gestion des exceptions
Compléments
Le tableau suivant décrit la procédure détruitCompagnie qui intercepte l’erreur ORA-
02292: enregistrement fils existant. Il s’agit de contrôler le programme si la
compagnie à détruire possède encore des pilotes référencés dans la table Pilote.
La trace de l’exécution de cette procédure est la suivante. Notez que si on applique cette procé-
dure à une compagnie inexistante, le programme se termine normalement sans passer dans la
section des exceptions.
Tableau 7-25 Exception interne non prédéfinie
Code PL/SQL Commentaires
CREATE PROCEDURE détruitCompagnie(p_comp IN VARCHAR2) IS Déclaration de l’exception.
BEGIN
DELETE FROM Compagnie WHERE comp = p_comp;
COMMIT;
DBMS_OUTPUT.PUT_LINE ('Compagnie ' || p_comp ||
' détruite.');
Corps du traitement
(validation).
DBMS_OUTPUT.PUT_LINE ('Désolé, il reste encore un
pilote à la compagnie ' || p_comp);
DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' || SQLERRM
|| '(' || SQLCODE || ')');
END;
Gestion de l’exception.
Gestion des autres
exceptions.
erreur_ilResteUnPilote EXCEPTION;
PRAGMA EXCEPTION_INIT(erreur_ilResteUnPilote , -2292);
EXCEPTION
WHEN erreur_ilResteUnPilote THEN
WHEN OTHERS THEN
Scénario de gestion d’exceptions (Soutou  Teste, 2008, p. 330)
M2106 – Cours 5/6 – Exceptions et curseurs 35 / 36
Exceptions Extraction de données Exceptions liées à l’extraction de données
Sources
Les illustrations sont reproduites à partir du document suivant :
SQL pour Oracle – 3e édition, C. Soutou, Eyrolles (2008)
M2106 – Cours 5/6 – Exceptions et curseurs 36 / 36

Contenu connexe

PDF
Cours08 exceptions
PPT
plsql-8.ppt
PPT
Les08.ppt
PDF
CMO3_PL_SQL.pdf FORMATION BD CYCLE INGGENIEUR
PPTX
trigger.pptx
PDF
trigger.pdf
PDF
PLSQL-Complements-4p.pdf
PDF
cours Plsql _ abdelkhalek benhoumine
Cours08 exceptions
plsql-8.ppt
Les08.ppt
CMO3_PL_SQL.pdf FORMATION BD CYCLE INGGENIEUR
trigger.pptx
trigger.pdf
PLSQL-Complements-4p.pdf
cours Plsql _ abdelkhalek benhoumine

Plus de LuneSabsPericolo1 (20)

PDF
Formulaire Congés ADAMA SABALYJDJFKFKLE.pdf
PPTX
Passation_Support_BILLPAY_ET_WALLET 1 (1).pptx
PDF
Formulaire CongésSKDKELLFEKSKAKDKZDF.pdf
DOCX
CR_SUPPORT_IGOR_TZESDJDJDKS20092024.docx
PDF
cours-laravel-lpti-dar324-janTEDTF-24.pdf
PDF
Web-DutDst-PHP-DSTTFORMATINCDECKDKD?E.pdf
PDF
GUIDE-POWERPOINT-FORMATION COMMISSION.pdf
PPTX
revue_paramTERFJKCKLD?ZLDF?SFJF_DAT.pptx
PPTX
ORACLETEDORACLEDEVELOPPEMENTWEBCJEK.pptx
PPTX
ORACLE2ANNEEIIIBSECOLESSUPERTEEKFLRLV.pptx
PPTX
TRIGGERENVEMFFJJDI3KFTEDHFJFFFFFFFF.pptx
PDF
CoursAdmin.pdf BASE DE DONNEES ORACLES TES
PDF
alphorm.com - support de la Formation Oracle Database 11g DBA 1 (1Z0-052)_SS.pdf
PDF
cours3-FR_poly.pdf formation POO en javascript
PDF
2-Elements de bases(variables-Opérateurs-Entrée-Sortie 2021.pdf
PDF
1- Introduction-2022.pdf formation python
PDF
Cours_ASP_NET_MVC_Premiers_pas.pdfTESTPAR
PPTX
ORACLE.pptx fromation genie logiciel accele
PDF
cours2_poly_4_240924_090436.pdf TEST_CER
PPTX
GENIE LOGICIEL ENSUP AFRIQUE 2024 ADAMA SABALY.pptx
Formulaire Congés ADAMA SABALYJDJFKFKLE.pdf
Passation_Support_BILLPAY_ET_WALLET 1 (1).pptx
Formulaire CongésSKDKELLFEKSKAKDKZDF.pdf
CR_SUPPORT_IGOR_TZESDJDJDKS20092024.docx
cours-laravel-lpti-dar324-janTEDTF-24.pdf
Web-DutDst-PHP-DSTTFORMATINCDECKDKD?E.pdf
GUIDE-POWERPOINT-FORMATION COMMISSION.pdf
revue_paramTERFJKCKLD?ZLDF?SFJF_DAT.pptx
ORACLETEDORACLEDEVELOPPEMENTWEBCJEK.pptx
ORACLE2ANNEEIIIBSECOLESSUPERTEEKFLRLV.pptx
TRIGGERENVEMFFJJDI3KFTEDHFJFFFFFFFF.pptx
CoursAdmin.pdf BASE DE DONNEES ORACLES TES
alphorm.com - support de la Formation Oracle Database 11g DBA 1 (1Z0-052)_SS.pdf
cours3-FR_poly.pdf formation POO en javascript
2-Elements de bases(variables-Opérateurs-Entrée-Sortie 2021.pdf
1- Introduction-2022.pdf formation python
Cours_ASP_NET_MVC_Premiers_pas.pdfTESTPAR
ORACLE.pptx fromation genie logiciel accele
cours2_poly_4_240924_090436.pdf TEST_CER
GENIE LOGICIEL ENSUP AFRIQUE 2024 ADAMA SABALY.pptx
Publicité

Dernier (11)

PDF
Proposition de contenu pouvant résoudre les problèmes détectés à partir des é...
PPT
Présentation de l’Analyse et Concepti SI
PDF
Regles sur la gestion de l’Eclairage public
PDF
Arouna Toure - Senior Ingénieur Logiciel Et Chef De Produit
PDF
ENSEIGNEMENT/APPRENTISSAGE ET COMPETENCE
PDF
UX DESIGN presentation canva plan et slides
PPTX
mon_expose_de_geophysique_dispositif_de_schlumberger.pptx
PPT
Icc courant de court circuit explication
PPTX
mon_expose_de_geophysique_disposotif_de_wener.pptx
PPTX
Chapitre7-java------------------ Exception.pptx
PDF
famille ................................
Proposition de contenu pouvant résoudre les problèmes détectés à partir des é...
Présentation de l’Analyse et Concepti SI
Regles sur la gestion de l’Eclairage public
Arouna Toure - Senior Ingénieur Logiciel Et Chef De Produit
ENSEIGNEMENT/APPRENTISSAGE ET COMPETENCE
UX DESIGN presentation canva plan et slides
mon_expose_de_geophysique_dispositif_de_schlumberger.pptx
Icc courant de court circuit explication
mon_expose_de_geophysique_disposotif_de_wener.pptx
Chapitre7-java------------------ Exception.pptx
famille ................................
Publicité

oracle les exceptions.pdf formation BASE DE

  • 1. Dernière version → http://www.irit.fr/~Guillaume.Cabanac/enseignement/m2106/cm5.pdf M2106 : Programmation et administration des bases de données Cours 5/6 – Exceptions et curseurs Guillaume Cabanac guillaume.cabanac@univ-tlse3.fr version du 19 février 2020
  • 2. Exceptions et curseurs 1 Exceptions 2 Extraction de données Affectation Curseur manuel Curseur semi-automatique Curseur automatique 3 Exceptions liées à l’extraction de données M2106 – Cours 5/6 – Exceptions et curseurs 2 / 36
  • 3. Exceptions Extraction de données Exceptions liées à l’extraction de données Exceptions et curseurs 1 Exceptions 2 Extraction de données Affectation Curseur manuel Curseur semi-automatique Curseur automatique 3 Exceptions liées à l’extraction de données M2106 – Cours 5/6 – Exceptions et curseurs 3 / 36
  • 4. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Exceptions prédéfinies Définition Une exception est une erreur logicielle détectée à l’exécution du programme. Le traitement de l’exception est réalisé via le gestionnaire d’exceptions. Une exception non traitée remonte la pile des appels de sous-programmes et cause l’arrêt du programme avec un code d’erreur. En PL/SQL, chaque bloc begin ... end peut définir un gestionnaire d’exception dans la section nommée exception. Quelques exceptions sont prédéfinies : Exception Code Description case_not_found ORA-06592 Aucun des choix d’un case sans else ne convient. invalid_number ORA-01722 Échec de conversion (var)char2 → number value_error ORA-06502 Erreur d’arithmétique sur un number. zero_divide ORA-01476 Division par zéro. . . . . . . . . . M2106 – Cours 5/6 – Exceptions et curseurs 4 / 36
  • 5. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Rappel du principe de propagation des exceptions (et qu’il n’existe pas l’entrée OTHERS), l’exception se propage successivement au niveau des blocs EXCEPTION contenus dans le code appelant (ou englobant), jusqu’à ce qu’une entrée corresponde (ou l’entrée OTHERS). Si aucun des blocs d’erreurs ne peut traiter l’exception, le programme principal se termine anormalement en renvoyant une erreur. La figure suivante illustre ce processus : Notez que lorsque l’exception se propage à un bloc englobant, les actions exécutables restantes de ce bloc sont ignorées. Un des avantages de ce mécanisme est de pouvoir gérer des excep- Figure 7-8 Propagation des exceptions Scénario de gestion d’exceptions (Soutou & Teste, 2008, p. 331) M2106 – Cours 5/6 – Exceptions et curseurs 5 / 36
  • 6. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Traitement d’une exception levée par le système declare vTmp number ; vRes number ; begin -- il se trouve que vTmp prend la valeur 0... ... select count (*)/vTmp into vRes from ... ; ... exception when zero_divide then -- interception de l'exception zero_divide ici when ... then ... when others then -- traitement d'une exception non interceptée préalablement dbms_output.put_line('Erreur inconnue '|| sqlcode ||' : '|| sqlerrm) ; end ; / NB : Dans un bloc exception, deux variables système sont consultables : sqlcode Le code d’erreur de l’exception prédéfinie ou personnalisée (ORA-XXXXX). sqlerrm Le message d’erreur correspondant au sqlcode. M2106 – Cours 5/6 – Exceptions et curseurs 6 / 36
  • 7. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Exceptions personnalisées Définition Le programmeur peut définir ses propres exceptions qui seront levées avec l’instruction raise ou la procédure raise_application_error. -- Création d'une exception personnalisée et déclenchement avec raise declare -- déclaration de l'exception en la nommant aucunInscrit exception ; -- association d'un code d'erreur dans [ -20999 ; -20000] à l'exception pragma exception_init(aucunInscrit , -20001) ; begin ... if vNb = 0 then -- déclenchement de l'exception raise aucunInscrit ; end if ; ... end ; -- Création et déclenchement d'une exception personnalisée avec raise_application_error begin if vNb = 0 then -- déclenchement de l'exception raise_application_error (-20001, 'Aucun chien n''est inscrit ') ; end if ; end ; M2106 – Cours 5/6 – Exceptions et curseurs 7 / 36
  • 8. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions raise et raise_application_error artie II PL/SQL Déclencheurs Les déclencheurs (triggers) existent depuis la version 6 d’Oracle. Ils sont compilables depuis la version 7.3 (auparavant, ils étaient évalués lors de l’exécution). Depuis la version 8, il existe un nouveau type de déclencheur (INSTEAD OF) qui permet la mise à jour de vues multitables. La plupart des déclencheurs peuvent être vus comme des programmes résidents associés à un événement particulier (insertion, modification d’une ou de plusieurs colonnes, suppression) Figure 7-10 Utilisation de RAISE_APPLICATION_ERROR Scénario de gestion d’exceptions (Soutou & Teste, 2008, p. 332) M2106 – Cours 5/6 – Exceptions et curseurs 8 / 36
  • 9. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions raise et raise_application_error artie II PL/SQL Déclencheurs Les déclencheurs (triggers) existent depuis la version 6 d’Oracle. Ils sont compilables depuis la version 7.3 (auparavant, ils étaient évalués lors de l’exécution). Depuis la version 8, il existe un nouveau type de déclencheur (INSTEAD OF) qui permet la mise à jour de vues multitables. La plupart des déclencheurs peuvent être vus comme des programmes résidents associés à un événement particulier (insertion, modification d’une ou de plusieurs colonnes, suppression) Figure 7-10 Utilisation de RAISE_APPLICATION_ERROR Scénario de gestion d’exceptions (Soutou & Teste, 2008, p. 332) " Attention à bien distinguer un message destiné à l’utilisateur (put_line) d’une erreur logicielle (raise et raise_application_error). M2106 – Cours 5/6 – Exceptions et curseurs 8 / 36
  • 10. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions raise et raise_application_error artie II PL/SQL Déclencheurs Les déclencheurs (triggers) existent depuis la version 6 d’Oracle. Ils sont compilables depuis la version 7.3 (auparavant, ils étaient évalués lors de l’exécution). Depuis la version 8, il existe un nouveau type de déclencheur (INSTEAD OF) qui permet la mise à jour de vues multitables. La plupart des déclencheurs peuvent être vus comme des programmes résidents associés à un événement particulier (insertion, modification d’une ou de plusieurs colonnes, suppression) Figure 7-10 Utilisation de RAISE_APPLICATION_ERROR Scénario de gestion d’exceptions (Soutou & Teste, 2008, p. 332) " Attention à bien distinguer un message destiné à l’utilisateur (put_line) d’une erreur logicielle (raise et raise_application_error). AFormellement interdit : signaler une erreur par un message (put_line). M2106 – Cours 5/6 – Exceptions et curseurs 8 / 36
  • 11. Exceptions Extraction de données Exceptions liées à l’extraction de données Exceptions et curseurs 1 Exceptions 2 Extraction de données Affectation Curseur manuel Curseur semi-automatique Curseur automatique 3 Exceptions liées à l’extraction de données M2106 – Cours 5/6 – Exceptions et curseurs 9 / 36
  • 12. Exceptions Extraction de données Exceptions liées à l’extraction de données Extraction de données Cadrage Il existe deux façons d’extraire des données en PL/SQL : ← Affectation Affectation de valeurs Extrait une seule ligne 1 syntaxe : select ... into ... from Curseur Boucle sur un résultat Extrait plusieurs lignes 3 syntaxes : 1 manuel : open ... 2 semi-autom. : cursor ... 3 automatique : for ... M2106 – Cours 5/6 – Exceptions et curseurs 10 / 36
  • 13. Exceptions Extraction de données Exceptions liées à l’extraction de données Extraction de données Cadrage Il existe deux façons d’extraire des données en PL/SQL : ← Affectation Affectation de valeurs Extrait une seule ligne 1 syntaxe : select ... into ... from Curseur Boucle sur un résultat Extrait plusieurs lignes 3 syntaxes : 1 manuel : open ... 2 semi-autom. : cursor ... 3 automatique : for ... ANe pas utiliser une affectation pour plusieurs lignes! Déclenche l’exception too_many_rows à l’exécution. . . M2106 – Cours 5/6 – Exceptions et curseurs 10 / 36
  • 14. Exceptions Extraction de données Exceptions liées à l’extraction de données Extraction de données Cadrage Il existe deux façons d’extraire des données en PL/SQL : ← Affectation Affectation de valeurs Extrait une seule ligne 1 syntaxe : select ... into ... from Curseur Boucle sur un résultat Extrait plusieurs lignes 3 syntaxes : 1 manuel : open ... 2 semi-autom. : cursor ... 3 automatique : for ... ANe pas utiliser une affectation pour plusieurs lignes! Déclenche l’exception too_many_rows à l’exécution. . . Éviter l’utilisation d’un curseur pour une seule ligne. M2106 – Cours 5/6 – Exceptions et curseurs 10 / 36
  • 15. Exceptions Extraction de données Exceptions liées à l’extraction de données Exceptions et curseurs 1 Exceptions 2 Extraction de données Affectation Curseur manuel Curseur semi-automatique Curseur automatique 3 Exceptions liées à l’extraction de données M2106 – Cours 5/6 – Exceptions et curseurs 11 / 36
  • 16. Exceptions Extraction de données Exceptions liées à l’extraction de données Affectation Syntaxes select * into variableRowType from ... -- var %rowtype select A[, ..., Z] into var1[, ..., varZ] from ... -- var %type , number ... declare vTatouage chien.tatouage %type default 1664 ; -- stocke une valeur vUnChien chien %rowtype ; -- stocke une ligne vMaxPrime participation.prime %type ; vNbSup100 number ; vDernierConc concours.dateC %type ; begin -- Affectation de l'intégralité d'une ligne dans un %rowtype select * into vUnChien from chien where tatouage = 1664 ; -- rowtype : on récupère nom sexe -- Affectation d'une valeur dans un %type select max(prime) into vMaxPrime from participation where tatouage = 1664 ; -- Affectation de 2 valeurs select count (*), max(dateC) into vNbSup100 , vDernierConc from participation p, concours c where p.idC = c.idC and tatouage = 1664 and prime 100 ; -- Affichage du résultat dbms_output.put_line(vUnChien.nom||' '||'de sexe ' || case vUnChien.sexe when 'M' then 'masculin ' else 'féminin' end || ' dont le plus gros gain est de '|| vMaxPrime ||' e. Gains supérieurs à' || ' 100 e : '|| vNbSup100 ||'. Dernier bon concours : '|| vDernierConc) ; end ; / -- Iench de sexe féminin dont le plus gros gain est de 1234 e. Gains supérieurs à 100 e : 1. Dernier bon concours : 30-SEP -13 M2106 – Cours 5/6 – Exceptions et curseurs 12 / 36
  • 17. Exceptions Extraction de données Exceptions liées à l’extraction de données Exceptions et curseurs 1 Exceptions 2 Extraction de données Affectation Curseur manuel Curseur semi-automatique Curseur automatique 3 Exceptions liées à l’extraction de données M2106 – Cours 5/6 – Exceptions et curseurs 13 / 36
  • 18. Exceptions Extraction de données Exceptions liées à l’extraction de données Curseur manuel Les instructions utilisées Instruction Description cursor nomCur is requête ; Déclare le curseur. open nomCur ; Ouvre le curseur en chargeant les lignes en mémoire centrale. Aucune exception levée si la requête ne renvoie aucune ligne. fetch nomCur into var1, ..., varN ; Avance d’une ligne et affecte les valeurs de la ligne aux variables. close nomCur ; Ferme le curseur. nomCur%isOpen true si le curseur est ouvert, false sinon. nomCur%notFound true si le dernier fetch n’a pas renvoyé de ligne (fin de curseur), false sinon. nomCur%found true si le dernier fetch a renvoyé une ligne, false sinon. nomCur%rowCount Nombre de lignes parcourues jusqu’à présent. M2106 – Cours 5/6 – Exceptions et curseurs 14 / 36
  • 19. Exceptions Extraction de données Exceptions liées à l’extraction de données Curseur manuel Cycle de vie cursor Déclaration du nom du curseur et de la requête. open Ouverture du curseur et exécution de la requête. fetch Récupération des lignes, une par une. close Fermeture du curseur et libération des ressources. http://www.dbanotes.com/wp-content/uploads/2011/06/Introduction-to-Oracle-11g-Cursors_img_2-1024x221.jpg M2106 – Cours 5/6 – Exceptions et curseurs 15 / 36
  • 20. Exceptions Extraction de données Exceptions liées à l’extraction de données Curseur manuel Exemple 1 : curseur manuel -- Exemple d'utilisation d'un curseur manuel create procedure hallOfFame as cursor curTopChiens is select c.tatouage , nom , count(classement) totClass from chien c, participation p where c.tatouage = p.tatouage and classement is not null group by c.tatouage , nom order by 3, 2 ; vTopChien curTopChiens %rowtype ; begin dbms_output.put_line('Hall of Fame de la Société Canine ') ; open curTopChiens ; -- Récupérer le premier chien fetch curTopChiens into vTopChien ; while curTopChiens %found loop dbms_output.put('Numéro '|| curTopChiens %rowcount ||' : '|| vTopChien.nom) ; dbms_output.put(' ('|| vTopChien.tatouage ||') avec '|| vTopChien.totClass ||' classement ') ; if vTopChien.totClass 1 then dbms_output.put('s') ; end if ; dbms_output.new_line ; -- Passer au chien suivant (NE PAS L'OUBLIER !!!) fetch curTopChiens into vTopChien ; end loop ; close curTopChiens ; -- NE PAS l'OUBLIER !!! end hallOfFame ; / call hallOfFame () ; -- Hall of Fame de la Société Canine -- Numéro 1 : Iench (1664) avec 1 classement -- Numéro 2 : Cerbère (666) avec 7 classements M2106 – Cours 5/6 – Exceptions et curseurs 16 / 36
  • 21. Exceptions Extraction de données Exceptions liées à l’extraction de données Curseur manuel Exemple 2 : affectation et curseur manuel paramétré create procedure afficherParticipants(pIdC in concours.idC %type) as cursor curPart(pcSexe in chien.sexe %type) is select p.tatouage from participation p, chien c where p.tatouage = c.tatouage and idC = pIdC -- paramètre de la procédure and sexe = pcSexe -- paramètre du curseur order by classement nulls last , tatouage ; vUnChien chien.tatouage %type ; vVille concours.ville %type ; vDateC concours.dateC %type ; vDotation number ; -- car la longueur peut dépasser concours.prime %type begin select ville , dateC , sum(prime) into vVille , vDateC , vDotation from concours c, participation p where c.idC = p.idC and c.idC = pIdC group by c.idC , ville , dateC ; dbms_output.put_line('Concours de '|| vVille ||' du '|| vDateC) ; dbms_output.put_line('Dotation : '|| vDotation) ; -- Liste des participants open curPart('F') ; -- Récupérer le premier chien fetch curPart into vUnChien ; dbms_output.put_line('Classement des chiennes ') ; while curPart %found loop dbms_output.put_line(curPart%rowCount ||'. '|| vUnChien) ; fetch curPart into vUnChien ; -- Passer au chien suivant (NE PAS L'OUBLIER !!!) end loop ; close curPart ; -- NE PAS l'OUBLIER !!! -- Idem pour les chiens mâles : open curPart('M') ; etc end afficherParticipants ; / call afficherParticipants (10) ; M2106 – Cours 5/6 – Exceptions et curseurs 17 / 36
  • 22. Exceptions Extraction de données Exceptions liées à l’extraction de données Exceptions et curseurs 1 Exceptions 2 Extraction de données Affectation Curseur manuel Curseur semi-automatique Curseur automatique 3 Exceptions liées à l’extraction de données M2106 – Cours 5/6 – Exceptions et curseurs 18 / 36
  • 23. Exceptions Extraction de données Exceptions liées à l’extraction de données Curseur semi-automatique Exemple 1 : curseur semi-automatique Le choc des simplifications variable %rowtype, open, fetch, close → for NB : ne pas déclarer la variable utilisée dans le for :-) -- Exemple d'utilisation d'un curseur semi -automatique create procedure hallOfFame as cursor curTopChiens is select c.tatouage , nom , count(classement) totClass from chien c, participation p where c.tatouage = p.tatouage and classement is not null group by c.tatouage , nom order by 3, 2 ; begin dbms_output.put_line('Hall of Fame de la Société Canine ') ; for vTopChien in curTopChiens loop dbms_output.put('Numéro '|| curTopChiens %rowcount ||' : '|| vTopChien.nom) ; dbms_output.put(' ('|| vTopChien.tatouage ||') avec '|| vTopChien.totClass ||' classement ') ; if vTopChien.totClass 1 then dbms_output.put('s') ; end if ; dbms_output.new_line ; end loop ; end hallOfFame ; / call hallOfFame () ; -- Hall of Fame de la Société Canine -- Numéro 1 : Iench (1664) avec 1 classement -- Numéro 2 : Cerbère (666) avec 7 classements M2106 – Cours 5/6 – Exceptions et curseurs 19 / 36
  • 24. Exceptions Extraction de données Exceptions liées à l’extraction de données Curseur semi-automatique Exemple 2 : affectation et curseur semi-automatique paramétré create procedure afficherParticipants(pIdC in concours.idC %type) as -- Définition d'un curseur paramétré avec Sexe cursor curPart(pcSexe in chien.sexe %type) is select p.tatouage from participation p, chien c where p.tatouage = c.tatouage and idC = pIdC -- paramètre de la procédure and sexe = pcSexe -- paramètre du curseur order by classement nulls last , tatouage ; vVille concours.ville %type ; vDateC concours.dateC %type ; vDotation number ; -- car la longueur peut dépasser concours.prime %type begin select ville , dateC , sum(prime) into vVille , vDateC , vDotation from concours c, participation p where c.idC = p.idC and c.idC = pIdC group by c.idC , ville , dateC ; dbms_output.put_line('Concours de '|| vVille ||' du '|| vDateC) ; dbms_output.put_line('Dotation : '|| vDotation) ; -- Liste des participants dbms_output.put_line('Classement des chiennes ') ; for vUneChienne in curPart('F') loop dbms_output.put_line(curPart%rowCount ||'. '|| vUneChienne.tatouage) ; end loop ; dbms_output.put_line('Classement des chiens ') ; for vUnChien in curPart('M') loop dbms_output.put_line(curPart%rowCount ||'. '|| vUnChien.tatouage) ; end loop ; end afficherParticipants ; / call afficherParticipants (10) ; M2106 – Cours 5/6 – Exceptions et curseurs 20 / 36
  • 25. Exceptions Extraction de données Exceptions liées à l’extraction de données Exceptions et curseurs 1 Exceptions 2 Extraction de données Affectation Curseur manuel Curseur semi-automatique Curseur automatique 3 Exceptions liées à l’extraction de données M2106 – Cours 5/6 – Exceptions et curseurs 21 / 36
  • 26. Exceptions Extraction de données Exceptions liées à l’extraction de données Curseur automatique Exemple 1 : curseur automatique Le choc des simplifications 2 : le retour cursor → requête dans le for. -- Exemple d'utilisation d'un curseur automatique create procedure hallOfFame as vI number := 0 ; -- Il n'y a plus de déclaration de curseur ici begin dbms_output.put_line('Hall of Fame de la Société Canine ') ; for vTopChien in (select c.tatouage , nom , count(classement) totClass from chien c, participation p where c.tatouage = p.tatouage and classement is not null group by c.tatouage , nom order by 3, 2) loop vI := vI + 1 ; -- remplace %rowcount car on n'y a plus accès dbms_output.put('Numéro '||vI||' : '|| vTopChien.nom) ; dbms_output.put(' ('|| vTopChien.tatouage ||') avec '|| vTopChien.totClass ||' classement ') ; if vTopChien.totClass 1 then dbms_output.put('s') ; end if ; dbms_output.new_line ; end loop ; end hallOfFame ; / call hallOfFame () ; -- Hall of Fame de la Société Canine -- Numéro 1 : Iench (1664) avec 1 classement -- Numéro 2 : Cerbère (666) avec 7 classements M2106 – Cours 5/6 – Exceptions et curseurs 22 / 36
  • 27. Exceptions Extraction de données Exceptions liées à l’extraction de données Curseur automatique Exemple 2 : affectation et curseur automatique paramétré par synchronisation Le paramétrage du curseur se fait désormais via la synchronisation sur pIdC. create procedure afficherParticipants(pIdC in concours.idC %type) as vVille concours.ville %type ; vDateC concours.dateC %type ; vDotation number ; -- car la longueur peut dépasser concours.prime %type vI number := 0 ; begin select ville , dateC , sum(prime) into vVille , vDateC , vDotation from concours c, participation p where c.idC = p.idC and c.idC = pIdC group by c.idC , ville , dateC ; dbms_output.put_line('Concours de '|| vVille ||' du '|| vDateC) ; dbms_output.put_line('Dotation : '|| vDotation) ; -- Liste des participants dbms_output.put_line('Classement des chiennes ') ; for vUneChienne in (select p.tatouage from participation p, chien c where p.tatouage = c.tatouage and idC = pIdC -- paramètre de la procédure and sexe = 'F' -- il n'y a plus de paramètre passé au curseur order by classement nulls last , tatouage) loop vI := vI + 1 ; -- remplace %rowCount car on n'y a plus accès dbms_output.put_line(vI||'. '|| vUneChienne.tatouage) ; end loop ; dbms_output.put_line('Classement des chiens ') ; vI := 0 ; for vUnChien in (select ... and sexe = 'M'... -- gros inconvénient : copier/coller !!! end afficherParticipants ; / call afficherParticipants (10) ; M2106 – Cours 5/6 – Exceptions et curseurs 23 / 36
  • 28. Exceptions Extraction de données Exceptions liées à l’extraction de données Bilan sur les 3 types de curseurs Curseur manuel ACode long ABugs potentiels dus aux divers oublis quasi-inévitables M2106 – Cours 5/6 – Exceptions et curseurs 24 / 36
  • 29. Exceptions Extraction de données Exceptions liées à l’extraction de données Bilan sur les 3 types de curseurs Curseur manuel ACode long ABugs potentiels dus aux divers oublis quasi-inévitables Curseur semi-automatique © 4 instructions en moins! La requête est parfois « loin » (déclaration) de son utilisation (boucle) M2106 – Cours 5/6 – Exceptions et curseurs 24 / 36
  • 30. Exceptions Extraction de données Exceptions liées à l’extraction de données Bilan sur les 3 types de curseurs Curseur manuel ACode long ABugs potentiels dus aux divers oublis quasi-inévitables Curseur semi-automatique © 4 instructions en moins! La requête est parfois « loin » (déclaration) de son utilisation (boucle) Curseur automatique © Encore 1 instruction en moins! © La requête et son utilisation sont couplées dans la boucle Pas de réutilisation de requête, contrairement au curseur déclaré M2106 – Cours 5/6 – Exceptions et curseurs 24 / 36
  • 31. Exceptions Extraction de données Exceptions liées à l’extraction de données Conseil d’un ami qui vous veut du bien ANe réinventez pas la roue! « Il n’y a rien de plus inutile que de faire avec efficacité quelque chose qui ne doit pas être fait du tout. » — Peter Drucker http://www.videouniversity.com/files/reinventing_wheel.jpg M2106 – Cours 5/6 – Exceptions et curseurs 25 / 36
  • 32. Exceptions Extraction de données Exceptions liées à l’extraction de données Conseil d’un ami qui vous veut du bien ANe réinventez pas la roue! « Il n’y a rien de plus inutile que de faire avec efficacité quelque chose qui ne doit pas être fait du tout. » — Peter Drucker http://www.videouniversity.com/files/reinventing_wheel.jpg Ne recodez pas avec des boucles les sélections, les jointures, les regroupements. . . Exploitez la puissance de SQL! M2106 – Cours 5/6 – Exceptions et curseurs 25 / 36
  • 33. Exceptions Extraction de données Exceptions liées à l’extraction de données Sometimes less is more! -- À NE PAS FAIRE : réinventer la roue !!! Ça fonctionne mais c'est sous -optimal , peu maintenable create function gainsMalesToulousainsKO return number as pVille adherent.ville %type ; vTotalGains number := 0 ; begin for ch in (select * from chien) loop if ch.sexe = 'M' then -- vérifie qu 'il est à Toulouse select ville into pVille from adherent where idA = ch.idA ; if pVille = 'Toulouse ' then for pa in (select * from participation) loop if ch.tatouage = pa.tatouage then vTotalGains := vTotalGains + pa.prime ; -- Ce code est une HORREUR ! end if ; -- Ne faites ** surtout pas** ça end loop ; end if ; end if ; end loop ; return vTotalGains ; end gainsMalesToulousainsKO ; / M2106 – Cours 5/6 – Exceptions et curseurs 26 / 36
  • 34. Exceptions Extraction de données Exceptions liées à l’extraction de données Sometimes less is more! -- À NE PAS FAIRE : réinventer la roue !!! Ça fonctionne mais c'est sous -optimal , peu maintenable create function gainsMalesToulousainsKO return number as pVille adherent.ville %type ; vTotalGains number := 0 ; begin for ch in (select * from chien) loop if ch.sexe = 'M' then -- vérifie qu 'il est à Toulouse select ville into pVille from adherent where idA = ch.idA ; if pVille = 'Toulouse ' then for pa in (select * from participation) loop if ch.tatouage = pa.tatouage then vTotalGains := vTotalGains + pa.prime ; -- Ce code est une HORREUR ! end if ; -- Ne faites ** surtout pas** ça end loop ; end if ; end if ; end loop ; return vTotalGains ; end gainsMalesToulousainsKO ; / -- Exploitation judicieuse de SQL , encapulation dans une fonction create function gainsMalesToulousainsOK return number as vTotalGains number ; begin -- calcul du résultat en pur SQL select nvl(sum(prime), 0) into vTotalGains from chien ch, participation pa, adherent ad where ch.tatouage = pa.tatouage and ch.idA = ad.idA and ville = 'Toulouse ' and sexe = 'M' ; return vTotalGains ; end gainsMalesToulousainsOK ; / M2106 – Cours 5/6 – Exceptions et curseurs 26 / 36
  • 35. Exceptions Extraction de données Exceptions liées à l’extraction de données Exceptions et curseurs 1 Exceptions 2 Extraction de données Affectation Curseur manuel Curseur semi-automatique Curseur automatique 3 Exceptions liées à l’extraction de données M2106 – Cours 5/6 – Exceptions et curseurs 27 / 36
  • 36. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Exceptions prédéfinies liées à l’extraction de données Parmi les exceptions prédéfinies, on trouve également : Exception Code Description dup_val_on_index ORA-00001 Violation de contrainte unique : UN ou PK no_data_found ORA-01403 Requête ne retournant aucun résultat rowtype_mismatch ORA-06504 Incompatibilité de types lors d’une affectation too_many_rows ORA-01422 Requête retournant plusieurs lignes (select into A) ORA-01400 Tentative d’insertion d’une valeur null non autorisée ORA-01407 Tentative de màj d’une valeur null non autorisée ORA-02290 Transgression d’une contrainte check ORA-02291 Tentative d’insertion d’une valeur de FK inexistante ORA-02292 Tentative de suppression d’une valeur de FK pointée M2106 – Cours 5/6 – Exceptions et curseurs 28 / 36
  • 37. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Exceptions prédéfinies liées à l’extraction de données Parmi les exceptions prédéfinies, on trouve également : Exception Code Description dup_val_on_index ORA-00001 Violation de contrainte unique : UN ou PK no_data_found ORA-01403 Requête ne retournant aucun résultat rowtype_mismatch ORA-06504 Incompatibilité de types lors d’une affectation too_many_rows ORA-01422 Requête retournant plusieurs lignes (select into A) ORA-01400 Tentative d’insertion d’une valeur null non autorisée ORA-01407 Tentative de màj d’une valeur null non autorisée ORA-02290 Transgression d’une contrainte check ORA-02291 Tentative d’insertion d’une valeur de FK inexistante ORA-02292 Tentative de suppression d’une valeur de FK pointée Certaines erreurs ne sont pas associées à des exceptions prédéfinies. On est donc forcé de les intercepter : soit en déclarant une exception et en la liant au code d’erreur associé (pragma), soit dans le cas others du bloc exception (en testant pour être sûr de bien avoir été déclenché par l’exception attendue). M2106 – Cours 5/6 – Exceptions et curseurs 28 / 36
  • 38. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Exceptions prédéfinies liées à l’extraction de données : exemple create procedure ajouterParticipation(pTatouage in participation.tatouage %type , pConcours in participation.idC %type , pClass in participation.classement %type , pPrime in participation.prime %type) as fkInexistante exception ; pragma exception_init(fkInexistante , -2291) ; -- associe un nom à cette exception prédéfinie -- ORA -02291: integrity constraint FK... violated - parent key not found vTestException number ; begin insert into participation values(pTatouage , pConcours , pClass , pPrime) ; exception when fkInexistante then -- PB de FK... oui , mais laquelle ? if sqlerrm like '%FK_PARTICIPATION_TATOUAGE%' escape '' then raise_application_error (-20001, 'Erreur : tatouage '|| pTatouage ||' inexistant.') ; elsif sqlerrm like '%FK_PARTICIPATION_IDC%' escape '' then raise_application_error (-20002, 'Erreur : concours '|| pConcours ||' inexistant.') ; else raise_application_error (-20003, 'Erreur fatale (FK transgressée inconnue).') ; end if ; when dup_val_on_index then raise_application_error (-20004, 'Part. au conc. '|| pConcours ||' déjà notée pour '|| pTatouage) ; end ajouterParticipation ; / call ajouterParticipation (99, 10, 2, 512) ; -- SQL Error: ORA -20001: Erreur : tatouage 99 inexistant. call ajouterParticipation (51, 99, 2, 512) ; -- SQL Error: ORA -20002: Erreur : concours 99 inexistant. call ajouterParticipation (666, 10, 2, 512) ; -- SQL Error: ORA -20004: Part. au conc. 10 déjà notée pour 666 M2106 – Cours 5/6 – Exceptions et curseurs 29 / 36
  • 39. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Compléments 322 © Éditions Eyrolles Plusieurs erreurs Le tableau suivant décrit une procédure qui gère deux erreurs : aucun pilote n’est associé à la compagnie de code passé en paramètre (NO_DATA_FOUND) et plusieurs pilotes le sont (TOO_ MANY_ROWS). Le programme se termine correctement si la requête retourne une seule ligne (cas de la compagnie de code 'CAST'). La trace de l’exécution de cette procédure est la suivante : SQL EXECUTE procException1('AF'); Tableau 7-20 Deux exceptions traitées Code PL/SQL Commentaires CREATE PROCEDURE procException1 (p_comp IN VARCHAR2) IS var1 Pilote.nom%TYPE; BEGIN SELECT nom INTO var1 FROM Pilote WHERE comp = p_comp; DBMS_OUTPUT.PUT_LINE('Le pilote de la compagnie ' || p_comp || ' est ' || var1); Requête déclenchant potentiellement deux exceptions prévues. DBMS_OUTPUT.PUT_LINE('La compagnie ' || p_comp || ' n''a aucun pilote!'); Aucun résultat renvoyé. DBMS_OUTPUT.PUT_LINE('La compagnie ' || p_comp || ' a plusieurs pilotes!'); END; Plusieurs résultats renvoyés. EXCEPTION WHEN NO_DATA_FOUND THEN WHEN TOO_MANY_ROWS THEN Scénario de gestion d’exceptions (Soutou Teste, 2008, p. 322) M2106 – Cours 5/6 – Exceptions et curseurs 30 / 36
  • 40. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Compléments Partie II PL/SQL Imbrication de blocs d’erreurs Le tableau suivant décrit une procédure qui inclut un bloc d’exceptions imbriqué au code prin- Tableau 7-21 Une exception traitée pour deux instructions Code PL/SQL Commentaires CREATE PROCEDURE procException2 (p_brevet IN VARCHAR2, p_heures IN NUMBER) IS var1 Pilote.nom%TYPE; requete NUMBER := 1; BEGIN SELECT nom INTO var1 FROM Pilote WHERE brevet = p_brevet; DBMS_OUTPUT.PUT_LINE('Le pilote de ' || p_brevet || ' est ' || var1); Requêtes déclenchant potentiellement une exception prévue. requete := 2; SELECT nom INTO var1 FROM Pilote WHERE nbHVol = p_heures; DBMS_OUTPUT.PUT_LINE('Le pilote ayant ' || p_heures || ' heures est ' || var1); IF requete = 1 THEN DBMS_OUTPUT.PUT_LINE('Pas de pilote de brevet : ' || p_brevet); ELSE DBMS_OUTPUT.PUT_LINE('Pas de pilote ayant ce nombre d''heures de vol : ' || p_heures); END IF; DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' || SQLERRM || ' (' || SQLCODE || ')'); END; Aucun résultat. Traitement pour savoir quelle requête a déclenché l’exception. Autre erreur. EXCEPTION WHEN NO_DATA_FOUND THEN WHEN OTHERS THEN SOUTOU Livre Page 324 Vendredi, 25. janvier 2008 1:08 13 Scénario de gestion d’exceptions (Soutou Teste, 2008, p. 324) M2106 – Cours 5/6 – Exceptions et curseurs 31 / 36
  • 41. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Compléments chapitre n° 7 Programmation avancée Exception utilisateur Il est possible de définir ses propres exceptions. Cela pour bénéficier des blocs de traitements d’erreurs et aborder une erreur applicative comme une erreur renvoyée par la base. Cela Tableau 7-22 Bloc d’exceptions imbriqué Code PL/SQL Commentaires CREATE PROCEDURE procException3 (p_brevet IN VARCHAR2, p_heures IN NUMBER) IS var1 Pilote.nom%TYPE; BEGIN BEGIN SELECT nom INTO var1 FROM Pilote WHERE brevet = p_brevet; DBMS_OUTPUT.PUT_LINE('Le pilote de ' || p_brevet || ' est ' || var1); DBMS_OUTPUT.PUT_LINE('Pas de pilote de brevet : ' || p_brevet); DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' || SQLERRM || ' (' || SQLCODE || ')'); END; Bloc imbriqué. Gestion des exceptions de la première requête. SELECT nom INTO var1 FROM Pilote WHERE nbHVol = p_heures ; DBMS_OUTPUT.PUT_LINE('Le pilote ayant ' || p_heures || ' heures est ' || var1); Suite du traitement. DBMS_OUTPUT.PUT_LINE('Pas de pilote ayant ce nombre d''heures de vol : ' || p_heures); DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' || SQLERRM || ' (' || SQLCODE || ')'); END; Gestion des exceptions de la deuxième requête. EXCEPTION WHEN NO_DATA_FOUND THEN WHEN OTHERS THEN EXCEPTION WHEN NO_DATA_FOUND THEN WHEN OTHERS THEN SOUTOU Livre Page 325 Vendredi, 25. janvier 2008 1:08 13 Scénario de gestion d’exceptions (Soutou Teste, 2008, p. 325) M2106 – Cours 5/6 – Exceptions et curseurs 32 / 36
  • 42. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Compléments 326 © Éditions Eyrolles Dans notre exemple, programmons les deux exceptions suivantes : ● erreur_piloteTropJeune qui va interdire l’insertion des pilotes ayant moins de 200 heures de vol ; ● erreur_piloteTropExpérimenté qui va interdire l’insertion des pilotes ayant plus de 20 000 heures de vol. Le tableau suivant décrit cette procédure qui intercepte ces deux erreurs applicatives : La trace de l’exécution de cette procédure où l’on passe des valeurs en paramètres qui déclen- chent les deux exceptions est la suivante : Tableau 7-23 Exceptions utilisateur Code PL/SQL Commentaires CREATE PROCEDURE saisiePilote (p_brevet IN VARCHAR2,p_nom IN VARCHAR2, p_nbHVol IN NUMBER, p_comp IN VARCHAR2) IS Déclaration de l’exception. BEGIN INSERT INTO Pilote (brevet,nom,nbHVol,comp) VALUES (p_brevet,p_nom,p_nbHVol,p_comp); IF p_nbHVol 200 THEN END IF; IF p_nbHVol 20000 THEN END IF; COMMIT; Corps du traitement (validation). EXCEPTION ROLLBACK; DBMS_OUTPUT.PUT_LINE ('Désolé, le pilote manque d''expérience'); ROLLBACK; DBMS_OUTPUT.PUT_LINE ('Désolé, le pilote a trop d''expérience'); WHEN OTHERS THEN ROLLBACK; DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' || SQLERRM || '(' || SQLCODE || ')'); END; Gestion de l’exception. Gestion des autres exceptions. erreur_piloteTropJeune EXCEPTION; erreur_piloteTropExpérimenté EXCEPTION; RAISE erreur_piloteTropJeune; RAISE erreur_piloteTropExpérimenté; WHEN erreur_piloteTropJeune THEN WHEN erreur_piloteTropExpérimenté THEN Scénario de gestion d’exceptions (Soutou Teste, 2008, p. 326) M2106 – Cours 5/6 – Exceptions et curseurs 33 / 36
  • 43. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Compléments lève pas l’exception NO_DATA_FOUND pour les instructions UPDATE et DELETE. Ce qui est en théorie valable (aucune action sur la base peut ne pas être considérée comme une erreur), en pratique il est utile de connaître le code retour de l’instruction de mise à jour. Considérons à nouveau la procédure détruitCompagnie en prenant en compte l’erreur applicative erreur_compagnieInexistante qui intercepte une suppression non réalisée. Le test du curseur implicite de cette instruction déclenche l’exception utilisateur associée. L’exécution de cette procédure où l’on passe un code compagnie inexistant fait maintenant dérouler la section des exceptions. Tableau 7-24 Utilisation du curseur implicite Code PL/SQL Commentaires CREATE OR REPLACE PROCEDURE détruitCompagnie (p_comp IN VARCHAR2) IS Déclaration des exceptions. BEGIN DELETE FROM Compagnie WHERE comp = p_comp; IF THEN END IF; COMMIT; DBMS_OUTPUT.PUT_LINE('Compagnie '||p_comp|| ' détruite.'); Corps du traitement (validation). EXCEPTION THEN DBMS_OUTPUT.PUT_LINE ('Désolé, il reste encore un pilote à la compagnie ' || p_comp); THEN DBMS_OUTPUT.PUT_LINE ('La compagnie ' || p_comp || ' n''existe pas dans la base!'); THEN DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' || SQLERRM || '(' || SQLCODE || ')'); END; Gestion des exceptions. Gestion des autres exceptions. erreur_ilResteUnPilote EXCEPTION; PRAGMA EXCEPTION_INIT(erreur_ilResteUnPilote , -2292); erreur_compagnieInexistante EXCEPTION; SQL%NOTFOUND RAISE erreur_compagnieInexistante; WHEN erreur_ilResteUnPilote WHEN erreur_compagnieInexistante WHEN OTHERS Scénario de gestion d’exceptions (Soutou Teste, 2008, p. 327) M2106 – Cours 5/6 – Exceptions et curseurs 34 / 36
  • 44. Exceptions Extraction de données Exceptions liées à l’extraction de données Le mécanisme de gestion des exceptions Compléments Le tableau suivant décrit la procédure détruitCompagnie qui intercepte l’erreur ORA- 02292: enregistrement fils existant. Il s’agit de contrôler le programme si la compagnie à détruire possède encore des pilotes référencés dans la table Pilote. La trace de l’exécution de cette procédure est la suivante. Notez que si on applique cette procé- dure à une compagnie inexistante, le programme se termine normalement sans passer dans la section des exceptions. Tableau 7-25 Exception interne non prédéfinie Code PL/SQL Commentaires CREATE PROCEDURE détruitCompagnie(p_comp IN VARCHAR2) IS Déclaration de l’exception. BEGIN DELETE FROM Compagnie WHERE comp = p_comp; COMMIT; DBMS_OUTPUT.PUT_LINE ('Compagnie ' || p_comp || ' détruite.'); Corps du traitement (validation). DBMS_OUTPUT.PUT_LINE ('Désolé, il reste encore un pilote à la compagnie ' || p_comp); DBMS_OUTPUT.PUT_LINE('Erreur d''Oracle ' || SQLERRM || '(' || SQLCODE || ')'); END; Gestion de l’exception. Gestion des autres exceptions. erreur_ilResteUnPilote EXCEPTION; PRAGMA EXCEPTION_INIT(erreur_ilResteUnPilote , -2292); EXCEPTION WHEN erreur_ilResteUnPilote THEN WHEN OTHERS THEN Scénario de gestion d’exceptions (Soutou Teste, 2008, p. 330) M2106 – Cours 5/6 – Exceptions et curseurs 35 / 36
  • 45. Exceptions Extraction de données Exceptions liées à l’extraction de données Sources Les illustrations sont reproduites à partir du document suivant : SQL pour Oracle – 3e édition, C. Soutou, Eyrolles (2008) M2106 – Cours 5/6 – Exceptions et curseurs 36 / 36