Vous êtes sur la page 1sur 18

Systèmes de Gestion de BD

Elaboré par Mme Emna HKIRI


Emna.hkiri@gmail.com

FSM de Monastir 2020-2021


2ème année Licence Fondamentale en Informatique

Plan du cours

Cours 1 : Vues et Index


Cours 2 : PL/SQL-les curseurs
Cours 3: Gestion des exceptions
Cours 4: Les sous programmes stockés et les packages
Cours 5: Les déclencheurs
Cours 6: Concurrence et contrôle des accès

1
Chapitre 2 : Le Langage PL/SQL

Chapitre2: Le Langage PL/SQL

1. Introduction
2. Les types de curseurs
3. Les curseurs implicites
4. Les curseurs explicites
5. Les curseurs paramétrés

2
Introduction

 Pour traiter une commande SQL, PL/SQL ouvre une zone de contexte pour
exécuter la commande et stocker les informations.

 Le curseur permet de nommer cette zone de contexte, d'accéder aux


informations et éventuellement de contrôler le traitement.

 Cette zone de contexte est une mémoire de taille fixe, utilisée par le noyau pour
analyser et interpréter tout ordre SQL.

 Les statuts d'exécution de l'ordre se trouvent dans le curseur.

Les types de curseurs


 On distingue deux types de curseurs :
 Les curseurs explicites
 Les curseurs implicites

Le curseur peut être implicite (pas déclaré par l’utilisateur) ou explicite


 Le curseur implicite
Il est généré et géré par le noyau pour les autres commandes SQL.

 Le curseur explicite
Il est créé et géré par l'utilisateur pour traiter un ordre Select qui ramène
plusieurs lignes. Le traitement du select se fera ligne par ligne
Les curseurs explicites servent à retourner plusieurs lignes avec un select

3
Les curseurs

 Le curseur peut être implicite (pas déclaré par l’utilisateur) ou explicite

 Les curseurs explicites servent à retourner plusieurs lignes avec un select

Les curseurs implicites


 Ils sont associés aux ordres SELECT, INSERT, DELETE et UPDATE.
Ils sont déclarés automatiquement par ORACLE lors de l'exécution
de la requête.
 Attention un seul enregistrement doit être résultat pour une requête SELECT
 Exemple d’un curseur implicite
 DECLARE
V_deptno NUMBER(2);
V_Loc VARCHAR2(15);
.....
BEGIN
SELECT deptno, loc
INTO v_deptno, v_loc  Obligatoire
FROM dept
WHERE upper(dname) = ‘TOUNSI’;
… END;/
8

4
Attributs du curseur implicite
 PL/SQL fournit des attributs permettant d’évaluer le résultat d’un curseur
implicite
 Ces attributs sont utilisables comme des fonctions dans les ordres
PL/SQL MAIS PAS dans les commandes SQL.
Attribut Description
SQL%ROWCOUNT Entier : Nombre de lignes affectées par le dernier ordre
SQL
Booléen : TRUE si le dernier ordre SQL affecte au moins
SQL%FOUND une ligne
SQL%NOTFOUND Booléen : TRUE si le dernier ordre SQL n’affecte aucune
ligne

SQL%ISOPEN Toujours FALSE pour les curseurs implicites.

Exemple

DECLARE
V_Rows_Updated NUMBER;

BEGIN

UPDATE EMP
SET sal = sal*1.1
WHERE deptno = 10;
V_Rows_Updated := SQL%ROWCOUNT;

INSERT INTO History_Tab


Values (‘Dept 10’, V_Rows_Updated, SYSDATE);

END ;
10

5
Application1: les curseurs implicites
 Soit la relation :

 EMPLOYE(ID, NOM, DEPARTEMENT, AGE, SALAIRE).

 Écrivez un bloc PLSQL qui effectue une augmentation de 200 euros du salaire
des employés du département 'Commercial' et qui utilise le curseur implicite pour
afficher le nombre d’employés affectés par ce changement.

11

