Bases de données avancées
LANGAGE PL/SQL
Niveau:
DUT GI S3
Bases de données avancées
2
INTRODUCTION
PL/SQL 25/11/2020
Généralités
3
PL/SQL: Procedural Language extensions to SQL.
Objectif : bonne intégration du langage avec SQL.
PL/SQL n’existe pas comme un langage autonome ; il est
utilisé à l’intérieur d’autres produits Oracle.
Permet des interactions avec une base SQL.
Langage de programmation qui inclut des ordres SQL.
PL/SQL 25/11/2020
Pourquoi PL/SQL
4
SQL est un langage non procédural.
Les traitements complexes sont parfois difficiles à écrire
si on ne peut utiliser des variables et les structures de
programmation comme les boucles et les alternatives.
On ressent vite le besoin d’un langage procédural pour
lier plusieurs requêtes SQL avec des variables et dans les
structures de programmation habituelles.
PL/SQL 25/11/2020
Pourquoi PL/SQL (2)
5
Les contraintes prédéfinies ne sont pas toujours
suffisantes.
Exemple : tout nouveau prix pour un CD doit avoir
une date de début supérieure à celle des autres prix
pour ce CD.
L'insertion, la suppression ou la mise à jour de certaines
données peut nécessiter des calculs sur la base.
Utilisation de fonction propres à l'application dans des
requêtes.
PL/SQL 25/11/2020
Caractéristiques du PL/SQL
6
Extension de SQL : des requêtes SQL cohabitent avec les
structures de contrôle habituelles de la programmation
structurée (blocs, alternatives, boucles).
La syntaxe ressemble au langage Ada et proche de Pascal.
Un programme est constitué de procédures et de
fonctions.
Des variables permettent l’échange d’information entre
les requêtes SQL et le reste du programme.
PL/SQL 25/11/2020
Utilisation de PL/SQL
7
PL/SQL peut être utilisé pour l’écriture des procédures
stockées et des triggers (Oracle accepte aussi le langage
Java).
Il convient aussi pour écrire des fonctions utilisateurs qui
peuvent être utilisées dans les requêtes SQL (en plus des
fonctions prédéfinies).
Il est aussi utilisé dans des outils Oracle, Forms et Report
en particulier.
PL/SQL 25/11/2020
PL/SQL
8
PL/SQL est un langage structuré en blocs, constitués
d'un ensemble d'instructions. C’est un langage de
programmation à la fois puissant, simple et moderne.
PL/SQL 25/11/2020
Comparaison avec SQL
9
SQL:
Langage assertionnel et non procédural.
Pl/Sql:
Langage procédural qui intègre des ordres sql:
Select, insert, update, delete
Langage à part entière comprenant:
Définition de variables, constantes, expressions, affectations.
Traitement conditionnels, répétitifs.
Traitement de curseurs.
Traitement des erreurs et d’exceptions.
Etc…
PL/SQL 25/11/2020
Avantages du PL/SQL
10
PL/SQL offre de nombreux avantages:
Intégration parfaite du SQL
Support de la programmation orientée objet
Très bonne performance
Portabilité
Facilité de programmation
PL/SQL 25/11/2020
Objectifs du chapitre
11
A la fin de ce chapitre, vous pourrez:
Identifier les différentes parties d’un bloc PL/SQL
Spécifier des variables PL/SQL
Déclarer des variables intégrées PL/SQL
Déclarer des variables typées dynamiquement
Exécuter un bloc PL/SQL
Avec ou sans accès à la base
PL/SQL 25/11/2020
Bases de données avancées
12
STRUCTURE D’UN
PROGRAMME PL/SQL
PL/SQL 25/11/2020
Blocs
13
Un programme est structuré en blocs d’instructions
de 3 types :
procédures anonymes
procédures nommées
fonctions nommées
Un bloc peut contenir d’autres blocs
PL/SQL 25/11/2020
Structure des blocs
14
Une section facultative de déclaration et initialisation de
types, variables et constantes
Une section obligatoire contenant les instructions
d'exécution
Une section facultative de gestion des erreurs
PL/SQL 25/11/2020
Structure des blocs (2)
15
DECLARE
-- définitions de variables
BEGIN
-- Les instructions à exécuter
EXCEPTION
-- La récupération des erreurs
END;
PL/SQL 25/11/2020
Structure des blocs (3)
16
Les blocs PL/SQL peuvent être imbriqués:
DECLARE
…
BEGIN
DECLARE
…..
BEGIN
……
BEGIN
………
END ;
………
END ;
……..
END ;
PL/SQL 25/11/2020
Structure des blocs (4)
17
Les blocs comme les instructions se terminent par
un ‘;’.
Seuls ‘Begin’ et ‘End’ sont obligatoires.
PL/SQL 25/11/2020
Bases de données avancées
18
LES VARIABLES
PL/SQL 25/11/2020
Les variables
19
Identificateurs Oracle :
30 caractères au plus
commence par une lettre
peut contenir lettres, chiffres, _, $ et #
Pas sensible à la casse.
Portée habituelle des langages à blocs.
Doivent être déclarées avant d’être utilisées.
PL/SQL 25/11/2020
Les variables (2)
20
Déclaration :
Nom_variable type_variable;
Initialisation:
Nom_variable := valeur;
Déclaration et initialisation :
Nom_variable type_variable := valeur;
PL/SQL 25/11/2020
Les variables
21
var [CONSTANT] datatype [NOT NULL] [:= | DEFAULT expression];
Adopter des conventions pour nommer des objets.
Initialiser les constantes et les variables déclarées en
utilisant les mots réservés NOT NULL.
Initialiser les identifiants en utilisant l'opérateur
d'affectation ( := ) ou le mot réservé DEFAULT.
Déclarer au plus un identifiant par ligne.
Le type peut être primitif ou objet.
PL/SQL 25/11/2020
Commentaires
22
-- Pour une fin de ligne
/* Pour plusieurs lignes
Pour plusieurs lignes
Pour plusieurs lignes */
PL/SQL 25/11/2020
Les types de variables
23
VARCHAR2
Longueur maximale : 32767 octets
Syntaxe:
Nom_variable VARCHAR2(30);
Exemple: name VARCHAR2(30);
name VARCHAR2(30) := ‘toto’;
NUMBER
Nom_variable NUMBER(long,dec);
avec Long : longueur maximale
Dec : longueur de la partie décimale
Exemple: num_tel number(10);
toto number(5,2)=142.12;
PL/SQL 25/11/2020
Les types de variables (2)
24
DATE
Nom_variable DATE;
Par défaut DD-MON-YY (18-DEC-02)
Fonction TO_DATE
Exemple :
start_date := to_date(’29-SEP-2003’,’DD-MON-YYYY’);
start_date := to_date(’29-SEP-[Link]’,’DD-MON-
YYYY:HH24:MI’);
BOOLEAN
TRUE, FALSE ou NULL
PL/SQL 25/11/2020
Les types de variables (3)
25
identificateur [CONSTANT] type [:= valeur];
Exemples :
age integer;
nom varchar(30);
dateNaissance date;
ok boolean := true;
Déclarations multiples interdites :
i, j integer;
PL/SQL 25/11/2020
Exemples
26
c CHAR( 1 );
name VARCHAR2(10) := 'Scott';
cpt BINARY_INTEGER := 0;
total NUMBER( 9, 2 ) := 0;
order DATE := SYSDATE + 7;
Ship DATE;
pi CONSTANT NUMBER ( 3, 2 ) := 3.14;
done BOOLEAN NOT NULL := TRUE;
ID NUMBER(3) NOT NULL := 201;
PRODUIT NUMBER(4) := 2*100;
V_date DATE := TO_DATE('17-OCT-01','DD-MON-YY');
V1 NUMBER := 10;
V2 NUMBER := 20;
V3 BOOLEAN := (v1>v2);
Ok BOOLEAN := (z IS NOT NULL);
PL/SQL 25/11/2020
Quelques conventions en PL/SQL
27
Deux variables peuvent partager le même nom si
elles sont dans des portées distinctes.
Les noms des variables doivent être différents des
noms des colonnes des tables utilisées dans un bloc:
v_empno (variable)
g_deptno (globale)
c_emp (CURSOR)
L’identifiant est limité à 30 caractères, le premier
caractère devant être une lettre.
PL/SQL 25/11/2020
Utilisation des variables
28
On utilise des variables pour :
Le stockage temporaire de données
La manipulation de valeur stockées
La possibilité de les réutiliser
Simplifier la maintenance du code
Variable typée dynamiquement au moyen d’ attributs spéciaux
%ROWTYPE ou %TYPE
Les variables Abstract Data Type et les collections
seront abordées ultérieurement
Oracle9i est également un SGBD orienté objet
PL/SQL 25/11/2020
Bloc PL/SQL Anonyme accédant à la base
29
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
v_name VARCHAR2(10);
BEGIN Affectation
SELECT ename INTO v_name
FROM emp; -- WHERE empno=7839;
DBMS_OUTPUT.PUT_LINE(v_name);
EXCEPTION
WHEN OTHERS
THEN NULL;
END;
/
PL/SQL Procedure successfully completed.
PL/SQL 25/11/2020
Cas à plusieurs variables hôtes
30
SET SERVEROUTPUT ON
SQL> DECLARE
v_ename VARCHAR2(12);
v_sal NUMBER(7,2);
BEGIN
SELECT ename, sal INTO v_ename, v_sal
FROM emp WHERE ROWNUM = 1;
DBMS_OUTPUT.PUT_LINE(v_ename);
DBMS_OUTPUT.PUT_LINE(v_sal);
EXCEPTION
WHEN OTHERS Optionnel à ce stade
THEN NULL;
END;
/
PL/SQL 25/11/2020
31
Bases de données avancées
Variables typées dynamiquement
PL/SQL 25/11/2020
Les types de variables (4)
32
Types composites adaptés à la récupération des
colonnes et lignes des tables SQL :
%TYPE
%ROWTYPE
PL/SQL 25/11/2020
Typage dynamique %TYPE
33
Déclarer une variable à partir :
D'une autre variable déjà déclarée
D’une définition d’un attribut de la base de données
Préfixer %TYPE avec :
Le nom de la variable déclarée précédemment
La table et la colonne de la base de données
PL/SQL évalue le type de donnée et la taille de la
variable.
Inspiré du langage ADA.
PL/SQL 25/11/2020
Déclaration %TYPE
34
On peut déclarer qu’une variable est du même type
qu’une colonne d’une table ou d’une vue (ou qu’une
autre variable) :
nom [Link]%TYPE;
PL/SQL 25/11/2020
L'Attribut %TYPE - Exemple
35
DECLARE
ename [Link]%TYPE;
job [Link]%TYPE;
balance NUMBER(7, 2);
mini_balance balance%TYPE := 10;
rec emp%ROWTYPE;
Le type de données de la colonne peut être inconnu.
Le type de données de la colonne peut se changer en exécution.
Facilite la maintenance.
PL/SQL 25/11/2020
Variable typée dynamiquement
36
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
v_ename [Link]%TYPE;
BEGIN
SELECT ename INTO v_ename
FROM emp WHERE ROWNUM = 1;
DBMS_OUTPUT.PUT_LINE(v_ename);
EXCEPTION
WHEN OTHERS
THEN NULL;
END;
/
PL/SQL 25/11/2020
Déclaration %ROWTYPE
37
Une variable peut contenir toutes les colonnes d’une
ligne d’une table:
employe emp%ROWTYPE;
déclare que la variable employe contiendra une ligne
de la table emp.
PL/SQL 25/11/2020
Exemple d’utilisation
38
employe emp%ROWTYPE;
nom [Link]%TYPE;
select * INTO employe
from emp
where matr = 900;
nom := [Link];
[Link] := 20;
----------
insert into emp
values employe;
PL/SQL 25/11/2020
Attribut %TYPE & %ROWTYPE
39
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
rec emp%ROWTYPE;
address VARCHAR2(64);
income [Link]%TYPE; -- [Link]%TYPE;
BEGIN
SELECT * INTO rec FROM emp Manipulation dans
WHERE ROWNUM = 1;
income := [Link]*12; une variable PL
address := [Link] || CHR(10) || income ||
CHR(10) || TO_CHAR([Link],'DD/MM/YYYY');
DBMS_OUTPUT.PUT_LINE(address);
END;
/
SMITH
9600
17/12/1980
PL/SQL 25/11/2020
Affectation
40
Plusieurs façons de donner une valeur à une
variable:
:=
par la directive INTO de la requête SELECT
Exemples :
dateNaissance := ’10/10/2004’;
select name INTO nom from emp where matr = 509;
PL/SQL 25/11/2020
Les opérateurs
41
PL/SQL supporte les opérateurs suivants :
Arithmétique : +, -, *, /
Concaténation : ||
Parenthèses (contrôle des priorités entre opérations): ()
Comparaison : =, !=, <, >, <=, >=, IS NULL, LIKE,
BETWEEN, IN
Logique : AND, OR, NOT
Affectation: :=
PL/SQL 25/11/2020
Portée
42
Les instructions peuvent être imbriquées là où les
instructions exécutables sont autorisées.
La section EXCEPTION peut contenir des blocs
imbriqués.
Les boucles possède chacune une portée
les incréments y sont définis
Un identifiant est visible dans les régions où on peut
référencer cet identifiant :
Un bloc voit les objets du bloc de niveau supérieur.
Un bloc ne voit pas les objets des blocs de niveau
inférieur.
PL/SQL 25/11/2020
Portée
43
PL/SQL 25/11/2020
Règles générales
44
Commenter le code
Adopter une convention de casse
Développer une convention d’appel pour les
identifiants et autres objets
Indenter le code
Instruction SQL en majuscules
Mots-clés en majuscules
Type de données en majuscules
Identifiant et paramètres en minuscules
Tables & colonnes en minuscules
PL/SQL 25/11/2020
Conventions d’appel possible
45
Identifiant Nom Exemple
Variable v_name v_sal
Constante c_name c_pi
Cursor name_cursor Emp_cursor
Exception e_name E_too_many
Table type name_table_type sum_table_type
Table name_table emp_tot_table
Record Type name_record_type emp_record_type
Record name_record emp_record
Substitution p_name p_sal
Globale g_name g_deptno
PL/SQL 25/11/2020
Bases de données avancées
46
LES CURSEURS
PL/SQL 25/11/2020
Introduction
47
Manipulation de tuples (champs) :
Les directives INSERT INTO, UPDATE et DELETE FROM peuvent
être utilisées sans restriction avec des variables PL/SQL (scalaires,
%ROWTYPE)
Lecture de tuples (champs) : Chargement d’une variable à partir
de la lecture d’un unique enregistrement dans la base (exception
si 0 ou plusieurs enregistrements en réponse)
DECLARE
heure_depart [Link]%TYPE;
BEGIN
SELECT [Link] INTO heure_depart
FROM vols WHERE [Link] = ‘AF3517’ ;
END;
PL/SQL 25/11/2020
Pourquoi utiliser les curseur
48
Les instructions de type SELECT ... INTO ... manquent de
souplesse, elles ne fonctionnent que sur des requêtes
retournant une et une seule valeur (ou une seule ligne). Ne
serait-il pas intéressant de pouvoir placer dans des variables
le résultat d'une requête retournant plusieurs lignes ?
PL/SQL 25/11/2020
Fonctionnalités
49
Toutes les requêtes SQL sont associées à un curseur.
Ce curseur représente la zone mémoire utilisée pour
analyser et exécuter la requête.
Le curseur peut être implicite (pas déclaré par
l’utilisateur) ou explicite.
Les curseurs explicites servent à retourner plusieurs
lignes avec un select.
PL/SQL 25/11/2020
Attributs des curseurs
50
Tous les curseurs ont des attributs que l’utilisateur peut
utiliser:
nom_cureseur%ROWCOUNT : nombre de lignes traitées par le
curseur
nom_cureseur%FOUND : vrai si au moins une ligne a été traitée par
la requête ou le dernier fetch
nom_cureseur%NOTFOUND : vrai si aucune ligne n’a été traitée
par la requête ou le dernier fetch
nom_cureseur%ISOPEN : vrai si le curseur est ouvert (utile
seulement pour les curseurs explicites)
PL/SQL 25/11/2020
Curseur implicite
51
Les curseurs implicites 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.
Les curseurs implicites sont tous nommés SQL
DECLARE
Exemple: nb_lignes integer;
BEGIN
DELETE FROM emp
WHERE dept = 10;
nb_lignes := SQL%ROWCOUNT;
...
PL/SQL 25/11/2020
Curseur Explicite
52
Un curseur explicite est une commande SELECT
pouvant ramener plusieurs lignes et qui est
totalement à la charge du développeur.
Tout curseur explicite géré dans la section exécution
doit avoir été déclaré dans la section déclarative.
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.
PL/SQL 25/11/2020
Déclaration des curseurs
53
Un curseur se déclare dans une section DECLARE :
CURSOR / nomcurseur / IS / requete / ;
Exemple:
CURSOR emp_cur IS
SELECT * FROM EMP ;
PL/SQL 25/11/2020
Ouverture
54
Lors de l'ouverture d'un curseur, la requête du curseur est
évaluée, et le curseur contient toutes les données retournées par la
requête. On ouvre un curseur dans une section BEGIN :
OPEN / nomcurseur / ;
Exemple:
DECLARE
CURSOR emp_cur IS
SELECT * FROM emp ;
BEGIN
OPEN emp_cur ;
/ Utilisation du curseur /
END;
PL/SQL 25/11/2020
Lecture d'une ligne
55
Une fois ouvert, le curseur contient toutes les lignes du résultat de
la requête. On les récupère une par une en utilisant le mot-clé
FETCH :
FETCH / nom curseur / INTO / listevariables/;
La liste de variables peut être remplacée par une structure de type
nom curseur%ROWTYPE. Si la lecture de la ligne échoue, parce
qu'il n'y a plus de ligne à lire, l'attribut %NOTFOUND prend la
valeur vrai.
PL/SQL 25/11/2020
Lecture d'une ligne (2)
56
DECLARE
CURSOR emp_cur IS
SELECT * FROM emp ;
ligne emp_cur%rowtype ;
BEGIN
OPEN emp_cur ;
LOOP
FETCH emp_cur INTO ligne ;
EXIT WHEN emp_cur%NOTFOUND ;
DBMS_OUTPUT . PUT_LINE ( ligne . ename ) ;
END LOOP ;
/.../
END;
PL/SQL 25/11/2020
Fermeture du curseur
57
Apres utilisation, il convient de fermer le curseur.
CLOSE / nomcurseur / ;
Complétons l’exemple:
DECLARE
CURSOR emp_cur IS
SELECT * FROM emp ;
ligne emp_cur%rowtype ;
BEGIN
OPEN emp_cur ;
LOOP
FETCH emp_cur INTO ligne ;
EXIT WHEN emp_cur%NOTFOUND ;
DBMS_OUTPUT . PUT_LINE ([Link]) ;
END LOOP ;
CLOSE emp_cur ;
END;
/
PL/SQL 25/11/2020
Boucle For
58
Il existe une boucle FOR se chargeant de l'ouverture, de la lecture
des lignes du curseur et de sa fermeture.
FOR ligne IN emp_cur LOOP
/ Traitement /
END LOOP ;
PL/SQL 25/11/2020
Boucle For: exemple
59
DECLARE
CURSOR emp_cur IS
SELECT * FROM emp ;
ligne emp_cur%ROWTYPE ;
BEGIN
FOR ligne IN emp_cur LOOP
DBMS_OUTPUT . PUT_LINE ([Link]) ;
END LOOP ;
END;
/
PL/SQL 25/11/2020
Curseurs paramétrés
60
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 parametres /) IS
/ requete /
PL/SQL 25/11/2020
Curseurs paramétrés: Exemple
61
Créons une requête qui, pour une personne donnée, nous donne la
liste des noms et prénoms de ses enfants :
CURSOR enfants (numparent NUMBER) IS
SELECT *
FROM personne
WHERE pere = numparent
OR mere = numparent ;
PL/SQL 25/11/2020
Curseurs paramétrés: Ouverture
62
On ouvre un curseur paramétré en passant en paramètres les
valeurs des variables :
OPEN / nom / ( / liste des paramètres / )
Exemple:
OPEN enfants ( 1 ) ;
PL/SQL 25/11/2020
Curseurs paramétrés: Boucle for
63
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 des parametres / ) LOOP
/ instructions /
END LOOP ;
Exemple:
FOR e IN enfants ( 1 ) LOOP
DBMS_OUTPUT.PUT_LINE([Link] ||" "|| [Link]) ;
END LOOP ;
PL/SQL 25/11/2020
Exemple récapitulatif
64
DECLARE
CURSOR parent IS
SELECT *
FROM personne WHERE pere is null OR mere is null ;
p parent%rowtype ;
CURSOR enfants (numparent NUMBER) IS
SELECT *
FROM personne WHERE pere = numparent OR mere = numparent ;
e enfants%rowtype ;
BEGIN
FOR p IN parent LOOP
DBMS_OUTPUT.PUT_LINE (' Les enfants de ' || [Link] ||' '||[Link] ||' sont : ') ;
FOR e IN enfants ([Link]) LOOP
DBMS_OUTPUT.PUT_LINE (' * ' || [Link] || ' ' ||[Link]) ;
END LOOP ;
END LOOP ;
END;
PL/SQL 25/11/2020
Bases de données avancées
65
LES PROCÉDURES ET
LES FONCTIONS
STOCKÉES
PL/SQL 25/11/2020
Fonctions et procédures stockées
66
Pourquoi?
Pour enregistrer des programmes dans le noyau d'Oracle.
Comme une table ou une vue, elles peuvent être utilisées par
d'autres utilisateurs, s'ils ont les droits voulus.
Stockées sous forme de pseudo-code : pas de nouvelle
compilation ! Efficace.
PL/SQL 25/11/2020
Déclaration procédure stockée
67
PL/SQL 25/11/2020
Déclaration procédure stockée: paramètres
68
PL/SQL 25/11/2020
Exemple de procédure stockée
69
On cherche les réalisateurs qui ont joué dans plus de nbFilms de
leurs films...
CREATE PROCEDURE realActeursProc (nbFilms NUMBER) IS
nbRealAct NUMBER(5) ;
BEGIN
SELECT COUNT(distinct [Link]) INTO nbRealAct
FROM Film F, Acteur A
WHERE [Link] = [Link]
AND [Link] = [Link];
IF nbRealAct >= nbFilms THEN
DBMS_OUTPUT.PUT_LINE(nbRealAct||' réalisateurs ont joué dans plus
de '||nbFilms||' de leurs films');
ELSE
DBMS_OUTPUT.PUT_LINE('Aucun réalisateur n''a joué dans plus de
'||nbFilms||' de ses films');
END IF;
END;
PL/SQL 25/11/2020
Déclaration fonction stockée
70
PL/SQL 25/11/2020
Exemple de fonction stockée
71
On cherche toujours les réalisateurs qui ont joué dans plus de
nbFilms de leurs films...
CREATE FUNCTION nbRealActeurFonc (nbFilms NUMBER)
RETURN NUMBER IS
nbRealAct NUMBER(5) := 0 ;
BEGIN
SELECT COUNT(distinct [Link]) INTO nbRealAct
FROM Film F, Acteur A
WHERE [Link] = [Link]
AND [Link] = [Link];
IF nbRealAct >= nbFilms THEN
DBMS_OUTPUT.PUT_LINE('Le nombre des réalisateurs qui ont joué
dans leurs films est: ');
RETURN nbRealAct;
ELSE RETURN null;
END IF;
END;
PL/SQL 25/11/2020
Appel de procédures et de fonctions stockées
72
PL/SQL 25/11/2020
Récursivité
73
PL/SQL 25/11/2020
Compilation et suppression
74
PL/SQL 25/11/2020
Exemple
75
On cherche les acteurs ayant joué dans plus de N
films... et on affiche leurs noms et prénoms!
CREATE PROCEDURE nomsGdsActeurs (nbFilms NUMBER) IS
Cursor lesActeurs IS
SELECT nomIndividu, prenomIndividu
FROM Individu
WHERE numIndividu IN
(SELECT numIndividu
FROM acteur
GROUP BY numIndividu
HAVING Count(numFilm) >= nbFilms) ;
sonNomPre lesActeurs%rowtype ;
...
PL/SQL 25/11/2020
Exemple (suite)
76
...
BEGIN
DBMS_OUTPUT.PUT_LINE('Les acteurs ayant joué dans plus de
'||nbFilms||' films sont : ') ;
OPEN lesActeurs ;
LOOP
FETCH lesActeurs INTO sonNomPre ;
EXIT WHEN lesActeurs%NOTFOUND ;
DBMS_OUTPUT.PUT_LINE(' '||[Link]||'
'||[Link]) ;
END LOOP ;
DBMS_OUTPUT.PUT_LINE(chr(10)||'Le nombre d''acteurs ayant joué
dans plus de '||nbFilms||' films est: '|| lesActeurs%rowCount);
CLOSE lesActeurs;
END;
PL/SQL 25/11/2020
Bases de données avancées
77
TRIGGERS
PL/SQL 25/11/2020
Déclencheur (Trigger)
78
C'est un traitement implicite déclenché par un
événement.
Utilisé pour implémenter des règles de gestion
complexes et pour étendre les règles d'intégrité
référentiel associées aux tables.
Un trigger est défini au moyen de PL/SQL.
PL/SQL 25/11/2020
Caractéristiques d'un Trigger
79
Son code est stocké dans la base de données.
Il est déclenché sur un événement complété par un prédicat
(INSERT, UPDATE, DELETE).
Un déclencheur peut être actif ou non.
Si un déclencheur aboutit, la transaction qui l'a appelé peut
se poursuivre.
PL/SQL 25/11/2020
Description d'un trigger
80
Le traitement peut s'appliqué :
À l'ordre
Le trigger ne s'applique qu'une fois
À chaque ligne de la table concernée par l'événement
générateur
Le trigger s'applique autant de fois que nécessaire
PL/SQL 25/11/2020
Structure d'un déclencheur
81
Événement
Ordre
BEFORE
ROW
INSERT
UPDATE Table
AFTER DELETE
PL/SQL 25/11/2020
Eléments constitutifs
82
CREATE OR REPLACE TRIGGER myFirstTrigger
BEFORE UPDATE OF ename ON emp
FOR EACH ROW
WHEN([Link] = ‘Mabrouk’)
BEGIN
DBMS_OUTPUT.ENABLE(20000);
DBMS_OUTPUT.PUT_LINE(:[Link]||’ ‘||:[Link]);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
SQL> UPDATE emp
SET ename = 'Durand'
WHERE empno = 7839;
SQL> Sami Durand
PL/SQL 25/11/2020
Résolution multi-événements
83
Un Trigger peut répondre à plusieurs événements.
Dans ce cas, il est possible d'utiliser les prédicats
intégrés INSERTING, UPDATING ou DELETING pour
exécuter une séquence particulière du traitement en
fonction du type d'événement.
PL/SQL 25/11/2020
Résolution multi-événements
84
CREATE OR REPLACE TRIGGER myFirstTrigger
AFTER UPDATE OR INSERT ON emp
FOR EACH ROW
BEGIN
DBMS_OUTPUT.ENABLE(20000);
IF INSERTING THEN
DBMS_OUTPUT.PUT_LINE(' INSERT ');
END IF;
IF UPDATING('ENAME') THEN
DBMS_OUTPUT.PUT_LINE(' UPDATED ' || :[Link]);
END IF;
END;
/
SQL> UPDATE emp SET ename = 'TOTO' WHERE empno = 7839;
UPDATED TOTO
1 row updated.
PL/SQL 25/11/2020
Typologie d'un Trigger
85
BEFORE AFTER
BEFORE UPDATE ligne AFTER UPDATE ligne
BEFORE DELETE ligne AFTER DELETE ligne
BEFORE INSERT ligne AFTER INSERT ligne
BEFORE UPDATE ordre AFTER UPDATE ordre
BEFORE DELETE ordre AFTER DELETE ordre
BEFORE INSERT ordre AFTER INSERT ordre
PL/SQL 25/11/2020
Mise hors-service d'un Trigger
86
ALTER TRIGGER myTrigger DISABLE;
ALTER TABLE maTable
DISABLE ALL TRIGGERS;
ALTER TRIGGER tonTrigger ENABLE;
ALTER TABLE taTable
ENABLE ALL TRIGGERS;
DROP TRIGGER ceTrigger;
PL/SQL 25/11/2020
USER_TRIGGERS
87
SQL> desc user_triggers
Name Null? Type
----------------------------------------------------- -------- --------------
TRIGGER_NAME VARCHAR2(30)
TRIGGER_TYPE VARCHAR2(16)
TRIGGERING_EVENT VARCHAR2(227)
TABLE_OWNER VARCHAR2(30)
BASE_OBJECT_TYPE VARCHAR2(16)
TABLE_NAME VARCHAR2(30)
COLUMN_NAME VARCHAR2(4000)
REFERENCING_NAMES VARCHAR2(128)
WHEN_CLAUSE VARCHAR2(4000)
STATUS VARCHAR2(8)
DESCRIPTION VARCHAR2(4000)
ACTION_TYPE VARCHAR2(11)
TRIGGER_BODY LONG
PL/SQL 25/11/2020