Académique Documents
Professionnel Documents
Culture Documents
LANGAGE PL/SQL
Bloc Anonyme
Stockéen-dehors de la base de données
Compilé et exécuté à la volée
Procédure Stockée :
Compilée séparément
Stockée de façon permanente dans la BD
Déclencheur (Trigger)
Procédure stockée associée à une table
Exécution automatique sur événement
Commandes de dialogue – SQL*Plus
8
DECLARE
-- déclarations
BEGIN
PL/SQL -- &var si numérique
-- '&var' si chaine de caractères
END;
/
SQL*Plus -- Ordre SQL .....
Package DBMS_OUTPUT – SQL*Plus
10
Message1
Message2
Message3
SQL>SET SERVEROUT ON
Mémoire tampon
Types de Variables PL/SQL
11
Variables locales:
De type simple: type de base ou booléen
Faisant référence à la métabase (dictionnaire de
données de Oracle)
De type composé : Tableau, Record
Variables Extérieures:
Variablesd’un langage hôte (ex: C) (préfixés par : )
Paramètres (ex: SQL interactif préfixés par &)
Types de Variables
12
Opérateurs SQL
13
Opérateur d’affectation :=
Opérateurs arithmétiques + - / * **
Opérateur de concaténation ||
Opérateurs de comparaison
= < > <= >= <> != IS NULL LIKE BETWEEN IN
Opérateurs logiques AND, OR, NOT
Variables simples
14
Déclaration :
variable_name [CONSTANT] datatype
[NOT NULL] [:= | DEFAULT initial_value];
declare
var_emp emp%rowtype;
begin
var_emp.empno := 1234;
var_emp.ename := 'Salah';
Fonctions de conversion :
TO_CHAR, TO_DATE, TO_NUMBER
CASE
WHEN condition1 THEN action1;
WHEN condition2 THEN action2;
………
ELSE action;
END CASE;
Structure alternative : CASE
21
DECLARE
note varchar2(1) := 'D';
BEGIN
CASE note
when 'A' then dbms_output.put_line('Excellent');
when 'B' then dbms_output.put_line('Très Bien');
when 'C' then dbms_output.put_line('Bien');
when 'D' then dbms_output.put_line('Passable');
when 'E' then dbms_output.put_line('Mauvais');
else dbms_output.put_line('Valeur incorrecte');
END CASE;
END;
/
Structure alternative : CASE
22
Traitements itératifs
23
LOOP
LOOP
instructions;
EXIT WHEN (condition);
END LOOP;
FOR
FOR (indice IN [REVERSE] borne1..borne2) LOOP
instructions;
END LOOP;
WHILE
WHILE (condition) LOOP
instructions;
END LOOP;
Structures itératives
24
BEGIN
dbms_output.put_line ('Les nombres divisibles par 4 sont : ');
FOR i IN 4..20 LOOP
IF (mod(i,4) = 0) THEN
dbms_output.put_line (to_char(i) || '-');
END IF;
END LOOP;
END;
/
Structures itératives
25
Structures itératives
26
BEGIN
dbms_output.put_line ('Les annees bissextiles sont : ');
FOR i IN &ANNEE1 .. &ANNEE2 LOOP
IF ( (MOD (i,4) = 0 AND MOD(i, 100) != 0) OR MOD(i, 400) = 0 )
THEN dbms_output.put_line(i);
END IF;
END LOOP;
END;
/
SELECT …. INTO … (mono – ligne)
29
Variable ROWTYPE
DECLARE
vdept dept%rowtype;
BEGIN
SELECT *
INTO vdept
FROM dept
WHERE deptno = 40;
Programme PL/SQL
Mémoire
FETCH
variables
DECLARE
CURSOR c1 IS SELECT ……;
BEGIN
OPEN c1;
FETCH c1 INTO ………;
WHILE (c1%FOUND) LOOP
………
……… OPEN
FETCH c1 INTO ………;
END LOOP;
CLOSE c1;
END;
BD
Attributs d’un Curseur
34
Curseur%FOUND
Variable
booléenne : est égal à TRUE si le dernier
FETCH a retourné un résultat
Curseur%NOTFOUND
Variable booléenne opposée au précédent : est égal à
TRUE si le dernier FETCH n’a pas retourné un résultat
Curseur%ROWCOUNT
Variable numérique : retourne le nombre de lignes lues
Curseur%ISOPEN
Variable booléenne : est égal à TRUE si le curseur est
ouvert
Gestion ‘classique’ d’un curseur
35
DECLARE
CURSOR emp_cursor IS -- déclarer le curseur
SELECT ename, dname FROM emp, dept
WHERE emp.deptno = dept.deptno;
emp_record emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor ; -- Ouvrir le curseur
LOOP
FETCH emp_cursor INTO emp_record; -- avancer au tuple suivant
EXIT WHEN emp_cursor%NOTFOUND; -- sortir si la fin du curseur
-- est détectée
DBMS_OUTPUT.PUT_LINE('L''employe '|| emp_record.ename ||
' travaille dans le departement ' || emp_record.dname);
END LOOP;
CLOSE emp_cursor; -- fermer le curseur
END;
/
Gestion ‘classique’ d’un curseur
36
Gestion ‘classique’ d’un curseur
37
DECLARE
CURSOR emp_cursor IS -- déclarer le curseur
SELECT ename, dname FROM emp, dept
WHERE emp.deptno = dept.deptno;
emp_record emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor ; -- Ouvrir le curseur
LOOP
FETCH emp_cursor INTO emp_record; -- avancer au tuple suivant
EXIT WHEN emp_cursor%NOTFOUND; -- sortir si la fin du curseur
-- est détectée
DBMS_OUTPUT.PUT_LINE(emp_cursor%ROWCOUNT||' - L''employe '||
emp_record.ename ||
' travaille dans le departement '
|| emp_record.dname);
END LOOP;
CLOSE emp_cursor; -- fermer le curseur
END;
/
Gestion ‘classique’ d’un curseur
38 DECLARE
CURSOR emp_cursor IS -- déclarer le curseur
SELECT ename, dname FROM emp, dept
WHERE emp.deptno = dept.deptno;
nom_emp emp.ename%TYPE;
nom_dept dept.dname%TYPE;
BEGIN
OPEN emp_cursor ; -- Ouvrir le curseur
LOOP
FETCH emp_cursor INTO nom_emp, nom_dept;
-- avancer au tuple suivant
EXIT WHEN emp_cursor%NOTFOUND; -- sortir si la fin du curseur
-- est détectée
DBMS_OUTPUT.PUT_LINE(emp_cursor%ROWCOUNT||' - L''employe '||
nom_emp ||
' travaille dans le departement '||
nom_dept);
END LOOP;
CLOSE emp_cursor; -- fermer le curseur
END;
/
Gestion ‘classique’ d’un curseur
39
DECLARE
CURSOR emp_cursor IS -- déclarer le curseur
SELECT ename, dname FROM emp, dept
WHERE emp.deptno = dept.deptno;
emp_record emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor; -- Ouvrir le curseur
FETCH emp_cursor INTO emp_record; -- avancer au premier tuple
WHILE (emp_cursor%FOUND) LOOP -- sortir si aucun tuple
-- n’a été ramené par
-- le dernier fetch
DBMS_OUTPUT.PUT_LINE(emp_cursor%ROWCOUNT||' - L''employe '||
emp_record.ename ||
' travaille dans le departement '
|| emp_record.dname);
DECLARE
CURSOR emp_cursor IS -- déclarer le curseur
SELECT ename, dname FROM emp, dept
WHERE emp.deptno = dept.deptno;
BEGIN
-- Ouverture, parcours et fermeture automatique du curseur
FOR emp_record IN emp_cursor LOOP
DBMS_OUTPUT.PUT_LINE(emp_cursor%rowcount||' - L''employe '||
emp_record.ename ||
' travaille dans le departement ' ||
emp_record.dname);
END LOOP;
END;
/
Gestion ‘automatique’ d’un curseur
41
BEGIN
-- Déclaration, ouverture, parcours et fermeture
-- automatique du curseur
FOR emp_record IN ( SELECT ename, dname FROM emp, dept
WHERE emp.deptno = dept.deptno)
LOOP
DBMS_OUTPUT.PUT_LINE('L''employe '||
emp_record.ename ||
' travaille dans le departement '
|| emp_record.dname);
END LOOP;
END;
/
Curseurs paramétrés
42
DECLARE
CURSOR emp_cursor (p_dep EMP.deptno%TYPE) IS
SELECT ename, job, sal
FROM emp
WHERE deptno = p_dep;
v_employe emp_cursor%rowtype;
BEGIN
dbms_output.put_line ('Employes du dept. '||&num_dep);
open emp_cursor(&num_dep);
LOOP
fetch emp_cursor into v_employe;
exit when emp_cursor%notfound;
dbms_output.put_line (v_employe.ename|| ' - '|| v_employe.job ||
' : '|| v_employe.sal);
END LOOP;
close emp_cursor;
END;
/
Curseur - Clause CURRENT-OF
43
DECLARE
CURSOR emp_cursor IS
SELECT comm
FROM emp
FOR UPDATE OF comm;
BEGIN
FOR v_employe IN emp_cursor LOOP
IF v_employe.comm IS NULL or v_employe.comm = 0
THEN
UPDATE emp SET comm = sal * 0.05
WHERE CURRENT OF emp_cursor;
END IF;
END LOOP;
END;
/
Gestion des Exceptions
45
DECLARE
erreur EXCEPTION; ---- Déclaration exception
BEGIN
SELECT … INTO ……
DECLARE
nbre_emp INTEGER;
aucun_emp EXCEPTION; ---- Déclaration exception
BEGIN
SELECT COUNT(*) INTO nbre_emp FROM emp;
IF nbre_emp =0 THEN
RAISE aucun_emp; ---- Levée exception
ELSE
DBMS_OUTPUT.PUT_LINE('La table EMP contient '||nbre_emp||' employes');
END IF;
EXCEPTION
WHEN aucun_emp THEN ---- Traitement exception
DBMS_OUTPUT.PUT_LINE('La table EMP est vide');
WHEN OTHERS THEN ---- Exception prédéfinie
DBMS_OUTPUT.PUT_LINE('Erreur inconnue ' || SQLERRM);
END;
/
Exemple de gestion d’exception
50
DECLARE
c INTEGER;
aucun_emp EXCEPTION; ---- Déclaration exception
BEGIN
SELECT COUNT(*) INTO c FROM emp;
IF c=0 THEN
RAISE aucun_emp; ---- Levée exception
………
EXCEPTION
WHEN aucun_emp THEN ---- Traitement exception
RAISE_APPLICATION_ERROR(-20501, 'La table EMP est vide');
………
END;
/
DECLARE
impot emp.sal%type;
net_payer emp.sal%type;
BEGIN
FOR emp_record IN (SELECT ename, sal, comm FROM emp)
LOOP
IF (emp_record.sal < 1000)
THEN impot := emp_record.sal * 0.25;
ELSIF emp_record.sal <= 1500
THEN impot := emp_record.sal * 0.3;
ELSE impot := emp_record.sal * 0.35;
END IF;
net_payer := emp_record.sal + nvl(emp_record.comm, 0) - impot;
DBMS_OUTPUT.PUT_LINE('L''employe '||emp_record.ename ||
' - Salaire = ' ||emp_record.sal|| ' - Impot = ' ||impot||' - Net a payer = ' ||net_payer);
END LOOP;
EXCEPTION
WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Erreur inconnue !!!');
END;
/
PROCÉDURES –
FONCTIONS – PACKAGES
BD – Oracle
Procédure/Fonction
Stockée
Procédures stockées
55
Exemple :
CREATE OR REPLACE PROCEDURE modifierTitre
(num IN film.numFilm%TYPE, nouvTitre IN film.titre%TYPE) IS
BEGIN
UPDATE film SET titre = UPPER(nouvTitre)
WHERE numFilm = num;
END modifierTitre;
DBMS_OUTPUT.PUT_LINE(num_employe||' '||v_ename||'
'||v_sal);
END;
/
Procédures stockées
58
DECLARE
nom_emp EMP.ename%type;
sal_emp EMP.sal%type;
BEGIN
affiche_salaire (7369, nom_emp, sal_emp);
DBMS_OUTPUT.PUT_LINE(nom_emp||' '|| sal_emp);
END;
/
Procédures stockées
61
Dictionnaire de données :
USER_SOURCE, USER_OBJECTS, USER_ERRORS
Fonctions stockées
62
Exemple :
CREATE OR REPLACE FUNCTION moyenneDuree (dd IN DATE )
RETURN NUMBER IS
moy NUMBER(8) := 0;
BEGIN
SELECT AVG(duree)
INTO moy
FROM film WHERE dateFilm <= dd;
RETURN moy;
END moyenneDuree;
Fonctions stockées
65
Return (v_resultat);
END;
/
Fonctions stockées
66
END;
Packages - BODY
73
Return (v_resultat);
END;
Une fois lancé, un trigger peut exécuter son code pour chaque
tuple touché par la mise à jour : utiliser la clause FOR EACH ROW
create or replace trigger monTrigger2
after update of sal on emp for each row
begin
dbms_output.put_line('Update Salaire');
end;
/