PLSQL Triggers 151215134150
PLSQL Triggers 151215134150
PLSQL Triggers 151215134150
Pourquoi PL/SQL ?
2 PL/SQL et Triggers
Principales caractéristiques de PL/SQL
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 ou 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
3 PL/SQL et Triggers
Utilisation de PL/SQL
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
Ex : Forms et Report
4 PL/SQL et Triggers
Normalisation du language
Langage spécifique à Oracle
Tous les SQBG ont un langage procédural
TransacSQL pour SQLServer,
PL/pgSQL pour Postgresql
Procédures stockées pour MySQL depuis 5.0
Tous les langages L4G des différents SGBDs se
ressemblent
5 PL/SQL et Triggers
Utilisation de PL/SQL
Le PL/SQL peut être utilisé sous 3 formes
Un bloc de code, exécuté comme une unique commande SQL,
via un interpréteur standard (SQL+ ou iSQL*PLus)
un fichier de commande PL/SQL
un programme stocké(procédure, fonction, package ou trigger)
6 PL/SQL et Triggers
Le langage PL/SQL
Blocs
8 PL/SQL et Triggers
Structure d’un programme PL/SQL
DECLARE
-- définition des variables
BEGIN
-- code du programme
EXCEPTION
-- code de gestion des erreurs
END;
9 PL/SQL et Triggers
Déclaration, initialisation des variables
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és avant d’être utilisés
10 PL/SQL et Triggers
Déclaration, initialisation des variables
Déclaration et initialisation
Nom_variable type_variable := valeur;
Initialisation
Nom_variable := valeur;
11 PL/SQL et Triggers
Initialisation de variables
12 PL/SQL et Triggers
SELECT … INTO …
13 PL/SQL et Triggers
Le type de variables
VARCHAR2
Exemple:
NUMBER(long,dec)
Exemple:
14 PL/SQL et Triggers
Le type de variables (2)
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-2003:13:01’,’DD-MON-
YYYY:HH24:MI’);
BOOLEAN
TRUE, FALSE ou NULL
15 PL/SQL et Triggers
Déclaration %TYPE et %ROWTYPE
On peut déclarer qu’une variable est du même type
qu’une colonne d’une table ou (ou qu’une autre variable) :
Exemple :
nom emp.nome.%TYPE;
Une variable peut contenir toutes les colonnes d’une
ligne d’une table
Exemple :
employe emp%ROWTYPE;
déclare que la variable employe contiendra une ligne de la table emp
16 PL/SQL et Triggers
Exemple d’utilisation
DECLARE
employe emp%ROWTYPE;
nom emp.nome.%TYPE;
BEGIN
SELECT * INTO employe
FROM emp
WHERE matr= 900;
nom := employe.nome;
employe.dept:= 20;
…
INSERT into emp VALUES employe;
END
17 PL/SQL et Triggers
Commentaires
/* Pour plusieurs
lignes */
18 PL/SQL et Triggers
PL /SQL : les principales
commandes
Test conditionnel
IF-THEN
IF l_date > ’11-APR-03’ THEN
l_salaire := l_salaire * 1.15;
END IF;
IF-THEN-ELSE
IF l_date > ’11-APR-03’ THEN
l_salaire := l_salaire * 1.15;
ELSE l_salaire := l_salaire * 1.05;
END IF;
20 PL/SQL et Triggers
Test conditionnel
IF-THEN-ELSIF
IF l_nom = MOHAMED’ THEN
l_salaire := l_salaire * 1.15;
ELSIF l_nom = ‘AHMED’ THEN
l_salaire := l_salaire * 1.05;
END IF;
CASE
CASE sélecteur
WHEN expression1 THEN résultat1
WHEN expression2 THEN résultat2
ELSE résultat3
END;
21 PL/SQL et Triggers
Test conditionnel
Exemple :
val := CASE os
WHEN ‘WINDOWS’ THEN ‘MICROSOFT’
WHEN ‘LEOPARD’ THEN ‘APPLE’
ELSE ‘Unix’
END;
22 PL/SQL et Triggers
Les boucles
LOOP
instructions exécutables;
END LOOP;
23 PL/SQL et Triggers
Les boucles
LOOP
instructions;
END LOOP;
24 PL/SQL et Triggers
Affichage
25 PL/SQL et Triggers
Exemple
26 PL/SQL et Triggers
Exemple
DECLARE
nb integer;
BEGIN
delete from emp where matr in (600, 610);
nb := sql%rowcount; --curseur sql
dbms_output.put_line('nb = ' || nb);
END;
27 PL/SQL et Triggers
Exemple
DECLARE
compteur number(3);
i number(3);
BEGIN
select count(*) into compteur from clients;
FOR i IN 1..compteur LOOP
dbms_output.put_line('Nombre : ' || i );
END LOOP;
END;
28 PL/SQL et Triggers
Les curseurs
Les curseurs
30 PL/SQL et Triggers
Les curseurs
Tous les curseurs ont des attributs que l’utilisateur peut
utiliser
%ROWCOUNT: nombre de lignes traitées par le
curseur
%FOUND: vrai si au moins une ligne a été traitée par la
requête ou le dernier fetch
%NOTFOUND: vrai si aucune ligne n’a été traitée par
la requête ou le dernier fetch
%ISOPEN: vrai si le curseur est ouvert (utile seulement
pour les curseurs explicites)
31 PL/SQL et Triggers
Les curseurs
Les curseurs implicites
Les curseurs implicites sont tous nommés SQL
Exemple :
DECLARE
nb_lignes integer;
BEGIN
delete from emp where dept= 10;
nb_lignes:= SQL%ROWCOUNT;
…
32 PL/SQL et Triggers
Les curseurs
Les curseurs explicites
33 PL/SQL et Triggers
Les curseurs
Les curseurs explicites
DECLARE
nom varchar2(30);
CURSOR c_nom_clients IS
SELECT nom,adresse FROM clients;
BEGIN
FOR le_client IN c_nom_clients
LOOP
dbms_output.put_line('Employé: ' ||
UPPER(le_client.nom) ||' Ville : '|| le_client.adresse);
END LOOP;
END;
34 PL/SQL et Triggers
Les curseurs
Curseurs paramétrés
35 PL/SQL et Triggers
Les curseurs
Curseurs paramétrés
DECLARE
CURSOR c(p_dept integer) is
select dept, nome from emp where dept= p_dept;
BEGIN
FOR employe in c(10)LOOP
dbms_output.put_line(employe.nome);
END LOOP;
FOR employe in c(20) LOOP
dbms_output.put_line(employe.nome);
END LOOP;
END;
41 PL/SQL et Triggers
Les exceptions Utilisateur
42 PL/SQL et Triggers
Exemple d’exception utilisateur
DECLARE
salaire numeric(8,2);
salaire_trop_bas EXCEPTION;
BEGIN
select sal into salaire from emp where matr= 50;
if salaire < 300 then
RAISE salaire_trop_bas;
end if;
EXCEPTION
WHEN salaire_trop_bas THEN
dbms_output.put_line(‘Salaire trop bas’);
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
END;
43 PL/SQL et Triggers
Exemple d’exception utilisateur
ACCEPT X PROMPT (‘Veuillez saisir la matricule’);
DECLARE
--identifiant cmd.id%TYPE;
CURSOR MON_CURSEUR(&X integer) IS
select * from cmd,emp where emp.matricule=X
AND emp.id_client = cmd.id_client;
BEGIN
--select id_client into identifiant from emp where matr= X;
FOR commande in MON_CURSEUR(&X)LOOP
dbms_output.put_line(commande.libelle);
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line(‘Pas de commandes trouvées.’);
END;
44 PL/SQL et Triggers
Procédures et Fonctions
Bloc anonyme ou nommé
46 PL/SQL et Triggers
Procédures sans paramètres
create or replace procedure list_nom_clients
IS
BEGIN
DECLARE
nom varchar2(30);
CURSOR c_nom_clients IS select nom,adresse from clients;
BEGIN
FOR le_client IN c_nom_clients LOOP
dbms_output.put_line('Employé: '
|| UPPER(le_client.nom)
||' Ville : '
|| le_client.adresse);
END LOOP;
END;
END;
47 PL/SQL et Triggers
Procédures avec paramètre
create or replace procedure list_nom_clients
(ville IN varchar2,
IN : en lecture seule
result OUT number) OUT : en écriture seule
IS IN OUT : en lecture/écriture
BEGIN
DECLARE
--CURSOR c_nb_clients IS
select count(*) INTO nombre
from clients where adresse=ville;
BEGIN
result := nombre – 5;
RETURN result;
END;
END;
48 PL/SQL et Triggers
Récupération des résultats sous SQL+
Déclarer une variable
Visualisation du résultat
SQL> print
49 PL/SQL et Triggers
Fonctions sans paramètres
create or replace function nombre_clients
return number
IS Déclaration du type de retour de la
BEGIN fonction
DECLARE
i number;
CURSOR get_nb_clients IS select count(*) from clients;
BEGIN
open get_nb_clients;
fetch get_nb_clients INTO i;
return i;
END;
END;
50 PL/SQL et Triggers
Fonctions avec paramètres
Seuls les paramètres IN (en lecture
seule) sont autorisés pour les fonctions
Create or replace
Function euro_to_fr(somme IN number)
return number
IS
taux constant number:= 6.55957;
BEGIN
return somme * taux;
END;
51 PL/SQL et Triggers
Procédures et fonctions
52 PL/SQL et Triggers
Compilation, exécution et utilisation
Compilation
Sous SQL*PLUS, il faut taper une dernière ligne contenant
«/»pour compiler une procédure ou une fonction
Exécution
Sous SQL*PLUS on exécute une procédure PL/SQL avec la
commande EXECUTE :
EXECUTE nomProcédure(param1, …);
Utilisation
Les procédures et fonctions peuvent être utilisées dans
d’autres procédures ou fonctions ou dans des blocs PL/SQL
anonymes
Les fonctions peuvent aussi être utilisées dans les requêtes
SQL
53 PL/SQL et Triggers
Triggers
Triggers
Création de triggers
Triggers ou déclencheurs
E(vènement)-C(ondition)-A(ction)
56 PL/SQL et Triggers
Différents type de triggers
Trigger Ordre
Before, After
Trigger Ligne
For Each Row
Before, After, Instead of
57 PL/SQL et Triggers
Création de triggers
Exemple :
CREATE TRIGGER nom
BEFORE DELETE OR INSERT OR UPDATE ON
table
FOR EACH ROW
WHEN (new.empno>0)
DECLARE ............ <<<<déclarations>>>>
BEGIN
............ <<<< bloc d'instructions PL/SQL>>>>
END;
58 PL/SQL et Triggers
Le nom du trigger
doit être unique dans un même schéma
59 PL/SQL et Triggers
Option BEFORE/AFTER
elle précise le moment de l'exécution du trigger
60 PL/SQL et Triggers
Définition du trigger
Elle comprend le type d'instruction SQL qui déclenche le
trigger :
DELETE, INSERT, UPDATE
On peut en avoir une, deux ou les trois.
Pour UPDATE, on peut spécifier une liste de colonnes. Dans
ce cas, le trigger ne se déclenchera que si l'instruction UPDATE
porte sur l'une au moins des colonnes précisée dans la liste.
S'il n'y a pas de liste, le trigger est déclenché pour toute
instruction UPDATE portant sur la table.
61 PL/SQL et Triggers
Définition du trigger
62 PL/SQL et Triggers
Types de triggers
63 PL/SQL et Triggers
ORACLE propose deux types de triggers
64 PL/SQL et Triggers
Types de triggers
Pour les triggers lignes, on peut introduire une restriction
sur les lignes à l'aide d'une expression logique SQL : c'est
la clause WHEN :
Cette expression est évaluée pour chaque ligne affectée par le
trigger.
Le trigger n'est déclenché sur une ligne que si l'expression
WHEN est vérifiée pour cette ligne.
L'expression logique ne peut pas contenir une sous-question.
Par exemple, WHEN (new.empno>0) empêchera l'exécution
du trigger si la nouvelle valeur de EMPNO est 0, négative ou
NULL.
65 PL/SQL et Triggers
Triggers
Le corps du trigger est un bloc PL/SQL :
66 PL/SQL et Triggers
Les noms de corrélation
Dans un trigger ligne, on doit pouvoir accéder aux ancienne
et nouvelle valeurs de colonne de la ligne.
Les noms de corrélation permettent de désigner ces deux
valeurs : un nom pour l'ancienne et un pour la nouvelle.
Si l'instruction de déclenchement du trigger est INSERT,
seule la nouvelle valeur a un sens.
Si l'instruction de déclenchement du trigger est DELETE,
seule l'ancienne valeur a un sens.
67 PL/SQL et Triggers
Les noms de corrélation
La nouvelle valeur est appelée
:new.colonne
L'ancienne valeur est appelée
:old.colonne
Exemple : IF :new.salaire < :old.salaire ........
68 PL/SQL et Triggers
L’option REFERENCING
Si une table s'appelle NEW ou OLD, on peut utiliser
REFERENCING pour éviter l'ambiguïté entre le nom de
la table et le nom de corrélation.
Exemple :
CREATE TRIGGER nomtrigger
BEFORE UPDATE ON new
REFERENCING new AS newnew
FOR EACH ROW
BEGIN
:newnew.colon1:= TO_CHAR(:newnew.colon2);
END;
69 PL/SQL et Triggers
Les prédicats conditionnels INSERTING,
DELETING et UPDATING
Quand un trigger comporte plusieurs instructions de
déclenchement (par exemple INSERT OR DELETE OR
UPDATE), on peut utiliser des prédicats conditionnels
(INSERTING, DELETING et UPDATING) pour
exécuter des blocs de code spécifiques pour chaque
instruction de déclenchement.
70 PL/SQL et Triggers
Les prédicats conditionnels INSERTING,
DELETING et UPDATING
Exemple :
CREATE TRIGGER ...
BEFORE INSERT OR UPDATE ON employe
.......
BEGIN
......
IF INSERTING THEN ....... END IF;
IF UPDATING THEN ........ END IF;
......
END;
71 PL/SQL et Triggers
Les prédicats conditionnels INSERTING,
DELETING et UPDATING
UPDATING peut être suivi d'un nom de colonne :
CREATE TRIGGER ...
BEFORE UPDATE OF salaire, commission ON employe
.......
BEGIN
......
IF UPDATING ('salaire') THEN ........ END IF;
......
END;
72 PL/SQL et Triggers
Instructions SQL autorisées
les instructions du LMD sont autorisées
73 PL/SQL et Triggers
Triggers
Ordre de traitement des lignes
On ne peut pas gérer l'ordre des lignes traitées par une
instruction SQL.
On ne peut donc pas créer un trigger qui dépende de l'ordre
dans lequel les lignes sont traitées.
Triggers en cascade
Un trigger peut provoquer le déclenchement d'un autre trigger.
ORACLE autorise jusqu'à 32 triggers en cascade à un moment
donné.
74 PL/SQL et Triggers
Triggers
Conditions nécessaires pour créer un trigger
il faut avoir le privilège CREATE TRIGGER
il faut soit posséder la table sur laquelle on veut définir un
trigger, soit posséder le privilège ALTER sur la table sur
laquelle on veut définir le trigger, soit posséder le privilège
ALTER ANY TABLE
Modification de triggers
Pour modifier un trigger, on refait une instruction CREATE
TRIGGER suivie de OR REPLACE ou bien on supprime le
trigger (DROP TRIGGER nomtrigger) et on le crée à
nouveau.
75 PL/SQL et Triggers
Activation d’un trigger
Un trigger peut être activé ou désactivé.
S’il est désactivé, ORACLE le stocke mais l’ignore.
On peut désactiver un trigger si :
il référence un objet non disponible
on veut charger rapidement un volume de données important
ou recharger des données déjà contrôlées.
Par défaut, un trigger est activé dès sa création.
76 PL/SQL et Triggers
Activation d’un trigger
Pour désactiver un trigger, on utilise l’instruction ALTER
TRIGGER avec l’option DISABLE :
ALTER TRIGGER nomtrigger DISABLE;
On peut désactiver tous les triggers associés à une table
avec la commande :
ALTER TABLE nomtable DISABLE ALL TRIGGERS;
A l’inverse on peut réactiver un trigger :
ALTER TRIGGER nomtrigger ENABLE;
ou tous les triggers associés à une table :
ALTER TABLE nomtable ENABLE ALL TRIGGERS;
77 PL/SQL et Triggers
Recherche d’information sur les triggers
78 PL/SQL et Triggers
La procédure raise_application_error
La procédure raise_application_error
( error_number, error_message )
error_number doit être un entier compris entre -20000 et -
20999
error_message doit être une chaîne de 500 caractères
maximum.
Quand cette procédure est appelée, elle termine le trigger,
défait la transaction (ROLLBACK), renvoie un numéro d'erreur
défini par l'utilisateur et un message à l'application.
79 PL/SQL et Triggers
Gestion des exceptions
Si une erreur se produit pendant l'exécution d'un trigger,
toutes les mises à jour produites par le trigger ainsi que
par l'instruction qui l'a déclenché sont défaites.
On peut introduire des exceptions en provoquant des
erreurs.
Une exception est une erreur générée dans une procédure
PL/SQL.
Elle peut être prédéfinie ou définie par l'utilisateur.
Un bloc PL/SQL peut contenir un bloc EXCEPTION gérant les
différentes erreurs possibles avec des clauses WHEN.
Une clause WHEN OTHERS THEN ROLLBACK; gère le cas
des erreurs non prévues.
80 PL/SQL et Triggers
Exceptions prédéfinies – quelques exemples
NO_DATA_FOUND
cette exception est générée quand un SELECT INTO ne retourne
pas de lignes
DUP_VAL_ON_INDEX
tentative d'insertion d'une ligne avec une valeur déjà existante pour
une colonne à index unique
ZERO_DIVIDE
division par zéro
etc
81 PL/SQL et Triggers
Quelques exemples
employe(numserv,....)
service(numserv,...)
/* vérifier que le service de l'employé existe bien */
CREATE TRIGGER verif_service
BEFORE INSERT OR UPDATE OF numserv ON employe
FOR EACH ROW WHEN (new.numserv is not null)
DECLARE
noserv integer;
BEGIN
noserv:=0;
SELECT numserv
INTO noserv
FROM SERVICE
WHERE numserv=:new.numserv;
IF (noserv=0)
82 PL/SQL et Triggers
Quelques exemples (suite)
THEN raise_application_error(-20501, 'N° de service non
correct');
END IF;
END;
employe(salaire,....)
/* mettre une valeur par défaut si le champ ne contient rien */
/* affecter 240 au salaire d'un employe qui n'en a pas */
CREATE TRIGGER smic
BEFORE INSERT OR UPDATE OF salaire ON employe
FOR EACH ROW WHEN (new.salaire is null)
BEGIN
SELECT 240
INTO :new.salaire
FROM employe;
END;
83 PL/SQL et Triggers
Quelques exemples
employe(numemp,salaire,grade,...)
grille(grade,salmin,salmax)
/* vérifier le salaire d'un employé */
/* s'assurer que le salaire est compris dans les bornes correspondant au
grade de l'employé */
CREATE TRIGGER verif_grade_salaire
BEFORE INSERT OR UPDATE OF salaire, grade ON employe
FOR EACH ROW
DECLARE
minsal number;
maxsal number;
BEGIN
/* retrouver le salaire minimum et maximum du grade */
SELECT salmin,salmax
INTO minsal, maxsal
FROM grille
84 PL/SQL et Triggers
Quelques exemples (suite)
WHERE grade= :new.grade;
/* s'il y a un problème, on provoque une erreur */
IF (:new.salaire<minsal OR :new.salaire>maxsal)
THEN
raise_application_error (-20300,'Salaire‘||TO_CHAR
(:new.salaire)||'incorrect pour ce grade');
EXCEPTION
WHEN no_data_found THEN
raise_application_error(-20301,'Grade incorrect');
END;
85 PL/SQL et Triggers