Corrigé
 DECLARE
 total NUMBER(2);
 BEGIN
 UPDATE EMPLOYE
 SET salaire = salaire + 200
 WHERE DEPARTEMENT = 'Commercial';
 IF SQL%NOTFOUND THEN
 DBMS_OUTPUT.PUT_LINE('Aucun salaire augmenté');
 ELSIF SQL%FOUND THEN
 total := SQL%ROWCOUNT;
 DBMS_OUTPUT.PUT_LINE( total || ' salaires ont été augmentés ');
 END IF;
 END;

12

6
Application 2: les curseurs implicites
 Ecrivez un script récupérant le client de clé primaire la plus élevée, et ajoutant ce
client dans la table PERSONNE(num_pers, nom, ville, daten)
 Declare
 Row client%rowtype;
 begin
select * into Row from client where num_client= (SELECT
MAX(num_client) FROM CLIENT) ;

insert into personne(num_pers, nom, ville, daten) values (row.num_client,


row.nom, row.ville, row.daten);
End ;

13

Curseur explicite
 Un curseur permet de "récupérer" un ensemble de
tuples, résultat d'une requête d'interrogation sur la base de données et de le manipuler de
manière procédurale, i.e. en balayant un par un les tuples/enregistrements.
 Le rôle des curseurs est d'établir la transition entre l'univers BD et celui des langages
procéduraux classiques.

 Définition: Un curseur est défini dans la partie déclarative d'un bloc PL/SQL par une
requête d'interrogation en SQL (sa structure correspond aux attributs du SELECT),

 Exemple:
CURSOR C_pilote IS
SELECT num_pil, nom_pil FROM pilote
ORDER BY num_pil, nom_pil ;
14

7
Le curseur explicite
 Pour traiter une requête qui retourne plusieurs lignes, l'utilisateur doit définir un curseur
qui lui permet d’extraire la totalité des lignes sélectionnées.

 L’utilisation d'un curseur pour traiter un ordre Select ramenant plusieurs lignes, nécessite
4 étapes:

1. Déclaration du curseur
2. Ouverture du curseur
3. Traitement des lignes
4. Fermeture du curseur.

15

La déclaration d'un curseur

 La déclaration du curseur permet de stocker l'ordre Select dans le curseur...


 Le curseur se définit dans la partie DECALRE d'un bloc PL/SQL.
