UNIVERSITE INUKA
.
Troisième année, 2019-2020
Fichier et Base de données
-Le PL/SQL est un langage hybride : il utilise des ordres SQL pour accéder à la base de
données et des instructions PL/SQL pour contrôler les ordres SQL afin de traiter de façon
explicite des données.
-Le PL/SQL permet d'inclure la manipulation des données et les ordres SQL dans des blocs
structurés et dans des unités procédurales de code.
Les blocs PL/SQL sont transmis de l'application au moteur PL/SQL du serveur Oracle.
Ensuite, le moteur PL/SQL fractionne les instructions SQL du bloc en instructions
séparées, puis les envoie au moteur SQL.
Si les blocs sont fractionnés en instructions SQL, un seul transfert est nécessaire entre
l’application et le serveur Oracle ce qui permet de réduire le trafic réseau et
d’augmenter de façon significative les performances, en particulier en architecture
client/serveur.
Pour faciliter la lecture d’un bloc de code PL/SQL, chaque nouvelle instruction doit être
sur une nouvelle ligne et les différents niveaux des blocs doivent être mis en évidence
par des retraits.
[DECLARE
Déclaration de variables, constantes,
exceptions, curseurs]
BEGIN
Instructions SQL et PL/SQL
[EXCEPTION
Traitement des exceptions
(gestion des erreurs)]
END;
10 Prof: Andy PIERRE, M.Sc
2. Structure d’un bloc PL/SQL
Remarques :
-les sections DECLARE et EXCEPTION sont facultatives.
-Les commentaires :
-- : sur une ligne
/* */ : sur plusieurs lignes
Pour exécuter un bloc anonyme dans le buffer de SQL*Plus, il faut utiliser le caractère slash
"/". Si le bloc s'exécute avec succès, sans erreurs soulevées ni d'erreurs de compilation, le
message suivant s'affiche :
« PL/SQL procedure successfully completed »
END;
END;
Syntaxe :
nom_var BOOLEAN;
Exemple :
DECLARE
retour BOOLEAN;
BEGIN
END;
Syntaxe :
nom_var table.colonne%TYPE;
Exemple :
DECLARE
nom pilote.plnom%TYPE;
BEGIN
END;
Syntaxe :
nom_var table%ROWTYPE;
Exemple :
DECLARE
V_Pilote pilote%ROWTYPE;
BEGIN
END;
V_Pilote.Sal
Syntaxe :
nom_var2 nom_var1%TYPE;
Exemple :
DECLARE
ancien_sal NUMBER(5);
nouveau_sal ancien_sal%TYPE; --NUMBER(5);
BEGIN
END;
20 Prof: Andy PIERRE, M.Sc
3.Variables et Types de Données
Remarque
Deux avantages à utiliser la forme de déclaration faisant référence
au dictionnaire de données:
1. Ce n’est pas nécessaire de connaître le type de données de la
colonne en question
2. Si le type de données (de la colonne de la table) change ce n’est
plus nécessaire d’apporter les nouvelles modifications au niveau
des codes.
DECLARE
variable1_v NUMBER(3) := 10 ;
BEGIN
variable1_v (10)
DECLARE
variable1_v NUMBER(3) := 200 ;
BEGIN
variable1_v (200)
END;
variable1_v (10)
END;
24
24 Prof: Andy PIERRE, M.Sc
3.Variables et Types de données
3.2. Variables de l'environnement extérieur à PL/SQL
Exemple :
SQL> VARIABLE return_code NUMBER
SQL> VARIABLE return_msg VARCHAR2(30)
[ELSE traitement3;]
END IF;
•Dès que l’une des conditions est vraie, le traitement qui suit le
THEN est exécuté.
DECLARE
bonus NUMBER(6,2);
empid NUMBER(6) := 7369;
V_hiredate DATE;
BEGIN
SELECT hiredate INTO V_hiredate FROM emp WHERE empno = empid;
IF V_hiredate > TO_DATE('01-JAN-98') THEN
bonus := 500;
ELSIF V_hiredate > TO_DATE('01-JAN-96') THEN
bonus := 1000;
ELSE
bonus := 1500;
END IF;
DBMS_OUTPUT.PUT_LINE(‘Le Bonus employe No: ' || empid || ' is: ' || bonus );
END;
/
33 Prof: Andy PIERRE, M.Sc
4.Traitements des données en PL/SQL
4.2 Traitement répétitif: boucle de base LOOP
Exécution d’un traitement plusieurs fois, le nombre n’étant pas
Connu mais dépendant d’une condition.
BEGIN
LOOP [label]
instructions;
EXIT [label] WHEN condition
END LOOP [label] ;
END;
EXIT [label] WHEN condition permet de sortir de la boucle.
Remarques
•Inutil de déclarer indice
•Indice varie de exp1 à exp2 (pas=1)
•Si REVERSE, indice varie de exp2 à exp1 (pas=-1)
IS|AS
[DECLARATION]
BEGIN
instructions_executables
END nom_procedure ;
3. Correction éventuelle des erreurs de la procédure (si le message suivant est affiché)
Warning: Procedure created with compilation errors.
SQL> show errors|show err|show error), puis apportez les correctifs nécessaires
4. Exécution de la procédure
EXECUTE calcul_bonus(numéro d’un employé)
5. Vérifier que la procédure a exécuté les instructions demandées
(interrogation de la table emp)
IS|AS
[DECLARATION]
BEGIN
instructions_executables
END [nom_fonction] ;
BEGIN
SELECT losal, hisal INTO min_sal, max_sal FROM sals
WHERE job = title;
RETURN (salary >= min_sal) AND (salary <= max_sal);
END ;
Package
Ensemble nommé de fonctions, procedures, types et variables.
Un package c’est un meta-module
Les curseurs permettent de nommer des zones de mémoire SQL privée et d’accéder
ainsi aux informations qui y sont stockées lors de l’exécution d’une instruction SQL.
Il existe deux types de curseurs :
les curseurs implicites (ou curseurs SQL) et explicites.
Les curseurs implicites et explicites réalisent la même fonction, à savoir la fourniture
d’espace mémoire pour le traitement des lignes. La différence entre eux réside dans la
façon dont ils sont déclarés :
-Un curseur implicite est automatiquement (implicitement) déclaré par PL/SQL lors de
l'exécution d'instructions PL/SQL et DML (telles que INSERT, UPDATE et DELETE).
-Un curseur explicite est déclaré et nommé par le programmeur. Les curseurs
explicites sont manipulés grâce à des instructions spécifiques dans la section exécutable
d'un bloc.
L’avantage de la création d’un curseur explicite est de pouvoir l’utiliser pour traiter
plusieurs ensembles de résultats de lignes. Le traitement dans un curseur explicite se fait
ligne par ligne au-delà de la première ligne renvoyée par la requête.
SQL%FOUND Retourne TRUE si la dernière instruction SQL a retourné une ou plusieurs lignes.
SQL%NOTFOUND Retourne TRUE si la dernière instruction SQL n’a retourné aucune ligne.
SQL%ISOPEN Détermine si un curseur est ouvert. Il prend toujours la valeur FALSE, car PL/SQL ferme les
curseurs implicites immédiatement après leur exécution.
Les attributs des curseurs SQL ne peuvent pas être utilisés dans des ordres SQL; mais
ils peuvent être utilisés dans la section de traitement des exceptions d'un bloc PL/SQL.
Exemple :
Les lignes renvoyées par une requête sont appelées ensemble actif. PL/SQL définit
automatiquement la taille du curseur en fonction de la taille de l’ensemble actif.
Un curseur doit être déclaré, nommé et associé à une requête. La requête peut contenir
des variables préalablement déclarées, mais en aucun cas de clause INTO.
Exemple :
DECLARE
CURSOR emp_cursor IS SELECT empno, sal * 10 FROM emp;
BEGIN
END ;
Si le curseur est déclaré avec la clause FOR UPDATE, l'ordre OPEN verrouille les lignes
retournées par la requête.
Exemple :
DECLARE
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
CURSOR emp_cursor IS
SELECT empno, ename FROM emp;
BEGIN
OPEN emp_cursor;
FOR i IN 1..10
LOOP
FETCH emp_cursor INTO v_empno, v_ename;
END LOOP;
END ;
- libère des ressources pouvant être utilisées pour l’extraction d’autres tâches.
Bien qu’il soit possible de terminer le bloc PL/SQL sans fermer le curseur, il est
préférable de le fermer explicitement. De plus, le nombre de curseurs ouverts pour
chaque utilisateur est limité par le paramètre de base de données OPEN_CURSORS qui
vaut, par défaut, 50.
L’accès aux données n’est plus possible après la fermeture d’un curseur.
Si une tentative d’accès aux données à partir d’un curseur fermé est effectuée, une
exception INVALID_CURSOR est levée.
Comme dans le cas des curseurs implicites, quatre attributs permettent d’obtenir les
informations relatives à l’état d’un curseur explicite : %ISOPEN, %FOUND,
%NOTFOUND et%ROWCOUNT.
Ces attributs ne peuvent pas être utilisés dans des ordres SQL.
L’attribut %ISOPEN est un attribut booléen qui prend la valeur TRUE si le curseur est
ouvert. Si FALSE est le résultat de l’attribut %ISOPEN, le curseur peut être ouvert.
L’ajout du mot clé NOT inverse la condition.
cursor_name%ISOPEN
NOT cursor_name%ISOPEN
END ;
7
78 Prof: Andy PIERRE, M.Sc
6. Les curseurs en PL/SQL
6.3. Les attributs des curseurs explicites
6.3.1. Contrôle de l’état à l’aide de l’attribut %ISOPEN
Exemple :
BEGIN
END ;
Exemple :
DECLARE
CURSOR emp_cursor IS
SELECT empno, ename FROM emp;
S_emp emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor;
FOR i IN 1..10
LOOP
FETCH emp_cursor INTO S_emp;
DBMS_OUTPUT.PUT_LINE (‘Nom Employe No:’||S_Emp.empno || ‘est ‘
| | S_Emp.ename);
END LOOP;
CLOSE emp_cursor;
END ;
La boucle de curseur FOR permet d'extraire et de traiter une par une les lignes de
l'ensemble actif.
FOR record_name IN cursor_name
LOOP
statements ;
END LOOP ;
La boucle de curseur FOR ouvre et ferme automatiquement le curseur.
De plus, il n’est plus nécessaire de déclarer l'enregistrement PL/SQL contrôlant la
boucle (record_name) , celui-ci est déclaré implicitement par la boucle de curseur FOR
Une boucle de curseur FOR sélectionne une plage de lignes d’une table de base de
données, puis extrait chaque ligne de cette plage.
Les paramètres d’un curseur peuvent être spécifiés entre parenthèses après le nom du
curseur dans l’instruction FOR
Exemple :
SET SERVEROUT ON
DECLARE
CURSOR emp_cursor IS SELECT ename, deptno FROM emp ;
BEGIN
FOR emp_record IN emp_cursor
LOOP
IF emp_record.deptno = 30 THEN
DBMS_OUTPUT.PUT_LINE ('Employe '||
emp_record.ename || ' Travaille au departement de Ventes.');
END IF;
END LOOP ;
END ;
Il est possible d’utiliser le même curseur dans différentes situations et d’extraire des
données différentes chaque fois. Pour cela, des paramètres sont passés au curseur
autorisant ainsi l’exécution de la requête pour différentes valeurs. Un curseur avec des
paramètres aboutit à des ensembles actifs différents suivant les paramètres passés au
curseur.
CURSOR cursor_name [(parameter [IN] datatype [{:= | DEFAULT} expr, …)]
IS select_statement ;
Le nom du paramètre doit être suivi d’un type de données scalaire. La taille des
données des paramètres ne doit pas être spécifiée. Les valeurs des paramètres sont
transmises au curseur lors de son ouverture. Ces valeurs sont utilisées dans la requête
du curseur lors de son exécution.
OPEN cursor_name (value,...)
ou
END LOOP;
Exemple :
DECLARE
CURSOR emp_cursor ( p_job emp.job%TYPE, p_deptno emp.deptno%TYPE) IS
SELECT ename, empno, hiredate FROM emp
WHERE deptno= p_deptno AND job = p_job ;
BEGIN
OPEN emp_cursor('ANALYST',20);
END ;
Écrire un fichier de commande permettant d’afficher les n plus anciens employés de l’entreprise
(recherche sur la date d’embauche)
Exemple :
L’ordre dans lequel les sous-programmes sont définis est très important. Il
faut déclarer ou définir les sous-programmes privés avant de les appeler depuis
d’autres sous-programmes. Le plus souvent, toutes les variables et sous-
programmes privés sont déclarés en premier dans le corps du package et ensuite on
définit les sous-programmes publics.
Les triggers sont des blocs PL/SQL s’exécutant implicitement chaque fois qu’un
événement particulier a lieu. Les triggers peuvent être mis en place soit sur
une base de données soit sur une application.
Les triggers de base de données peuvent être définis sur des tables ou sur des
vues. Si une opération DML est effectuée sur une vue, le trigger INSTEAD OF
définit les actions qui auront lieu. Si ces actions incluent des opérations DML
sur des tables, tous les triggers sur la ou les tables de base sont déclenchées
Corps du trigger Définit les actions qui seront exécutées par le Bloc PL/SQL
trigger complet
Un trigger Row est un trigger dont le corps s’exécute une fois pour chaque
ligne concernée par l’évènement déclenchant. Si l’évènement déclenchant
n’affecte aucune ligne, le corps du trigger n’est pas exécuté. Les triggers Row
sont utiles lorsque l’action du trigger dépend des données des lignes affectées
ou des données fournies directement par l’évènement déclenchant
Écrire un fichier qui mette à jour l’âge des pilotes de la table pilote.
Traiter les anomalies:
• pilote de moins de 20 ans
• Pour les autres erreurs qui pourraient se produire: les traiter globalement.