Upload
youssef-loumi
View
696
Download
8
Embed Size (px)
Citation preview
1
ENIS GI2ENIS GI2
Faiza JedidiFaiza Jedidi
SGBD : Langage PL_SQL
2
PlanPlan
Chapitre 1 : Introduction à PL/SQL et Structures de contrôle
Chapitre 2 : Interaction avec Oracle et curseurs explicites
Chapitre 3 : Gestion des exceptions
Chapitre 4 : Les sous programmes, les sous programmes stockés et les packages
Chapitre 5 : Declancheurs de BD
3
PlanPlan
Chapitre 1 : Introduction à PL/SQL et Structures de contrôle
• Introduction• L’environnement PL/SQL• Structure d’un bloc PL/SQL• Types PL/SQL et déclarations
4
IntroductionIntroduction
• PL/SQL?Extension procédurale à SQL• Avantages de PL/SQL
– Développement de programmes modulaires• Déclaration des identifiants : Variables, Constates,..• Structures de contrôle• Fonctions intégrés• Blocs nommés : sous programmes• Procédures et fonctions stockées• Blocs imbriqués• Package
– Déclencheurs de BD– Portabilité– Intégration– Accroissement des performances
5
L’environnement PL/SQLL’environnement PL/SQL
• PL/SQL est une technologie employée par Oracle server et par certains outils oracles. Les blocs PL/SQL sont analysés et exécutés par le moteur PL/SQL qui peut se trouver soit dans l’outil, soit dans le serveur Oracle. Le moteur utilisé dépend d’où le bloc a été appelé.
• Le moteur PL/SQL (PL/SQL engine)Lorsque le moteur PL/SQL reçoit un bloc pour exécution, il effectue
les opérations suivantes :– Séparation des ordres SQL et PL/SQL– Passage des commandes SQL au processeur SQL (SQL Statement
Executor)– Passage des instructions procédurales au processeur d’instructions
procédurales (Procedural Statement Executor)
• Moteur PL/SQL dans les outilsCertains outils disposent de leur propre moteur PL/SQL (Oracle
Forms, Oracle Report,…)
6
Structure d’un bloc PL/SQLStructure d’un bloc PL/SQL
• PL/SQL distingue deux types de blocs : anonymes ou nommés– Bloc anonyme correspond à une séquence d’instructions qui s’exécute
à l’endroit où elle existe– Bloc nommé est un sous programme : fonctions ou procédure
éventuellement paramétrée et pouvant être appelée autant de fois que nécessaire
[ DECLARE--déclaration ]
BEGIN--statements
[EXCEPTION--handlers]END;
Optionnelle
Corps du bloc : Obligatoire
Optionnelle
7
• ExempleDECLARE – ceci est un bloc anonyme
V_Sal NUMBER (9, 3); --déclarationV_Mess VARCHAR2 (50)
BEGINSELECT Sal INTO V_SalFROM Chercheur WHERE Chno =1234;
EXCEPTIONWHEN NO_DATA_FOUND THEN--gestion de l’exception NO_DATA_FOUNDV_Mess := ‘Chercheur non trouvé’;--suiteEND;
Structure d’un bloc PL/SQLStructure d’un bloc PL/SQL
8
• Section de déclarationCette section optionnelle introduite par le mot clé DCLARE est
l’unique endroit de déclaration des constantes, variables simples ou composites, curseurs et exceptions utilisateurs.
• Section exécutableCette section obligatoire introduite par le mot clé BEGIN et se
terminant par END contient les instructions du programme et la section de gestion des erreurs si présente. Ces instructions peuvent être :– Instructions d’affectation– Instructions de contrôle de flux– Instructions SQL– Instructions de gestion des curseurs– Instructions de gestion des erreurs
• Section de gestion des exceptionsCette section optionnelle introduite par le mot EXCEPTION est
réservée pour le traitement des erreurs qui pourraient se produire durant l’exécution d’un programme
Structure d’un bloc PL/SQLStructure d’un bloc PL/SQL
9
Types PL/SQL et déclarationsTypes PL/SQL et déclarations
• Types PL/SQLPL/SQL supporte une variété de type de données utiles pour
déclarer des variables et des constantes – compatibles avec les types Oracle (colonnes de tables)+type BOOLEAN
Type Scalaire Types composés
NUMBER[(précision, scale)] RECORD
VARCHAR2 TABLE
CHAR
DATE
BOOLEAN
10
Types PL/SQL et déclarationsTypes PL/SQL et déclarations
• Déclarations de variablesIdentificateur Type [(précision, scale)] [NOT NULL] [:=expression];Où Identificateur : règles Oracles habituellesNOT NULL : initialisation obligatoireExemples
DECLARE
….V_sal NUMBER (7,3);V_message VARCHAR2(80):= ‘Texte initial’; Married BOOLEAN:=FALSE;Next_Week DATE :=DATE+7;
• Suivre les conventions suivantes :
Identifiant Préfix Exemple
Variables V_ V_sal
Exception E_ E_RupStock
Variables Hôtes H_ H_Ename
Curseurs C_ C_EMPDEPT10
Paramètre P_ P_EMPNO
11
• L’attribut %TypeDéclaration de variable en se référant au type d’une variable ou d’une colonne
Identificateur nomTable.colonne%Type;AvantageGarantit la compatibilité de type surtout si la variable déclaré sera cité dans
INTO pour initialisation à partir d’une colonne
ExempleDECLARE…V_deptno1 dept.deptno%TYPE;V_loc dept.loc%TYPE;V_deptno2 deptno%TYPE;BEGIN
SELECT deptno, locINTO v_deptno, v_locFROM …WHERE …
QuestionEst-ce qu’une variable déclaré avec %TYPE en se référant à une colonne NOT
NULL hérite cette contrainte?
Types PL/SQL et déclarationsTypes PL/SQL et déclarations
12
• Déclaration de constantesIdentificateur CONSTANT Type [(precision,scale)]:=expression;
ExemplePie CONSTANT NUMBER(9.5):=3.14159;
Affectations et expressionsIdentificateur := expression;
ExempleV_compteur :=V_compteur+1;V_message := TO_CHAR(v_compteur);V_ename :=‘KING’;
Les variables logiques reçoivent directement TRUE, FALSE ou bien le résultat d’une expression logique :
Bien_Payé := v_sal>1500;Trouve := TRUE;NotTrouve :=NOT Trouve;
Types PL/SQL et déclarationsTypes PL/SQL et déclarations
13
• Fonction SQL valides en PL/SQL La plupart des fonctions SQL sont utilisables dans les expressions PL/SQL :
F° numériques mono-ligne :F° caractères mono-ligne :F° Date :F° d’usage divers :
ROUND,…LENGTH, LOWER, UPPER,..SYSDATE,NEXTDAY,LASTDAYDECODE, NVL,
Fonctions SQL NON valides dans les instructions procédurales :GREATEST, LEASTFonctions agrégat (min, max, avg, count, etc.)
Types PL/SQL et déclarationsTypes PL/SQL et déclarations
14
DECLAREA CHAR ;B NUMBER ;
BEGIN……DECLARE
A INTEGER ;C NUMBER ;
BEGIN …EXCEPTION
…END ;
…EXCEPTION
WHEN …… THEN ….WHEN …… THEN ….
END;
• Blocs Imbriqués et Portée d’une variableParmi les avantages de l’imbrication, on peut citer :
– Une meilleure lisibilité des programmes décomposés en sous-blocs– Un meilleur usage des techniques de gestion et de propagation des
exceptions
Types PL/SQL et déclarationsTypes PL/SQL et déclarations
15
<<bloc1>>DECLARE
Birthdate DATE ;BEGIN
……DECLARE
Birthdate DATE;BEGIN …
IF Birthdate = bloc1.Birthdate THEN ……END IF;
END ;END bloc1;
• Blocs Imbriqués et Portée d’une variable
Types PL/SQL et déclarationsTypes PL/SQL et déclarations
16
PlanPlan
Chapitre 2 : Interaction avec Oracle et curseurs explicites
• Introduction• Notion de curseur• Curseurs implicites• Curseurs explicites• Conclusion
17
IntroductionIntroduction
• Interaction avec Oracle : accéder et manipuler le contenu de la base de données.
• Cette interaction se fait par les commandes SQL utilisées de deux façons : – Autonome : à partir de l’environnement SQL*Plus– Bloc PL/SQL : environnement de développement comme Oracle
Forms, Report, etc.
• Les commandes SQL (SELECT ou du LMD) utilisées dans un bloc PL/SQL sont dites des curseurs.
18
IntroductionIntroduction
DECLARE
BEGIN SELECT INSERT, UPDATE, DELETE Instructions Procédurales
EXCEPTIONEND ;
19
Notion de CurseurNotion de Curseur
• A l’exécution d’une commande SQL, Oracle Server ouvre une zone de mémoire dans laquelle la commande est analysée (parsed) et exécutée.
• Cette zone est appelée curseur.
Current Row
Zone Mémoire dans laquelle l’ordre SELECT est compilé etexécuté
On distingue deux types de curseurs :• Les curseurs explicites • Les curseurs implicites
20
Notion de curseurNotion de curseur
• Les curseurs explicites– C’est une commande SELECT pouvant ramener plusieurs
lignes et qui est totalement à la charge du développeur. – Un curseur explicite doit être explicitement :
• Déclaré dans la section DECLARE• Géré par le développeur dans la section exécutable. La gestion
d’un curseur consiste à exécuter les opérations : ouverture du curseur, lecture et traitement des lignes, fermeture.
21
• Les curseurs implicites– Un curseur implicite est toute commande SQL (Select, Insert,
Update, Delete) située dans la partie exécutable d’un bloc :• NON déclaré explicitement • Nommé ‘SQL’ implicitement par Oracle : tester l’état du curseur• Gestion automatique par PL/SQL : ouverture, traitement,
fermeture.
– Lorsque le curseur implicite est un ordre SELECT, alors il doit ramener une seule ligne, sinon erreur.
Notion de curseurNotion de curseur
22
Les curseurs implicitesLes curseurs implicites
• Le tableau suivant indique, par opération de manipulation, les commandes SQL susceptibles de jouer le rôle de curseur implicite et/ou explicite :
Opération Curseur implicite Curseur explicite
MAJ Insert, Update, Delete
Aucune*
Interrogation Select …Into Select**
* Il n’existe pas de curseur explicite de mise à jour** Un curseur explicite ne peut être qu’un select
23
Les curseurs implicitesLes curseurs implicites
• ExempleDECLAREV_deptno NUMBER(2);V_Loc VARCHAR2(15);.....BEGINSELECT deptno, locINTO v_deptno, v_loc ObligatoireFROM dept
WHERE upper(dname) = ‘SALES’;…END;
Si le SELECT ne ramène pas exactement une ligne, PL/SQL réagit contre ces erreurs en levant (raise) des exceptions qu’on peut piéger (trap) et gérer dans la section EXCEPTION.
24
• Exceptions du SELECTExceptions du SELECT
Condition Nom Exception
Le SELECT identifie plus d’une ligneErreur Oracle Server ORA-01422
TOO_MANY_ROWS
Le SELECT n’identifie aucune ligneErreur Oracle Server ORA-01403
NO_DATA_FOUND
Les curseurs implicitesLes curseurs implicites
25
Les curseurs implicitesLes curseurs implicites
• Attributs du curseur implicitePL/SQL fournit des attributs permettant d’évaluer le résultat d’un
curseur implicite :
Attribut Description
SQL%ROWCOUNT Entier : Nombre de lignes affectées par le dernier ordre SQL
SQL%FOUND Booléen : TRUE si le dernier ordre SQL affecte au moins une ligne
SQL%NOTFOUND Booléen : TRUE si le dernier ordre SQL n’affecte aucune ligne
SQL%ISOPEN Toujours FALSE pour les curseurs implicites.
Ces attributs sont utilisables comme des fonctions dans les ordres PL/SQL MAIS PAS dans les commandes SQL.
26
• ExempleDECLAREV_Rows_Updated NUMBER; BEGIN UPDATE EMP SET sal = sal*1.1 WHERE deptno = 10;
V_Rows_Updated := SQL%ROWCOUNT;
-- SQL%ISOPEN est FALSEINSERT INTO History_TabValues (‘Dept 10’, V_Rows_Updated, SYSDATE);
END ;
Les curseurs implicitesLes curseurs implicites
27
• Les variables PL/SQL qui risquent d’être utilisées dans des ordres SQL doivent être différentes des noms de colonnes des tables manipulées :
DECLAREempno NUMBER(4) := 7788; BEGINUPDATE EMPSET sal = 9000WHERE empno = empno; !!Toutes les lignes
seront MAJ
… (V_empno) END ;
Les curseurs implicitesLes curseurs implicites
28
Les curseurs explicitesLes curseurs explicites• Motivation
– Besoin de consulter n-uplets issus d’une ou de plusieurs tables de la base de données
– Effectuer des traitements en examinant chaque ligne individuellement
• Curseur explicite – Est une commande Select déclaré et nommé– Généralisation du curseur implicite d’interrogation– Possédant les quatre attributs suivants : %ISOPEN%ISOPEN, %FOUND%FOUND,
%NOTFOUND%NOTFOUND et %ROWCOUNT%ROWCOUNT.
• Exigences du curseur explicite
– Déclaration– Ouverture– Accès aux lignes du curseur– Fermeture
Section DECLARE
Section EXECUTABLE
29
Les curseurs explicitesLes curseurs explicites
• Déclaration d’un curseur : Syntaxe
CURSOR nom_curseurCURSOR nom_curseur [(paramètre1, paramètre2,…)] IS Commande_SELECTIS Commande_SELECT [FOR UPDATE [OF colonne1, colonne2,…] [NOWAIT]];;
Où
nom_curseur : est le nom du curseur
Commande_SELECT : est une requête pouvant utiliser les clauses habituelles (group by, having, order by
Paramètre : est un paramètre formel décrit comme suit :
Nom_paramètre [IN] Type [{:=|DEFAULT} valeur]
FOR UPDATE [OF colonne1, colonne2,…] : place un verrou exclusif portant sur des n-uplets de la table du SELECT
[OF colonne1, colonne2,…] : les colonnes à mettre à jour par le curseur sont verrouillées
NOWAIT : pas d’attente pour accéder aux n-uplets
30
Les curseurs explicitesLes curseurs explicites• Déclaration d’un curseur : ExemplesDECLARE
……
CURSOR C1_Cher IS – curseur non paramétré
SELECT Cnom, Labno
FROM chercheur
WHERE Sal> 1200;
**************************************************************
CURSOR C2_Cher (P_Labno IN NUMBER) IS
-- IN est optionnel
SELECT Grade, Cnom
FROM chercheur
WHERE Labno = P_Labno;
**************************************************************
CURSOR C3_CHER (P_Min NUMBER DEFAULT 0, P_Max NUMBER DEFAULT 99) IS
SELECT ….
FROM ….
WHERE BETWEEN P_Min AND P_Max;
31
Les curseurs explicitesLes curseurs explicites• Ouverture d’un curseur : SyntaxeOPEN nom_curseur [(paramètre_effectif,…)];
• ExemplesOPEN C1_Cher;OPEN C1_Cher;
OPEN C2_Cher (10);|V_Labno :=10;OPEN C2_Cher (10);|V_Labno :=10;
OPEN C2_Cher (V_Labno);OPEN C2_Cher (V_Labno);
OPEN C3_Cher;OPEN C3_Cher;
OPEN C2_Cher (10);|OPEN C2_Cher (10);|
SELECT Grade, CnomFROM chercheurWHERE Labno = 10;
Manager CLARKPresident kINGClerk Miller
Current ROW
Active Set of Rows
ZONE
Mémoire où l’ordre SELECT est compilé et exécuté
32
Les curseurs explicitesLes curseurs explicites
• Accès aux lignes d’un curseur : SyntaxeFETCHFETCH nom_curseur INTOINTO variable1, variable2,…;
• Fonctionnalités– Ramène le contenu de la ligne courante– Assigne les données dans les variables de INTO– Déplace le pointeur vers la ligne suivante
33
• Accès aux lignes d’un curseur : ExempleDECLAREDECLARECURSOR C1_Cher IS
SELECT Cnom, LabnoFROM ChercheurWHERE Sal >1400;
V_Cnom Chercheur.Cnom%TYPE;V_Labno Chercheur.Labtno%TYPE;BEGINBEGINOPEN C1_Cher;--Exécution du SELECTLOOPLOOP
FETCH C1_Cher INTO V_Cnom, V_Labno;EXIT WHEN C1_Cher%NOTFOUND;--Test de sortie-- ici %FOUND est TRUE-- traitement de la ligne ramenée par FETCH…
END LOOP;END LOOP;…ENDEND; --fin du bloc
Les curseurs explicitesLes curseurs explicites
34
Les curseurs explicites Les curseurs explicites • Fermeture d’un curseur Fermeture d’un curseur
– Libération de l’espace mémoire alloué– Réouverture si nécessaire
• SyntaxeSyntaxe
CLOSECLOSE nom_curseur;
• RemarqueRemarquetoute opération sur un curseur fermé (Fetch, %attribut) engendra l’exception prédéfinie INVALID_CURSOR
• Attributs d’un curseur expliciteAttributs d’un curseur explicite– %FOUND
Cet attribut prend la valeur TRUE lorsque une ligne est ramenée, sinon il prend la valeur FALSE
– %NOTFOUNDCet attribut prend la valeur FALSE lorsque une ligne est ramenée, sinon il prend
la valeur TRUE – %ISOPEN
Cet attribut prend la valeur TRUE lorsque le curseur indiqué est ouvert, sinon il prend la valeur FALSE
– %ROWCOUNTCet attribut retourne le nombre de lignes impactées par la dernière instruction SQL
35
Les curseurs explicitesLes curseurs explicites• Curseur et enregistrement : SyntaxeNom_enregistrement nom_curseur%ROWTYPE;• ExempleDECLAREDECLARECURSOR C1 IS
SELECT Cnom, Sal+NVL(prime,0) salaireFROM chercheurWHERE Labno=10;
Rec1 C1%ROWTYPERec1 C1%ROWTYPE;-- Rec1 de même schéma que C1V_Cnom Chercheur.Cnom%TYPE;…BEGINBEGINOPEN C1;LOOP
FETCH C1 INTO Rec1FETCH C1 INTO Rec1;EXIT WHEN C1%NOTFOUND OR C1%ROWCOUNT >5;V_Cnom:=Rec1.Cnom;V_Salaire := Rec1.salaire;
END LOOP;Close C1;ENDEND;__ fin bloc
36
Les curseurs explicitesLes curseurs explicites• Clauses WHERE CURRENT OF et FOR UPDATE Les commandes SQL (UPDATE et DELETE) peuvent utiliser la clause
«WHERE CURRENT OF nom_curseur» pour référencer la ligne courante d’un curseur explicite
• ExempleDECLAREDECLARE
CURSOR C1 ISSELECT Cnom, Labno FROM ChercheurWHERE Sal>1400 FOR UPDATE of Labno;
Ligne_C1 C1%ROWTYPE;BEGINBEGINOPEN C1;LOOPLOOP
FETCH C1 INTO Ligne_C1;EXIT WHEN C1%NOTFOUND;IFIF Ligne_C1.Labno=10 Then
UPDATE ChercheurSET Labno =99—supposé existantWHERE CURRENT OF C1WHERE CURRENT OF C1;
END IFEND IF-- suite de traitementEND LOOPEND LOOP;CLOSE C1;Commit;ENDEND; --fin bloc
37
Les curseurs explicitesLes curseurs explicites• Boucle dédiée curseur
PL/SQL offre une boucle FOR spéciale pour les curseurs explicites. Elle prend en charge toutes les opérations du curseur (OPEN, FETCH, EXIT et CLOSE)
• Syntaxe 1 : cas d’un curseur nomméSyntaxe 1 : cas d’un curseur nomméFOR nom_record IN nom_curseur [(paramètre,…)]
LOOP
…
--traitement de la ligne courante
END LOOP;
• Syntaxe 2 : cas d’un curseur anonymeSyntaxe 2 : cas d’un curseur anonymeFOR nom_record IN (Commande_SELECT)
LOOP
…
--traitement de la ligne courante
END LOOP;
38
• Boucle dédiée curseur : Exemple 1DECLAREDECLARE
CURSOR C1 (P_DATEREC DATE) IS
SELECT Cnom, Grade FROM Chercheur
WHERE DATEREC < P_DATEREC;
BEGINBEGIN
FOR REC IN C1 (’01-JAN-99’) -- curseur ouvert
LOOPLOOP -- ici une ligne est disponible
-- traitement des lignes, une par itération
END LOOP;END LOOP;
/* Ici le curseur est automatiquement fermé
les attributs ne sont pas utilisables
Toute référence à REC est invalide*/
-- suite traitement
END;END;
Les curseurs explicitesLes curseurs explicites
39
• Boucle dédiée curseur : Exemple 2
DECLAREDECLARE
……
BEGINBEGIN
…
V_TOT_SAL NUMBER :=0;
FOR REC IN (SELECT Cnom, SalFOR REC IN (SELECT Cnom, Sal
FROM ChercheurFROM Chercheur
WHERE Labno=10)WHERE Labno=10)
LOOPLOOP
-- traitement de la ligne courante
IF Rec.Sal > 1000 THEN …
END LOOP;END LOOP;
……..
END;END;
Les curseurs explicitesLes curseurs explicites
40
ConclusionConclusion• Notion de curseurNotion de curseur : une zone de mémoire dans laquelle la commande
est analysée (parsed) et exécutée
• Curseurs implicitesCurseurs implicites– Curseur implicite : SELECT …INTO– Autres curseurs implicites : INSRET, UPDATE et DELETE après BEGIN– Attributs des curseurs implicites :SQL%ROWCOUNT, SQL%FOUND, SQL
%NOTFOUND, SQL%ISOPEN
• Curseurs explicitesCurseurs explicites– Déclaration de curseur CURSOR– Ouverture de curseur OPEN– Accès aux lignes d’un curseur FETCH– Fermeture de curseur CLOSE– Attributs d’un curseur explicite :%ROWCOUNT, %FOUND, %NOTFOUND,
%ISOPEN– Curseur et enregistrement : Nom_enregistrement nom_curseur
%ROWTYPE– Clauses WHERE CURRENT OF et FOR UPDATE– Boucle dédiée curseur : gestion automatique de toutes les opérations
d’un curseur (OPEN, FETCH, EXIT et CLOSE)
41
PlanPlan
Chapitre 3 : Gestion des exceptions
1. Introduction2. Gestion des exceptions3. Propagation des exceptions4. Envoie de message d’erreur avec
RAISE_APPLICATION_ERROR5. Traitement des exceptions dans les autres
environnements
42
IntroductionIntroduction
• Lors de l’exécution d’un bloc PL/SQL, certaines erreurs peuvent se produire. Les conditions de ces erreurs sont appelés des exceptions
• Oracle distingue deux types d’exception :
– Les exceptions internes
– Les exceptions utilisateur (User-Exceptions)
43
IntroductionIntroduction
• Les exceptions internes
– Détecter implicitement par le serveur Oracle
– Elles sont libellées et codées (ORA-XXXXX)
– Deux types d’exception internes :
• Nommées (ou Prédéfinies)
• Anonymes (ou Non prédéfinies)
44
IntroductionIntroduction
• Les exceptions utilisateur
– Détecter explicitement par le développeur
– Elles sont définies dans la section DECLARE
• Une exception non traitée, interne ou utilisateur, provoque l’échec du bloc PL/SQL
• Pour se protéger contre ces situations, il est possible de gérer ces exceptions. La gestion d’une exception consiste à prévoir un traitement approprié qui absorbe ou résout l’erreur. L’endroit de ce traitement est la section EXCEPTION
45
Gestion des exceptionsGestion des exceptions
• En cas d’une exception rencontrée dans la section exécutable d’un bloc le contrôle passe immédiatement à la section EXCEPTION du même bloc pour chercher si un gestionnaire approprié existe
DECLARE
BEGIN
EXECPTION
END;
Erreur
Recherche d’un gestionnaire approprié
46
Gestion des exceptionsGestion des exceptions• Comment gérer une exception?
Gérer une exception c’est prévoir un traitement correspondant à l’erreur rencontrée
• Pourquoi gérer une exception?
Transformer un échec en succès
Eviter la propagation de l’exception vers les blocs parents
• Où gérer une exception?
Tout bloc PL/SQL prévoit une section optionnelle de gestion des exceptions
47
Gestion des exceptionsGestion des exceptions• Syntaxe
-- corps du bloc
EXCEPTION
WHEN Nom_Exception THEN
Instructions; -- gestionnaire d’exception
WHEN
[WHEN OTHERS THEN
…;]
END;-- fin du bloc
Nom_Exception : interne ou utilisateur
48
Gestion des exceptionsGestion des exceptions• Exemple
DECLAREDECLARE
V_Cnom Chercheur.Cnom%TYPE;
BEGINBEGIN
SELECT Cnom
INTO V_Cnom
FROM Chercheur
WHERE Labno =10;
DBMS_OUTPUT.PUT_LINE (‘Nom Chercheur’||V_Cnom);
ExceptionException
WHEN TOO_MANY_ROWS TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE (‘Plusieurs chercheurs Trouvés.’);
--Utiliser un curseur explicite
ENDEND;
49
Gestion des exceptionsGestion des exceptions
• Exceptions prédéfinies (internes)
– Elles sont prédéfinies par Oracle
– Elles possèdent des noms significatifs
– Elles sont automatiquement provoquées
– Les exceptions les plus courantes sont les suivantes :
• Exception DUP_VAL_ON_INDEX (ORA-00001)
• Exception NO_DATA_FOUND (ORA-01403)
• Exception TOO_MANY_ROWS (ORA-01422)
• Exception VALUE_ERROR (ORA-06502)
• Exception INVALID_NUMBER (ORA-01722)
• Exception ZERO_DIVIDE (ORA-01476)
• Exception INVALID_CURSOR (ORA-01722)
50
Gestion des exceptionsGestion des exceptions
• Exception DUP_VAL_ON_INDEX (ORA-00001)
– Condition de provocation : lorsqu’une commande SQL tente d’insérer une valeur dupliquée dans une colonne définie avec un index unique (UNIQUE INDEX ou PRIMARY KEY)
– Exemple : cas d’insertion avec duplication de clé primaire
BEGIN
INSERT INTO Etudiant (NumETUD, NomETUD, FilETUD)
VALUES (10, ‘Dupont’, ‘Informatique’);
EXCEPTION
WHEN DUP_VAL_ON_INDEXDUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE (‘Insertion rejetée :NumETUD existe déjà.’);
END;
51
Gestion des exceptionsGestion des exceptions
• Exception NO_DATA_FOUND (ORA-01403)– Condition de provocation : lorsqu’un curseur implicite
d’interrogation ne retourne aucune ligne– Exemple : cas de recherche d’un étudiant inexistant
DECLARE
ETUDIANT_REC ETUDIANT%ROWTYPE;
V_NumETUD ETUDIANT.NumETUD%TYPE :=10;
BEGIN
SELECT * INTO ETUDIANT_REC
FROM ETUDIANT WHERE NumETUD= V_NumETUD;
EXECPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE (‘Etudiant 10 Inexistant’);
…
END;
– Remarque : L’absence d’un gestionnaire pour l’exception NO_DATA_FOUND entraîne une sortie du bloc avec échec
52
Gestion des exceptionsGestion des exceptions
• Exception TOO_MANY_ROWS (ORA-01422)– Condition de provocation : lorsqu’un curseur implicite
d’interrogation identifie plus qu’un seul n-uplet à retourner– Exemple : plusieurs étudiants ayant la même filière
DECLARE
V_NomETUD ETUDIANT.NomETUD%TYPE;
BEGIN
SELECT NomETUD
INTO V_NomETUD
FROM ETUDIANT WHERE FilETUD= ‘Informatique’;
EXECPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE (‘Plusieurs étudiants trouvés.’);
…
END;
53
Gestion des exceptionsGestion des exceptions
• Exception VALUE_ERROR (ORA-06502)
– Condition de provocation : en cas de troncature ou d’erreur de conversion
– Exemple : Affectation générant une troncature
DECLARE
V_message VARCHAR2 (10);
BEGIN
V_message :=‘Chaîne trop longue’;
EXCEPTION
WHEN VALUE_ERRORVALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE (‘Erreur de troncature’);
END;
54
Gestion des exceptionsGestion des exceptions
• Exception INVALID_NUMBER (ORA-01722)– Condition de provocation : lorsqu’une commande SQL spécifie
un nombre invalide
– ExempleDECLARE
V_mgr VARCHAR2 (4);
BEGIN
UPDATE EMP
SET MGR = V_mgr
WHERE empno=7902;
EXCEPTION
WHEN INVALID_NUMBER INVALID_NUMBER THEN
DBMS_OUTPUT.PUT_LINE (‘Exception INVALID_NUMBER’);
END;
55
Gestion des exceptionsGestion des exceptions• Exception ZERO_DIVIDE (ORA-01476)
– Condition de provocation : tentative de division par ZERO
– ExempleDECLARE
V_nombre1 int :=10;
V_nombre2 int :=5;
V_resultat number (5,3);
BEGIN
V_resultat := 100/(V_nombre1 -2* V_nombre2);
EXCEPTION
WHEN ZERO_DIVIDEZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE (‘Exception ZERO_DIVIDEException ZERO_DIVIDE’);
END;
56
Gestion des exceptionsGestion des exceptions
• Exception INVALID_CURSOR (ORA-01722)
– Condition de provocation : au moment ou un curseur fermé est référencé dans une opération de lecture (FETCH), de fermeture (CLOSE) ou via des attributs (%FOUND, %NOTFOUND, %ROWCOUNT)
57
Gestion des exceptionsGestion des exceptions
• Exceptions génériques OTHERS— Condition de provocation : toute exception non gérée— WHEN OTHERS doit être la dernière
• Les fonctions SQLCODE et SQLERRMQuand une exception se produit, on peut récupérer son code et son
message d’erreur. Ceci est particulièrement intéressant pour les exceptions manipulées avec OTHERS
SQLCODE SQLCODE : Renvoie un entier représentant le n° de l’erreur (99999) qui a provoquée l’exception et Zéro sinon (pas d’erreur)
SQLERRM :SQLERRM : Renvoie un texte composé du numéro de l’erreur et d’un message complet associé à l’exception rencontrée, de la forme (ORA-XXXX: texte explicatif)
58
Gestion des exceptionsGestion des exceptions
• Exceptions de l’utilisateur
Toute exception utilisateur doit être déclarée et explicitement provoquée pour la capturer selon les étapes suivantes :
– Déclaration : syntaxe
Nom_exception EXCEPTION;
– Déclenchement : syntaxe
RAISE nom_exception;
– Capture : syntaxe
WHEN nom_exception THEN instructions;
59
Gestion des exceptionsGestion des exceptions!!• Exceptions de l’utilisateur
– Exemple DECLARE
E_Rupt_Stk EXCEPTION;--déclarationE_Rupt_Stk EXCEPTION;--déclaration
V_Qtestk Art.Qtestk%TYPE;
V_Qtestksec Art.Qtestksec%TYPE;
BEGIN
SELECT Qtestk, Qtestksec
INTO V_Qtestk, V_Qtestksec
FROM Stock WHERE Numart=1234;
--suite
IF V_Qtestk <V_Qtestsec THEN
RAISE E_Rupt_Stk; --provocationRAISE E_Rupt_Stk; --provocation
END IF;
--suite
EXCEPTION
WHEN E_Rupt_Stk THEN --gestionnaireWHEN E_Rupt_Stk THEN --gestionnaire
DBMS_OUTPUT.PUT_LINE (‘Stock insuffisant,article 1234’);
END;
60
Gestion des exceptionsGestion des exceptions• Exceptions internes non prédéfinies
Les exceptions internes non prédéfinies peuvent être piégées par la clause générique WHEN OTHERS.
PL/SQL offre une souplesse additionnelle au développeur en permettant de nommer des erreurs internes ce qui permettra de les distinguer individuellement et de les utiliser comme les exceptions prédéfinies.
Les erreurs internes pour lesquelles le développeur assigne un nom sont dites des exceptions Non Prédéfinies
• Etapes de capture d’une Exception Non Prédéfinie1. Déclarer l’exception
Nom_exception EXCEPTION ;
2. Associer l’exception déclarée à un numéro d’erreur interne
PRAGMA EXCEPTION_INIT (nom_exception, no_err_interne) ;
3. Prévoir un gestionnaire d’exception1. Idem ;
• Remarque : les exceptions internes :– sont provoquées implicitement– peuvent être provoquées explicitement (RAISE nom_except).
61
• Exemple
DECLARE Privilege_Insuffisant EXCEPTION; PRAGMA EXCEPTION_INIT(Privilege_Insuffisant, -1031); /*Oracle return error number -1031 if, for example, you try to
UPDATE a table for which you have only SELECT privileges */BEGIN ...…EXCEPTION WHEN Privilege_Insuffisant THEN-- Gestionnaire d’exception END;
Gestion des exceptionsGestion des exceptions
62
Propagation des exceptionsPropagation des exceptions
• Principe
Lorsqu’un sous-bloc traite une exception, il se termine normalement (succès) et le contrôle reprend dans le bloc parent immédiatement après l’instruction END du sous-bloc. Lorsqu’une exception n’est pas gérée dans son bloc, elle se transmet au bloc parent : cette transmission de l’erreur entre blocs est appelée propagation.
63
Propagation des exceptionsPropagation des exceptions• Exceptions de la section exécutable
BEGIN
……
-- Exception X déclenché ici
EXCEPTION – Aucun gestionnaire pour l’exception X
END;
Exception
-- il y a un gestionnaire pour l’exception x
END;
Propagation
64
Propagation des exceptionsPropagation des exceptions
• Avantages de la propagation
– Gérer les exceptions spécifiques à certaines instructions au niveau de leur bloc pour assurer la sûreté de fonctionnement de ces blocs
– Ceci permettra également d’éviter une reproduction en cascade de l’erreur
65
Propagation des exceptionsPropagation des exceptions• Exceptions de la section DECLAREToute exception provoquée par l’initialisation d’une variable lors de sa
déclaration se propage et ne peut être traitée dans son bloc même si un gestionnaire d’exception approprié (ou OTHERS) y est prévu.
DECLARE
V_NO NUMBER (3):=‘ABC’
BEGIN
….
EXCEPTION
WHEN OTHERS THEN
…
END;
Affectation illégale, provoque l’exception VALUE_ERROR
Ne peut être exécutée pour l’exception VALUE_ERROR
Bloc en échec
Exception VALUE_ERROR reconduite
66
Propagation des exceptionsPropagation des exceptions
• Exceptions de la section EXCEPTIONUn gestionnaire d’exception peut provoquer une autre exception
implicitement (interne) ou explicitement (RAISE), auxquels cas, l’exception se propage et ne peut être capturée dans le même bloc : le principe est d’activer un seul gestionnaire d’exception à la fois dans un bloc
• ExempleEXCEPTION
WHEN INVALID_NUMBER THENINSERT INTO …--peut causer DUP_VAL_ON_INDEX
WHEN DUP_VAL_ON_INDEX THEN…
END;
67
Propagation des exceptionsPropagation des exceptions
• Gestion locale et reproduction d’une exceptionParfois, on a besoin de traiter localement une exception provoquée
puis de la transmettre au bloc parent. La commande RAISE permet cette reproduction de l’erreur
EXCEPTION WHEN E_STOCK_INSUFFISANT THEN
-- Gérer localement l’erreur RAISE; --Reproduit l’exception courante . . . .END; -- fin sous blocEXCEPTION WHEN E_STOCK_INSUFFISANT THEN
-- Gérer l’erreur différemment . . . .END ;
68
Envoie de message d’erreur avec Envoie de message d’erreur avec RAISE_APPLICATION_ERRORRAISE_APPLICATION_ERROR
• RAISE_APPLICATION_ERROR est une procédure du package DBMS_STANDARD, utile pour produire des messages d’erreur applicatifs spécifiques à l’environnement appelant (SQL*Plus, s/p PL/SQL, application client). L’exécution de RAISE_APPLICATION_ERRORRAISE_APPLICATION_ERROR reproduit l’erreur et annule la transaction en cours. Elle est utilisable dans les sections BEGIN et EXCEPTION.
• Syntaxe RAISE_APPLICATION_ERROR (no_erreur, message_erreur);
no-erreur : doit être compris entre -20000 et -20999
message-erreur : texte de 512 caractères maximum
DECLARE
E_mon-Exception EXCEPTION ;
BEGIN
….
Raise E_mon-Exception;
….
EXCEPTION
WHEN E_mon-Exception THEN
RAISE_APPLICATION_ERROR(-20000, ‘message applicatif’);
END ;
69
Traitement des exceptions dans les autres Traitement des exceptions dans les autres environnementsenvironnements
• Il est possible de propager une exception vers l’environnement appelant au lieu de la traiter dans le bloc PL/SQL courant
• Chaque environnement possède sa propre façon de traiter les erreurs.
Environnement appelant
Possibilité de traitement des Exceptions
SQL* Plus ou Procedure Builder
Le libellé et le numéro des exceptions non traitées sont affichés à l’écran.
Developer/2000 Forms Le libellé et le numéro des exceptions non traitées sont accessibles par un trigger au moyen des fonctions ERROR_CODE et ERROR_TEXT.
Précompilateur C Le numéro des exceptions non traitées est accessibles via la structure SQLCA.
70
PlanPlan
Chapitre 4 : Les sous programmes, les sous programmes stockés et les packages
1. Les sous programmes2. Les sous programmes stockés3. Les packages
71
PlanPlan
Section 1 : Les sous programmes
1. Introduction2. Procédures
1. Modes de passage des paramètres2. Correspondance entre paramètres Actuels et
Formels3. Fonctions4. Exceptions dans les sous programmes et impact
sur les paramètres5. Appels Mutuels entre sous programmes
72
IntroductionIntroduction
• Bien que PL/SQL permet l’imbrication de blocs, cette pratique n’est pas recommandée pour deux raisons majeures :
– Réduit la lisibilité du code et rend plus difficile sa maintenance
– Les blocs emboîtés ne peuvent pas être appelés
• Les sous programmes
– PL/SQL offre la possibilité de travailler avec des sous programmes
– Un sous programme PL/SQL est un bloc nommé défini dans la section DECLARE et pouvant posséder des paramètres
– Il est réutilisable et facilite la maintenance des applications
73
ProcéduresProcédures• Syntaxe
PROCEDURE nom_procédure [(paramètre [, paramètre…])]{IS |AS}/*déclarations si nécessaires*/BEGIN--instructions exécutables[EXCEPTION--Section optionnelle de --Gestion des exceptions ]END [nom_procédure];
74
ProcéduresProcédures
• Exemple 1 (procédure sans paramètres)Enregistrer l’utilisateur courant et la date système dans la table Tab_Trace
(User_Uid, User_Name, User_Trace_Date)
DECLAREDECLARE….PROCEDUREPROCEDURE RECORD_Trace As BEGINBEGININSERT INTO Tab_Trace(User_Uid, User_Name, User_Trace_Date)VALUES (UID, USER, SYSDATE);EXCEPTIONEXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE (SUBSTR (SQLERRM, 1,80);ENDEND RECORD_Trace;-- autres déclarations
BEGIN –début bloc externe
RECORD_Trace;--appel procédure
END;--fin bloc externe
75
ProcéduresProcédures• Exemple 2 (procédure avec paramètres)Augmenter le salaire d’un employé identifié par EMPNO d’un montant donné
DECLARE….PROCEDUREPROCEDURE AUGMENTE_SAL (P_EMPNO EMP.EMPNO%TYPE, P_Montant
NUMBER) ISBEGINBEGINUPDATE EMPSET SAL =SAL+P_MontantWHERE EMPNO=P_EMPNOAND P_EMPNO NOT NULL;IF SQL%NOTFOUND THENDBMS_OUTPUT.PUT_LINE (‘MAJ Non Effectuée’);ELSEDBMS_OUTPUT.PUT_LINE (‘MAJ Réussie’);END IFEND AUGMENTE_SAL;-- autres déclarations
BEGIN –début bloc externeAUGMENTE_SAL (1234,1000);
END;--fin bloc externe
76
Modes de passage des paramètresModes de passage des paramètres
• Nom_param [IN|OUT|IN OUT ] Type [{:=|DEFAULT} expr]
Paramètre formel Paramètre d’appelIN (read-only) (1) Le sous PG reçoit une copieOUT (write-only) (2) Le sous PG fournit un résultatIN OUT (read-write) (1)&(2)
IN : Passage par valeurIN OUT : Passage par @ échange dans les deux sensOUT : Passage par @ pour retourner un résultat
77
Modes de passage des paramètresModes de passage des paramètres• Exemple
PROCEDUREPROCEDURE ModeParam (P_In IN NUMBER, P_Out OUT NUMBER, P_InOut NUMBER ) IS
V_Local NUMBER;BEGINBEGINP_In :=20; -- Affectation illégaleP_Out est null iciP_Out:=10; --légaleV_local :=P_Out; --illégale (Write only)P_InOut reçoit la valeur du param d’appelP_InOut :=P_InOut*3;ENDEND ModeParam;
78
Modes de passage des paramètresModes de passage des paramètres
• Teste de la procédure ModeParamDECLARE V_IN NUMBER := 1;V_OUT NUMBER :=2;V_INOUT NUMBER :=3;BEGINModeParam (V_IN, V_OUT, V_INOUT);DBMS_OUTPUT.PUT_LINE (‘V_IN : ‘ || V_IN);DBMS_OUTPUT.PUT_LINE (‘V_OUT : ‘ || V_OUT);DBMS_OUTPUT.PUT_LINE (‘V_INOUT : ‘ || V_INOUT);END;• Test du blocV_IN : 1V_OUT : 10V_INOUT : 9Procédure PL/SQL terminée avec succès
79
Correspondance entre paramètres Correspondance entre paramètres Actuels et FormelsActuels et Formels
• Correspondance par position– Fournir des paramètres d’appel dans le même ordre que celui
des paramètres de définition du sous PG– Les paramètres avec DEFAULT doivent être les derniers pour
pouvoir ne pas leur fournir de valeurs• Correspondance par nom
– Permet de ne pas respecter l’ordre de définition– Utile pour des sous PG avec un nombre important de
paramètres
PROCEDURE CorrespondanceParam (P_A VARCHAR2, P_B NUMBER, P_C BOOLEAN, P_D DATE) as
BEGINNULL;-- ou un traitement quelconqueEND CorrespondanceParam;
Par position : CorrespondanceParam (V_A, V_B, V_C, V_D);
Par nom : CorrespondanceParam (P_A=>V_A, P_B=>V_B, P_C=>V_C, P_D=>V_D)
80
FonctionsFonctionsUne fonction est un sous programme qui retourne une valeur
explicitement par la clause RETURN
• SYNTAXEFUNCTION nom_fonction [(paramètre [, paramètre…])]
RETURN type IS
/*déclarations si nécessaires*/
BEGINBEGIN
--instructions exécutables
--RETURN expression;
[EXCEPTIONEXCEPTION
--Gestionnaires d’exceptions]
ENDEND [nom_fonction] ;
• Le type de la fonction peut utiliser %TYPE
• Mêmes modes de passage de paramètres que les procédures
81
FonctionsFonctions• ExempleLa fonction Avg_Sal retourne le salaire moyen des chercheurs d’un
laboratoireDECLAREDECLARE
--déclarations si nécessairesV_Sal_Moy NUMBER (10,3);FUNCTIONFUNCTION Avg_Sal (P_Labno IN Chercheur.Labno%TYPE)RETURN NUMBER ISV_Avg_Sal Chercheur.Sal%TYPE;BEGINBEGINSELECT AVG(Sal) INTO V_Avg_Sal FROM ChercheurWHERE Labno=P_Labno;RETURN V_Avg_Sal;EXCEPTIONEXCEPTIONWHEN OTHERS THEN RAISE_APPLICATION_ERROR (-20110, SUBSTR(SQLERRM, 1, 80));ENDEND AVG_SAL;
--autres déclarations
BEGINBEGINV_Sal_Moy := Avg_Sal (10);-- Appel fonctionDBMS_OUTPUT.PUT_LINE (‘Salaire Moyen :’|| V_Sal_Moy);
ENDEND;--fin bloc externe
82
Exceptions dans les sous-programmes Exceptions dans les sous-programmes et Impact sur les paramètreset Impact sur les paramètres
• Dans un sous programme, une exception non traitée se reproduit selon le principe de propagation. En conséquence, les valeurs des paramètres formels ne seront pas récupérées dans les paramètres actuels
83
Exceptions dans les sous-programmes Exceptions dans les sous-programmes et Impact sur les paramètreset Impact sur les paramètres
• ExempleDECLARE
PROCEDURE Proc_RaiseError (p_Raise IN BOOLEAN , p_Parameter OUT NUMBER) ASMy_Exception Exception;BEGIN
p_Parameter := 10; IF p_Raise THEN RAISE My_Exception; END IF;
END Proc_RaiseError;v_Temp NUMBER := 5;
BEGIN DBMS_OUTPUT.PUT_LINE('V_temp avant Premier appel : '||v_temp); Proc_RaiseError(FALSE, v_Temp); DBMS_OUTPUT.PUT_LINE('V_temp Après appel en succès:'||v_temp); v_Temp := 8; DBMS_OUTPUT.PUT_LINE('V_temp Avant second appel : '||v_temp); Proc_RaiseError(TRUE, v_Temp);EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('V_temp après second appel:'||v_temp);END;
V_temp avant Premier appel : 5V_temp Après appel en succès : 10V_temp Avant second appel : 8V_temp après second appel : 8
84
Appels mutuels entre sous-Appels mutuels entre sous-programmesprogrammes
• Puisque les noms des sous programmes locaux sont des identificateurs, ils doivent être déclarés avant qu’ils soient utilisés. Par exemple, si un sous programme A appelle un sous programme B, B doit être déclaré avant A.
• Dans le cas de références mutuelles (A appelle B et B appelle A), il faut procéder à une déclaration en avant (forward) de l’un ou même des deux sous programmes selon l’utilisation
85
Appels mutuels entre sous-Appels mutuels entre sous-programmesprogrammes
• ExempleDECLARE v_TempVal BINARY_INTEGER := 5; -- Forward declaration of procedure B. PROCEDURE B(p_Counter IN OUT BINARY_INTEGER); PROCEDURE A(p_Counter IN OUT BINARY_INTEGER) IS BEGIN IF p_Counter > 0 THEN B(p_Counter); p_Counter := p_Counter - 1; END IF; END A; PROCEDURE B(p_Counter IN OUT BINARY_INTEGER) IS BEGIN p_Counter := p_Counter - 1; A(p_Counter); END B;BEGIN B(v_TempVal);END;
86
ExercicesExercices1. Ecrire un bloc PL/SQL qui appelle une fonction permettant de
sélectionner le plus grand numéro de département (DEPTNO) de la table DEPT et le stocke dans une variable SQL*Plus. Affichez le résultat à l’écran.
2. Ecrire un bloc PL/SQL qui appelle une procédure permettant de calculer le montant de la commission d’un employé donné, en fonction de son salaire. Si le salaire de l’employé est inférieur à 1OOO$, la commission vaut 10% du salaire. Si le salaire de l’employé est compris entre 1OOO$ et 1500$, la commission vaut 15% du salaire. Si le salaire de l’employé est supérieur à 15OO$, la commission vaut 20% du salaire. Si le salaire de l’employé est NULL, la commission vaut 0.
87
ExercicesExercices
DECLAREV_deptno_Max Number;
FUNCTION Max_Dept
RETURN Number IS
V_deptno NUMBER ;BEGINBEGIN
SELECT MAX (deptno)INTO V_deptnoFROM dept;Return V_deptno;
EXCEPTIONEXCEPTION
WHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE (‘aucun département enregistré’);ENDEND Max_Dept;
BEGINV_deptno_Max := Max_Dept ;
DBMS_OUTPUT.PUT_LINE (V_deptno_Max);END ;
88
ExercicesExercicesDECLARE PROCEDURE Calcul_Commission (P_empno emp.empno%TYPE) ISV_sal emp.sal%TYPE;V_comm emp.comm%TYPE; --peut être une variable globaleBEGINSELECT salINTO V_salFROM empWhere empno= P_empno;IF V_sal <1000 then V_comm:=V_sal*0.10;ELSIF V_sal Between 1000 and 1500 then V_comm:=V_sal*0.15;ELSIF V_sal > 1500 then V_comm:=V_sal*0.20;Else V_comm:=0;END IF;UPDATE empSET comm= V_comm;END Calcul_Commission;
BEGINCalcul_Commission (10);--appel de la procédure
END;
89
PlanPlan
• Section 2 : Les sous-programmes stockés
1. Introduction2. Procédures stockées3. Fonctions stockées4. Suppression de sous programmes stockés5. Dictionnaire de données et sous-programmes stockés6. Sous-programmes stockés versus sous programmes
locaux7. Sous-programmes et privilèges
90
IntroductionIntroduction
• La différence entre une procédure stockée et une procédure déclarée et utilisée dans un bloc anonyme est importante. Cette dernière est temporaire. C’est-à-dire qu’elle n’existe plus lorsque l’exécution du bloc anonyme est terminée
• Fonction ou Procédure stockée : sous programme (en tant qu’objet du dictionnaire Oracle) appelable par un utilisateur, directement ou indirectement
91
PROCEDURES StockéesPROCEDURES Stockées• Syntaxe
CREATE [OR REPLACE] ProcedureOù
Procedure : syntaxe habituelle de déclaration d’une procédureOR REPLACE : Remplace une procédure existante (suppression + re-création)
• Exemple
CREATE OR REPLACE PROCEDURECREATE OR REPLACE PROCEDURE raise_salary (p_empno emp.empno%TYPE, p_montant Number) IS
V_sal_actuel emp.sal%type;E_sal_NULL EXCEPTION;BEGINBEGINSELECT sal INTO v_sal_actuel FROM empWHERE empno = p_empno and p_empno is not null;IF v_sal_actuel IS NULL THENRAISE E_sal_NULL;ELSEUPDATE emp SET sal = sal + p_montantWHERE empno = p_empno;END IF;EXCEPTIONEXCEPTION WHEN NO_DATA_FOUND THEN ….. WHEN E_sal_NULL THEN -- instructions exécutablesENDEND raise_salaryraise_salary;
SQL> EXECUTE raise_salary(7788, 1000);
92
• Autres ExemplesCREATE OR REPLACE PROCEDURE Affiche_Sal_Moy CREATE OR REPLACE PROCEDURE Affiche_Sal_Moy
ISIS
V_avg_sal emp.sal%type ;V_avg_sal emp.sal%type ;
BEGINBEGIN
SELECT AVG(SAL) INTO v_avg_salSELECT AVG(SAL) INTO v_avg_sal FROMFROM EMPEMP ;;
DBMS_OUTPUT.PUT_LINE (concat (‘salaire Moyen : ‘,v_avg_sal);DBMS_OUTPUT.PUT_LINE (concat (‘salaire Moyen : ‘,v_avg_sal);
END;END;
SQL> EXECUTE affiche_sal_moy;
Salaire Moyen : 2073,21
CREATE OR REPLACE PROCEDURE Affiche_Sal_Moy_deptno (p_deptno dept.deptno%type) CREATE OR REPLACE PROCEDURE Affiche_Sal_Moy_deptno (p_deptno dept.deptno%type) ISIS
V_avg_sal emp.sal%type;V_avg_sal emp.sal%type;
BEGINBEGIN
SELECT AVG(SAL) INTO v_avg_salSELECT AVG(SAL) INTO v_avg_sal
FROM EMPFROM EMP
WHERE deptno = p_deptno AND p_deptno is not null;WHERE deptno = p_deptno AND p_deptno is not null;
DBMS_OUTPUT.PUT_LINE(‘salaire Moyen : ‘||v_avg_sal);DBMS_OUTPUT.PUT_LINE(‘salaire Moyen : ‘||v_avg_sal);
END;END;
SQL> EXECUTE Affiche_Sal_Moy_deptno(10);
salaire Moyen : 2916,67
PROCEDURES StockéesPROCEDURES Stockées
93
• Autres Exemples
CREATE OR REPLACE PROCEDURE get_emp_name (p_empno CREATE OR REPLACE PROCEDURE get_emp_name (p_empno ININ emp.empno emp.empno%type, p_ename %type, p_ename OUTOUT emp.ename%type) emp.ename%type)
ISIS
BEGIN BEGIN
SELECT SELECT ename ename INTO INTO p_enamep_ename
FROM FROM emp emp
WHERE WHERE empno = p_empno and p_empno is not null; empno = p_empno and p_empno is not null;
EXCEPTION EXCEPTION
WHEN NO_DATA_FOUND ThenWHEN NO_DATA_FOUND Then
DBMS_OUTPUT.PUT_LINE (‘Employé non Trouvé);DBMS_OUTPUT.PUT_LINE (‘Employé non Trouvé);
END get_emp_name;END get_emp_name;
SQL> EXECUTE get_emp_name (7788);
‘SCOTT’
PROCEDURES StockéesPROCEDURES Stockées!!
94
PROCEDURES StockéesPROCEDURES Stockées• CREATE PROCEDURE/FUNCTION
Compile et Stocke dans le Dictionnaire de Oracle
• La vue USER_ERRORS Affiche les erreurs de compilationSQL>SHOW ERRORS (commade SQL*Plus)
• La vue USER_OBJECTS Présente les objets-Oracle de chaque utilisateur
Name Null? Name Null? TypeType ------------------------------- -------- ------------------------ OBJECT_NAME VARCHAR2(128) OBJECT_ID NUMBER OBJECT_TYPE VARCHAR2(13) CREATED DATE STATUS VARCHAR2(7)
95
PROCEDURES StockéesPROCEDURES Stockées
• La vue USER_SOURCEPrésente le code source des sous programmes de chaque utilisateur Name Null? Name Null? TypeType ------------------------------- -------- ------------------------ NAME NOT NULL VARCHAR2(30) TYPE VARCHAR2(12) LINE NOT NULL NUMBER TEXT VARCHAR2(2000)
Possibilité de récupérer le texte source d’1 sous programme stockée :
SELECT line, TextFROM USER_SOURCEWHERE UPPER(NAME) = ‘nom_sous_prog’AND UPPER(TYPE) = ‘FUNCTION’ORDER BY line ;
96
PROCEDURES StockéesPROCEDURES Stockées
LINE TEXT
--------- ------------------------------------------------- 1 procedure get_emp_ename ( 2 p_empno in emp.empno%type, 3 p_ename OUT emp.ename%type) 4 is 5 begin 6 select ename 7 into p_ename 8 from emp 9 where empno = p_empno; 10 exception 11 when no_data_found then 12 dbms_output.put_line (‘employé non trouvé’); 13 end get_emp_name;
97
FONCTIONS StockéesFONCTIONS Stockées
Doit retourner une valeur. CREATE [OR REPLACE] fonction
Où fonction : syntaxe habituelle de déclaration d’une fonction
• Exemple 1
CREATE OR REPLACE FUNCTION LIB_JOUR (p_date DATE) RETURN VARCHAR2 IS
BEGIN RETURN (TO_CHAR(p_date, ‘Day’));EXCEPTION
When Others Then RETURN (NULL);END;
V_Lib_Jour := Lib_Jour(sysdate) ; -- appel de la fonction
98
FONCTIONS StockéesFONCTIONS Stockées• Exemple 2
CREATE OR REPLACE FUNCTION SECOND_SAL_DEPTNO (P_DEPTNO DEPT.DEPTNO%TYPE)
RETURN NUMBER IS/* DECLARATIONS */
CURSOR C_EMP (P_DEPTNO DEPT.DEPTNO%TYPE) IS SELECT SAL FROM EMP WHERE DEPTNO = P_DEPTNO and P_DEPTNO IS NOT NULL ORDER BY SAL;
V_SAL EMP.SAL%TYPE DEFAULT NULL;BEGINOPEN C_EMP(P_DEPTNO);LOOPFETCH C_EMP INTO V_SAL;EXIT WHEN C_EMP%NOTFOUND OR C_EMP%ROWCOUNT=2;END LOOP ;CLOSE C_EMP;
RETURN(V_SAL);END;
99
FONCTIONS StockéesFONCTIONS Stockées• Exemple Find_GradeFind_Grade qui retourne le grade de salaire d’un empno
s’il existe,–1 , sinon.
SQL> CREATE OR REPLACE function Find_Grade Find_Grade (p_empno in emp.empno%type) 2 RETURN number 3 is 4 v_grade salgrade.grade%type; 5 begin 6 select grade 7 into v_grade 8 from emp, salgrade 9 where empno = p_empno and p_empno is not null 10 and sal between losal and hisal; 11 return (v_grade); 12 exception 13 when no_data_found then 14 return(-1); 15 end Find_grade; SQL> var H_grade number;SQL> execute :H_grade := find_grade(7788);--appel de la fonction SQL> print H_grade H_GRADE --------- 4
100
Suppression de sous-programmes stockésSuppression de sous-programmes stockés
• Suppression d’une FONCTION/PROCEDUREDROP {PROCEDURE | FUNCTION} nompf ;
• Remarques1. CREATE et DROP : Commandes du LDD. !!!2. Modes de passage de paramètres identiques aux sous-
programmes non stockés.
101
Sous-programmes stockés versus sous-Sous-programmes stockés versus sous-programmes locauxprogrammes locaux
• Comparaison S/Pg. stocké et S/Pg. local
Sous-Programme Stocké Sous-Programme Local
Stocké sous forme compilée : immédiatement exécutable
Compilé avec son bloc parent.Si le bloc est exécuté plusieurs fois, le sous-programme sera compilé à chaque fois
Appelable par tout blocUtilisateur ayant le privilège Exécute sur le sous programme
Appelable uniquement dans le bloc parent
.. ..
102
Sous-programmes et privilegesSous-programmes et privileges
• Le privilège EXECUTE
Le propriétaire d’un s/pg stocké ou d’un package peut autoriser d’autres utilisateurs à s’en servir en leur accordant le privilège EXECUTE :
– GRANT EXECUTE ON {fonct | proc | pkg} TO username ;GRANT EXECUTE ON {fonct | proc | pkg} TO username ;
– SQL> SQL> GRANTGRANT EXECUTE ONEXECUTE ON Lib_Jour Lib_Jour TO BTO B;;
103
Sous-programmes et privilegesSous-programmes et privileges
• Privilège Execute : Cas d’objets de même nom
Si UserB possède une table de même nom T1. Lorsque UserB appelle UserA.SOUSPROG, quelle table sera modifiée ? C’est UserA.T1. Ce concept peut être énoncé par la règle :Règle : Un s/pg s’exécute sous les privilèges de son propriétaire.
104
Sous-programmes et RoleSous-programmes et Role
• Octroi de Privilèges sans ROLE
GRANT SELECT ON T2 TO UserB ;GRANT EXECUTE ON F TO UserB ;
permet à UserB de compiler avec succès son sous programme
105
Sous-programmes et RoleSous-programmes et Role
GREATE ROLE My_Role;GRANT SELECT ON T2 TO My_Role;GRANT EXECUTE ON F TO My_Role;GRANT My_Role TO UserB ;ne marchera pas ; d’où :Règle : Un s/pg s’exécute sous les privilèges attribués explicitement
(non à travers un ROLE) à son propriétaire
• Octroi de Privilège à travers un ROLE
106
PlanPlan
• Section 3 : Les packages
1. Structure d’un package2. Développement d’un package3. Le package DBMS_OUTPUT
107
Structure d’un packageStructure d’un package
Progiciel, réunit des fonctions et des procédures stockéesComposé de 2 parties :
• Package Specification : déclarativevariables globales, Exceptions, curseurs, typesprototypes de fonctions et des procédures
• Package Body :Description complète des fonctions/procédures globales§ BEGIN optionnelle
Déclaré en 2 phases :
108
Développement d’un packageDéveloppement d’un package
CREATE OR REPLACE PACKAGE pkg_nameAS -- Déclaration variables Globales, Exceptions, Curseurs
... -- Prototypes des Fonctions / Procédures Globales
prototype1;prototype2;...prototype n;
END [pkg_name];
109
Développement d’un packageDéveloppement d’un package
CREATE OR REPLACE PACKAGE BODY pkg_nameAS -- Corps des Fonctions / Procédures Globales BEGIN -- optionnelleCommandes à exécuter une seule fois suite à votre premier appel du package(initialisation de variables par des valeurs calculées)END [pkg_name];
110
Développement d’un packageDéveloppement d’un package
• Exemple CREATE OR REPLACE PACKAGE pkg_EMP AS
-- Déclaration variables Globales
G_nb_emp number(3);
G_nb_dept number(2);
G_nb_MANAGERS number(2);
G_avg_sal number;
-- Prototypes des Fonctions / Procédures Globales
function get_sal(p_empno in emp.empno%type) return emp.sal%type;
function get_grade(p_empno in emp.empno%type) return salgrade.grade%type;
function get_nb_emp_exceeds_avg_sal return number;
END pkg_EMP;
111
Développement d’un packageDéveloppement d’un packageCREATE OR REPLACE PACKAGE BODY Pkg_EMP IS
Function get_sal (p_empno in emp.empno%type) return emp.sal%type ISv_sal number ;BEGINIF p_empno is not null THEN
RAISE NO_DATA_FOUND; -- ou une exception utilisateurEND IF;select sal into v_sal
from empwhere empno =p_empno;
return v_sal;EXCEPTION when no_data_found then
raise_application_error ( -20000, ‘N° Employé ' || p_empno || ' Non Trouvé ou non renseigné');
return null;END get_sal;
112
Développement d’un packageDéveloppement d’un package
Function get_grade(p_empno in emp.empno%type) return salgrade.grade%type ISv_grade salgrade.grade%type;BEGIN
select grade into v_gradefrom emp , salgradewhere empno = p_empno and p_empno is not nulland sal between losal and hisal;
return v_grade;EXCEPTIONwhen no_data_found then
raise_application_error (-20001,'Grade de Salaire non trouvé pour Employé n° '||
p_empno); return null;END get_grade;
113
Développement d’un packageDéveloppement d’un package
Function get_nb_emp_exceeds_avg_sal Return number ISv_nb integer;BEGIN
select count(*) into v_nbfrom emp where sal > G_avg_sal;
return v_nb; -- utilisation var GlobaleEXCEPTION when no_data_found then
raise_application_error (-20001, 'Erreur '); return null;END get_nb_emp_exceeds_avg_sal ;
114
Développement d’un packageDéveloppement d’un package
BEGIN -- Initialiser la variable G_nb_emp
select count(*) into G_nb_empfrom emp;
-- Initialiser la variable G_nb_deptselect count(*) into G_nb_dept
from dept;-- Initialiser la variable G_nb_MANAGERS
select count(*) into G_nb_MANAGERSfrom empwhere upper(job) = 'MANAGER';
-- Initialiser la variable G_avg_salselect avg(sal) into G_avg_salfrom emp;
END pkg_EMP;
115
Développement d’un packageDéveloppement d’un package
• Intérêt des packages ./. à des sous programmes stockés :
• A la première utilisation du package, tous ses composants seront chargés en mémoire pour être directement disponibles, cette technique améliore les temps de réponse comparativement à l’usage de sous programmes stockés où chacun est cherché individuellement sur demande.
116
APPEL des s/pg d’un packageAPPEL des s/pg d’un package
Préfixer par le nom du package.ExempleExempleBEGINDBMS_OUTPUT.PUT_LINE (‘Salaire : ‘ ||PKg_emp.get_sal(7788) );END;ouExecute :h_sal := PKg_emp.get_sal(7788);Les variables globales du package peuvent être référencées :BEGINDBMS_OUTPUT.PUT_LINE ('G nb dept : ' ||PKg_emp.g_nb_dept );END;
117
PlanPlan
Chapitre 5 : Déclencheurs de BD
1. Introduction2. Utilité des déclencheurs3. Caractéristiques des déclencheurs4. Description d’un déclencheur5. Usage Des Prédicats de Déclencheurs :
INSERTING, UPDATING et DELETING 6. Gestion des déclencheurs
118
IntroductionIntroduction
• On appelle déclencheur (trigger) un traitement qui se déclenche suite à un événement
• Dans une programmation traditionnelle se faisait par un appel de sous programme
• Il existe deux types de déclencheurs :
– Des déclencheurs applicatifs crées et manipulés au niveau d’une application
– Des déclencheurs de bases de données stockés dans le dictionnaire de données du SGBD et associés à des événements sur des tables
119
Utilité des déclencheursUtilité des déclencheurs
• Les déclencheurs sont utiles pour plusieurs fins :
– Implémenter certaines règles de métier du SI de l’organisation (par exemple, MAJ du stock suite à une entrée, déclenchement d’une demande de réapprovisionnement à la suite d’une insuffisance de stock,…)
– Mettre en oeuvre une politique de sécurité complexe (par exemple, interdire des modifications des données à certains utilisateurs, garder trace mises à jour douteuses,….
120
Caractéristiques des déclencheursCaractéristiques des déclencheurs
• Les Triggers ressemblent aux sous programmes stockés sur les points suivants :
– Sont des blocs PL/SQL nommés
– Objets stockés dans Oracle sous forme de code source et p-code (exécutable)
• Mais ils en diffèrent sur les points suivants :
– Liés à un événement : exécution implicite
– Ne sont pas paramétrables
– Peuvent être désactivés
– Etc.
121
Description d’un déclencheurDescription d’un déclencheur
Elément Valeurs possibles
Explication
Nom_Trigger Choisie par le développeur
Identifiant du déclencheur
Nom_Table Nom d’une table La table sur laquelle le trigger est défini. Si l’événement est exécuté sur cette table, le trigger sera déclenché
Evénement INSERT ou UPDATE, ou DELETE
Evénement déclenchant l’exécution du trigger : commande LMD ou une combinaison utilisant OR
Séquencement BEFORE ou AFTER Caractérise le séquencement du déclencheur (timing) par rapport à son événement. Avec BEFORE (AFTER), le déclencheur est lancé avant (après) que l’événement déclenchant ne soit exécuté.
• Eléments de description
Un trigger est défini à travers les éléments suivants :
122
Description d’un déclencheurDescription d’un déclencheur
• Niveaux de déclenchement
Il existe deux niveaux de déclenchement :
1. Niveau instruction (statement level trigger)
2. Niveau ligne (row level trigger)
(1) : un déclencheur de niveau 1 s’exécute une seule fois
Création : la commande de création d’un déclencheur permet sa compilation et son stockage dans la métabase. Après une compilation correcte, le déclencheur est crée à l’état actif (ENABLE)
123
Description d’un déclencheurDescription d’un déclencheur
• Création d’un TRIGGER
CREATE [ OR REPLACE ] TRIGGER nom_Trigger
{ BEFORE | AFTER } événement
ON nom_Table
DECLARE
-- déclarations variables, curseurs, records,…
BEGIN
- - traitement
EXCEPTION
- - Gestionnaires d’exceptions
END [nom_Trigger ];
124
Description d’un déclencheurDescription d’un déclencheur• Déclencheur de Niveau ligne (row level trigger)
Un déclencheur de ligne s’exécute une fois pour chaque n-uplet affecté par l’événement déclanchant.
• Création d’un TRIGGERCREATE [OR REPLACE] TRIGGER nom_Trigger
{ BEFORE | AFTER } événement
ON nom_Table
FOR EACH ROW [WHEN condition]
[REFERINCING {[old [AS] nom_old] | New [AS] nom_new]}]
DECLARE
-- déclarations variables, curseurs, records,…
BEGIN
- - traitement
EXCEPTION
- - Gestionnaires d’exceptions
END [nom_Trigger ];
125
Description d’un déclencheurDescription d’un déclencheur
For each row Clause optionnelle, si utilisée le déclencheur spécifié sera de niveau ligne. Autrement il est de niveau instruction
Condition Option de la clause For each Row (valable uniquement pour les triggers de niveau ligne), introduit une condition selon laquelle le corps du déclencheur peut être exécuté ou simplement abandonné
Referencing Permet de changer les noms standards des pseudo records OLD et NEW par de nouveaux noms nom_old et nom_new
126
Description d’un déclencheurDescription d’un déclencheur
• Exemples1. Ecrire un trigger de BD qui affiche un message à la suite de la
suppression d’un dept
Choix des composants du trigger
Nom Evénement Séquencement Niveau Table
TRG_DEL_DEPT DELETE BEFORE(ou AFTER)
Ligne DEPT
127
Description d’un déclencheurDescription d’un déclencheur
CREATE OR REPLACE TRIGGER TRG_DEL_DEPT
AFTER DELETE -- ou bien BEFORE
ON DEPT
FOR EACH ROW -- de niveau n-uplet
BEGIN
DBMS_OUTPUT.PUT_LINE(‘TRG0 : Dépt supprimé’);
END TRG_DEL_DEPT;
Test :
SQL> delete from dept
where deptno NOT IN (Select deptno from emp);
TRG0 : Dépt supprimé
1 ligne(s) supprimée(s).
128
Description d’un déclencheurDescription d’un déclencheur• Remarques
– Comme il s’agit d’un ‘Row level Trigger’ le corps du déclencheur sera exécuté avec chaque n-uplet affecté par l’événement déclenchant (DELETE). Si aucune ligne n’est affectée alors aucun message affiché
– Utiliser un trigger de niveau instruction pour exécuter le corps du déclencheur une seule fois quelque soit le nombre de lignes affectées (même 0). Si aucune ligne n’est affectée alors le message sera affiché.
129
Description d’un déclencheurDescription d’un déclencheur
• Exemple de Trigger de niveau instruction CREATE OR REPLACE TRIGGER TRG_DEL_DEPT_Niv_Ins
AFTER DELETE -- ou bien BEFORE
ON DEPT
BEGIN
DBMS_OUTPUT.Put_Line(‘TRG_DEL_DEPT_Niv_Ins Déclenché’);
END TRG_DEL_DEPT_Niv_Ins;
Test du trigger :
SQL> delete from dept where
deptno is null;
TRG_DEL_DEPT_Niv_Ins Déclenché
0 ligne(s) supprimée(s).
130
Description d’un déclencheurDescription d’un déclencheur
• Les Pseudo-records : old et : new
• Un trigger de niveau ligne se déclenche une fois avec chaque n-uplet traité par l’événement du trigger
• A l’intérieur d’un trigger de niveau ligne, on a souvent besoin d’accéder aux données du n-uplet en cours de manipulation. PL/SQL le permet par le biais des 2 pseudo-records :old et :new de même structure que la table sur laquelle le trigger est défini.
131
Description d’un déclencheurDescription d’un déclencheur
• Non valables pour les triggers de niveau instruction.
• Utilisables dans les curseurs implicites et explicites.
Evénement OLD NEW
INSERT Tous les champs sont nulls Valeurs à insérer en provenance de la commande INSERT qui a déclenché le trigger
UPDATE Valeurs originales du n-uplet avant UPDATE
Nouvelles valeurs après UPDATE
DELETE Valeurs Originales du n-uplet avant DELETE
132
Description d’un déclencheurDescription d’un déclencheur
• Exemple 1. Ecrire un trigger qui enregistre dans la table ARCHIVE_DEPT
chaque dept. Supprimé.
CREATE OR REPLACE TRIGGER TRG_Archive_Dept BEFORE DELETE ON DEPTFOR EACH ROWBEGIN INSERT INTO ARCHIVE_DEPT (DEPTNO, Dname, Loc)VALUES (:old.deptno, :old.dname, :old.loc);EXCEPTION
When OTHERS THENRAISE_APPLICATION_ERROR(-20001,’Erreur dans Trigger Before
Delete On DEPT’) ;END TRG_Archive_Dept;
Nom Evénement Séquencement Niveau Table
TRG_Archive_Dept DELETE BEFORE Ligne DEPT
133
Description d’un déclencheurDescription d’un déclencheur• ExempleEcrire un trigger de BD qui à la suite d’une modification de salaire enregistre dans la
table AUDIT_SAL (Utilisateur, date_maj, Empno, anc_sal, nouv_sal)
CREATE OR REPLACE TRIGGER TRG_Audit_Sal AFTER UPDATE OF SAL ON EMPFOR EACH ROWBEGIN INSERT INTO AUDIT_SAL VALUES (user,sysdate, :old.empno, :old.sal, :new.sal);EXCEPTION
When others then null;END ;
SQL> update emp set sal= sal + 1000 where deptno= 10;
3 ligne(s) mise(s) à jour.
SQL> select * from audit_sal;
UTILISATE DATEMAJ EMPNO ANC_SAL NOUV_SAL--------- -------- --------- --------- ---------SCOTT 18/04/02 7782 2450 3450SCOTT 18/04/02 7839 5000 6000SCOTT 18/04/02 7934 1300 2300
134
Description d’un déclencheurDescription d’un déclencheur• La clause WHEN «condition»
Cette clause est valide uniquement pour les row-level triggers. Si utilisée, la condition sera évaluée pour chaque ligne affectée par l’événement du trigger, et le corps du trigger n’est exécuté pour cette ligne que si l’expression logique est vraie.
• Les pseudo-record old et new sont autorisés dans la clause WHEN mais sans le préfixe (:)
135
Description d’un déclencheurDescription d’un déclencheur• Exemple 1
CREATE OR REPLACE TRIGGER TRG_B_IU_EMP BEFORE INSERT OR UPDATE of deptno ON EMPFOR EACH ROW WHEN (new.deptno = 40)BEGIN
Update dept Set nb_emp = nvl(Nb_emp,0) + 1Where deptno = :new.deptno;
END TRG_B_U_EMP;
Test du trigger :SQL> update emp
set deptno = 40 where deptno = 10;
3 ligne(s) mise(s) à jour.SQL> select * from dept where deptno = 40; DEPTNO DNAME LOC NB_EMP--------- -------------- ------------- --------- 40 OPERATIONS BOSTON 3
136
Description d’un déclencheurDescription d’un déclencheur• Exemple 2Modification systématique de la commission pour la fonction SALESMAN :
Augmenter leur commission au prorata de leur augmentation du salaire.CREATE OR REPLACE TRIGGER TRG_B_Usal BEFORE UPDATE OF SAL ON EMPFOR EACH ROW WHEN (upper(new.job) = ‘SALESMAN’)BEGIN IF nvl(:old.sal,0)>0 THEN :new.comm := :old.comm *(:new.sal/:old.sal);END IF;END TRG_B_Usal;
Test du trigger :EMPNO SAL COMM JOB--------- --------- ---------- ---------7499 1600 300 SALESMAN
UPDATE EMPSET SAL = SAL+320 -- 320 = 20% de salWHERE EMPNO = 7499;
EMPNO SAL COMM--------- --------- --------- 7499 1760 360
137
Description d’un déclencheurDescription d’un déclencheur• Remarques :
– La clause WHEN condition équivaut un test portant sur tout le corps du trigger
– Ainsi, TRG_B_UI_EMP peut être réécrit comme suit :
CREATE OR REPLACE TRIGGER TRG_B_IU_EMP BEFORE INSERT OR UPDATE of deptno ON EMPFOR EACH ROW BEGIN IF (:new.deptno = 40) THEN
/* corps du trigger */END IF;END TRG_B_U_EMP;
138
Description d’un déclencheurDescription d’un déclencheur• ExempleInterdire les modifications sur la table EMP en dehors des
horaires de travail supposés entre 8h à 17h.
CREATE OR REPLACE TRIGGER TRG_Grant_Emp BEFORE UPDATE ON EMPDECLARE
E_ACCES_DENIED EXCEPTION ;BEGIN If (to_number (to_char(sysdate,’HH24’) ) NOT between 8 and 17) THENRAISE E_ACCES_DENIED ;End IF ;EXCEPTIONWHEN E_ACCES_DENIED THENRAISE_APPLICATION_ERROR (-20001, ’Accès interdit en dehors des
horaires de travail’) ;END;
139
Usage Des Prédicats de Déclencheurs : Usage Des Prédicats de Déclencheurs : INSERTING, UPDATING, et DELETINGINSERTING, UPDATING, et DELETING
• Si l’événement d’un trigger utilise OR, le trigger se déclenchera alors par l’une ou l’autre des commandes LMD. Les trois prédicats ci-dessus permettent de déterminer laquelle des opérations a déclenchée le trigger. On peut alors tester dans le corps du trigger :
CREATE OR REPLACE TRIGGER TRG_ARV_DEPT BEFORE INSERT OR DELETE OR UPDATE ON DEPT FOR EACH ROWDECLARE v_Operation CHAR(1);BEGIN IF INSERTING THEN v_Operation:= 'I'; ELSIF UPDATING THEN v_Operation:= 'U'; ELSE v_Operation:= 'D'; END IF;INSERT INTO Arch_dept (operation, changed_by, timestamp, old_deptno, old_dname,
old_loc,new_deptno, new_dname,new_loc) VALUES (v_Operation, USER, SYSDATE, :old.deptno, :old.dname, :old.loc, :new.deptno, :new.dname, :new.loc);
END TRG_ARV_DEPT;
140
Usage Des Prédicats de Déclencheurs : Usage Des Prédicats de Déclencheurs : INSERTING, UPDATING, et DELETINGINSERTING, UPDATING, et DELETING
Test du Trigger :
insert into dept values (70,'gestion','FSEGS');update dept set dname = upper (dname)where deptno =70;select * from arch_dept;
C CHANGED_ TIMESTAM OLD_DEPTNO OLD_DNAME OLD_LOC NEW_DEPTNO NEW_DNAME NEW_LOC- -------- -------- ---------- ------------ ---------- ---------- ------------ ---------I SCOTT 18/04/02 70 gestion FSEGSU SCOTT 18/04/02 70 gestion FSEGS 70 GESTION FSEGSD SCOTT 18/04/02 70 GESTION FSEGS
141
Gestion des déclencheursGestion des déclencheurs• DROP TRIGGER triggerName ;
• Activation / Désactivation d’un trigger
Parfois il est préférable de désactiver un trigger que de le supprimer en vue de le réactiver ultérieurement.
• ALTER TRIGGER triggerName { ENABLE |DISABLE } ;
A la création un trigger est activé
Un trigger désactivé (DISABLE) continue à exister dans le DD.
• Affichage des erreurs de compilation
SQL>SHOW ERRORS
• Activation/Désactivation de Tous les Triggers d’une table
ALTER TABLE TableName { ENABLE | DISABLE } ALL TRIGGERS ;
142
ConclusionConclusion• Lorsqu’un trigger échoue (exception non traitée ou
explicitement reconduite avec RAISE_APPLICATION_ERROR sa commande événement Echoue de même.
• ExempleEcrire un déclencheur qui Interdit la suppression d’employés.
CREATE OR REPLACE TRIGGER TRG_DENY_DELETE_EMP BEFORE DELETE ON EMPDECLARE
E_DELETE_DENIED EXCEPTION ;BEGIN
RAISE E_DELETE_DENIED;EXCEPTIONWHEN E_DELETE_DENIED THENRAISE_APPLICATION_ERROR (-20002, 'Suppression d''Employées Non Autorisée') ;END;
143
Merci de Votre attention