Cursor nomcurseur [(nompararn type [,nomparam type, .. )]
IS Commande_SELECT

 Exemple :
Declare
Cursor DEPT_10 is
select ename, sal
from emp
where depno = 10;

16

8
L'ouverture et la fermeture d’un curseur

 L'étape d'ouverture permet d'effectuer:


1. l'allocation mémoire du curseur,
2. l'analyse sémantique et syntaxique de l'ordre
3. le positionnement de verrous éventuels (si select for update.. )
 L'étape de fermeture permet de libérer la place mémoire réservé.

 La syntaxe :
OPEN nomcurseur [(nomparam1[,nomparam2 , . .)]
/* traitement des lignes */
CLOSE nomcurseur
 Exemple :
Begin

OPEN DEPT_10
/* traitement des lignes*/
CLOSE DEPT_10

17

Le traitement des lignes


 Il faut traiter les lignes une par une et renseigner les variables réceptrices définies
dans la partie DECLARE du bloc.

 La syntaxe :Dans la partie traitement du bloc.PL/Sql, il faut commencer par


ouvrir le curseur puis

FETCH nomcurseur
INTO nomvariable |nomrecord

 L’ordre fetch ne ramène qu’une seule ligne à la fois.

 Pour traiter n lignes, il faut prévoir une boucle

18

9
Exemple récapitulatif
Declare
Cursor DEPT_10 is select ename, sal from emp where depno = 10;
Vnom emp.name%TYPE ;
Vsalaire emp.sal%TYPE ;
Begin
OPEN DEPT_10;
LOOP
FETCH DEPT10 into vnom, vsalaire ;
--Traitement ligne
END LOOP ;

CLOSE DEPT_10;
End;
19

Les attributs d’un curseur


 Les attributs d’un curseur nous fournissent des informations sur l’exécution d’un
ordre. Ils sont conservés par PL/SQL après l’exécution du curseur (implicite ou
explicite)
 Ces attributs permettent de tester directement le résultat de l’exécution. Ils sont
résumés dans le tableau suivant :

Curseurs implicites Curseurs explicites


Sql%Found Nomcurseur%Found
Sql%Notfound Nomcurseur %Notfound
Sql%Isopen Nomcurseur %Isopen
Sql%Rowcount Nomcurseur %Rowcount
Sql%Rowtype Nomcurseur %Rowtype
20

10
Les attributs:%Found
 L'attribut %NotFound
 Cet attribut est de type booléen (vrai ou faux)
 Pour les curseurs implicites, cet attribut est vrai si les instructions insert, update,
delete traitent au moins une ligne.
 Pour les curseurs explicites, il est vrai si le fetch ramène au moins une ligne.

21

Les attributs %IsOpen & %RowCount


 L'attribut %IsOpen
Cet attribut est de type booléen soit vrai, soit faux.
Le curseur implicite est toujours faux car Oracle referme toujours les curseurs
qu'il ouvre après chaque utilisation.
Le curseur explicite est vrai si le curseur est ouvert.

 L'attribut %RowCount
Cet attribut est de type numérique. Le curseur implicite indique le nombre de
lignes traités par les ordres insert, update, delete.
Le curseur explicite est incrémenté à chaque ordre fetch, donc cet attribut traduit
la nième ligne traitée.

22

11
L'attribut %Rowtype
 Cet attribut permet la déclaration implicite d'une structure dont les éléments sont
d'un type identique aux colonnes ramenées par le curseur.

 Syntaxe : Dans la partie déclarative du bloc.


CURSOR nomcurseur IS ordre select;
nomrecord nomcurseur%Rowtype;

23

Les boucles et les curseurs


 L'objectif est de fournir au programmeur une structure simple et efficace pour
utiliser les structures de boucle et les curseurs.

 Elle simplifie la programmation car elle évite d’utiliser explicitement les


instructions OPEN, FETCH et CLOSE

 Elle déclare implicitement une variable de type « row » associée au


curseur.

24

12
Boucle FOR pour un curseur

 En cas d'utilisation LOOP on ne doit pas déclarer l'enregistrement ou variables


pour stocker les valeurs du curseur, pas besoin d’ouvrir, chercher et fermer le curseur.
Ces fonctions sont accomplies par la boucle FOR automatiquement.

Declare
Cursor nomcurseur is ordre_select ;
Begin
For nomrecord in nomcurseur Loop
/* traitement
End Loop;
End;

25

Boucle FOR pour un curseur : exemple


 Exemple:
 DECLARE
CURSOR dept_10 IS
Select ename,sal FROM emp WHERE deptno = 10
ORDER BY sal;
Variable de type
 dept_10%ROWTYPE
BEGIN
FOR nom_rec IN dept_10;
LOOP
IF salaire >2500 THEN
INSERT INTO resultat VALUES (nom_rec.ename, nom_rec.sal);
END IF;
END LOOP;
END;

26

13
APPLICATION
 Utilisez une boucle dans laquelle vous placerez une requête pour recopier les
 couples nom/prénom ville et daten de la table CLIENT dans la table personne.
 DECLARE
 cursor c is
 select * from client;
 Begin
 for row in c loop
 insert into personne (num_pers, nom, ville, daten) values
 (row.num_client, row.nom, row.ville, row.daten);
 end loop;
 end;/

27

Curseur et enregistrement : Syntaxe


 Nom_enregistrement nom_curseur%ROWTYPE;
 Exemple

DECLARE
CURSOR C1 IS
SELECT Cnom, Sal FROM chercheur WHERE Labno=10;

Rec1 C1%ROWTYPE;-- Rec1 de même schéma que C1


V_Cnom Chercheur.Cnom%TYPE;

BEGIN
OPEN C1;
LOOP
FETCH C1 INTO Rec1;
EXIT WHEN C1%NOTFOUND OR C1%ROWCOUNT >5;
END LOOP;
Close C1;
END;__ fin bloc

28

14
Application 3: les curseurs explicites
 On considère la table suivante:

 PILOTE(Matricule, Nom, Ville, Age, Salaire).

 Écrivez un programme PL/SQL qui calcule la moyenne des salaires des pilotes
dont l’âge est entre 30 et 40 ans.

29

Corrigé

DECLARE EXITWHEN (curseur1%NOTFOUND OR


CURSOR curseur1 IS SELECT salaire FROM curseur1%NOTFOUND IS NULL);
pilote sommeSalaires := sommeSalaires + salairePilote;
WHERE (Age >= 30 AND Age <=40); END LOOP;
salairePilote Pilote.Salaire%TYPE; moyenneSalaires := sommeSalaires /
sommeSalaires NUMBER(11,2) := 0; curseur1%ROWCOUNT;
moyenneSalaires NUMBER(11,2); CLOSE curseur1;
*******************
*******************
BEGIN DBMS_OUTPUT.PUT_LINE('Moyenne salaires
OPEN curseur1; (pilotes de 30 <E0> 40 ans) : ' ||
LOOP moyenneSalaires);
FETCH curseur1 INTO salairePilote; END;

30

15
Les curseurs paramétrés
 Définition: Un curseur paramétré est un curseur dont la requête contient des
variables dont les valeurs ne seront fixées qu’à l'ouverture.
 Déclaration: On précise la liste des noms et des type des paramètres entre
parenthèses après le nom du curseur :
CURSOR / nom / (/liste des paramètres /) IS
/requête/

 Par exemple, créons une requête qui, pour une mère donnée, nous donne la liste
des noms et prénoms de ses enfants :
CURSOR enfants ( numparent NUMBER) IS
SELECT
FROM PERSONNE
WHERE mere = numparent;
31

Ouverture d’un curseur paramétré


 On ouvre un curseur paramétré en passant en paramètres les valeurs des variables
:
OPEN / nom / ( / liste des paramètres / )

 Par exemple,
 OPEN enfants ( 1 ) ;

32

16
Boucle pour & curseurs paramétrés
 La boucle pour se charge de l'ouverture, il convient donc de placer les paramètres
dans l'entête de la boucle,

FOR / variable / IN / nom / ( / liste parametres / ) LOOP


/ instructions /
END LOOP ;

 Par exemple,
FOR e IN enfants ( 1 ) LOOP
DBMS_OUTPUT . PUT_LINE ( e . Nompers || ' ' || e . prenompers )
;
END LOOP ;

33

Remarques:
 Le seul ordre qui offre le choix entre curseur implicite et explicite est
le SELECT lorsqu’il ne ramène qu’une seule ligne.
 Il n’existe pas de curseur explicite de mise à jour
 Un curseur explicite ne peut être qu’un SELECT : utiliser systématiquement des
CE pour les ordres SELECT
 Inconvénients de CI par rapport au CE

34

17
Remarques:
 Curseurs implicites: Gérés automatiquement par le noyau dans les cas suivants:
• Une instruction SELECT exécutée sous SQL Developer
• Une instruction SELECT donnant une seule ligne de résultat sous
PL/SQL
• Les instructions UPDATE, INSERT et DELETE

 Curseurs explicites: Obligatoires pour un SELECT susceptible de produire plusieurs


lignes résultat
Quatre étapes :
1) Déclaration du curseur
2) Ouverture du curseur
3) Traitement des lignes du résultat
4) Fermeture du curseur

35

Récap
 Jusqu’à présent, nous avons vu comment récupérer le résultat de requêtes SQL
dans des variables PL/SQL lorsque ce résultat ne comporte au plus qu’une seule
ligne.
 Bien évidemment, cette situation est loin de représenter le cas général : les
requêtes renvoient très souvent un nombre important et non prévisible de lignes.
 Dans la plupart des langages procéduraux au dessus de SQL, on introduit une
notion de “curseur” pour récupérer (et exploiter) les résultats de requêtes.
 Un curseur est une variable dynamique qui prend pour valeur le résultat d’une
requête. La méthode pour utiliser un curseur est invariable. En premier lieu,
celui-ci doit être défini (dans la zone de déclaration).

36

18