LES PROCEDURES ET
FONCTIONS STOCKEES
LES
TRIGGERS
1.
ETUDE DU LANGAGE PL/SQL
1.1.
Introduction
Sql est un langage complet pour travailler sur
une base de données, mais il ne comporte pas d'instructions
procédurales.
PL/SQL comprend quant à lui :
·
la partie LMD de SQL (Select,
Update, Insert, Delete),
·
la gestion des transactions (Commit,
Rollback ...),
·
les fonctions de manipulation telles
MONTH, YEAR …,
·
plus une partie procédurale
(affectation, calculs, IF, WHILE, ...),
PL/SQL va en particulier nous permettre de créer
de nouveaux objets dans la base de données : :
procédures et fonctions ainsi que triggers
(‘déclencheurs’). Ces objets sont des unités de
traitements :
-
les procédures et
fonctions stockées permettent d’effectuer certains
traitements lourds ou confidentiels sur le serveur ; elles
permettent aussi de factoriser les traitements dans les
architectures client/serveur (plusieurs clients utilisent la même
procédure).
-
les triggers permettent de
maintenir dynamiquement la cohérence de la base de données et de
décharger les programmes de cette tâche ; exemple : la
mise à jour d’une table déclenche automatiquement une mise à jour
sur une autre table.
De plus, nous verrons que ces traitements
stockés dans la base de données permettent d’alléger le trafic sur
le réseau.
1.2. Structure d'un bloc
Pl/SQL
La structure d'un bloc est la suivante
:
BEGIN
DECLARE …
Instructions SQL et PL/SQL;
Peut
éventuellement contenir un autre bloc
Pl/Sql
END |
Remarque :
Chaque instruction PL/SQL ou SQL de n'importe
quelle section doit se terminer par un ';'.
La
structuration des instructions en blocs procure une plus grande
lisibilité des traitements.
Exemple de
bloc PL/SQL :
DELIMITER
|;
DECLARE code_prod
int;
DECLARE qte_stock int;
Select quantite,
codeprod
into qte_stock,
code_prod
from
inventaire
where
produit='raquette tennis';
-- contrôle du stock suffisant --
If qte_stock
> 0
then
update inventaire
set quantite=quantite-1
where produit='raquette tennis';
insert into achat
values (code_prod, CURRENT_DATE);
end
if;
END |
Les déclarations
PL/SQL
La partie
déclarative dans un bloc PL/SQL, peut comporter les trois types de
déclarations suivants.
·
déclaration des variables et des
constantes,
·
déclaration de curseurs,
·
déclaration des exceptions. (non
traité ici)
1.3. L'affectation des
variables PL/SQL
1.3.1. Principaux types de
données
Chaque variable
ou constante utilisée dans un bloc PL/SQL, possède un type de
données qui détermine son format de stockage et sa plage de valeurs
valides.
Les types de
données offerts par PL/SQL sont d'abord les types offerts pour les
colonnes des tables MySql auxquels s'ajoutent d'autres types tel le
type boolean.
Une constante
est définie comme une variable sauf qu’on y ajoute le mot-clé
CONSTANT, le contenu est alors non modifiable.
Les variables
et constantes sont précédées du mot DECLARE et utilise la syntaxe
suivante :
Nomdonnée [CONSTANT]
nomtype
Remarque
:
·
L'attribut constant permet de
figer l'affectation.
Deux
possibilités d'affectation sont disponibles :
L'initialisation d'une variable se fait de la
façon suivante : SET nomvariable = valeur
;
Exemple : SET A
= A + 1 ;
L'initialisation peut également se faire par la
clause INTO d'une requête SQL :
SELECT nomcli FROM client
INTO nom
WHERE numcli =
104 ;
L'affectation
par la clause INTO s'effectue sous certaines conditions.
Si le Select
retourne une et une seule ligne, l'affectation s'effectue
correctement.
Par
contre,
. Si le
Select retourne 0 ligne : è
une erreur PL/SQL est
générée.
. Si le
Select retourne plusieurs lignes :
è
une erreur PL/SQL est
générée.
Remarque
: .
Entre BEGIN et END, les instructions
select ne servent qu'à alimenter des variables, elles ne provoquent
aucun affichage à l'écran. Si le bloc d'instructions a pour but
d'afficher un résultat à l'utilisateur, il faudra insérer le
résultat dans une table temporaire à l'intérieur du bloc et faire
un select de la table résultat à l'extérieur du bloc. La table
temporaire (nommée resultat dans l'exemple) devra être créée avant
l'exécution du bloc.
Exemple
On va
utiliser la table emp : Emp(empno, ename, job,
mgr, hiredate, sal , comm, #deptno)
DELIMITER
|;
BEGIN
DECLARE
vjob varchar(15);
DECLARE vnom varchar(30);
DECLARE message varchar(50);
select job
into vjob
from emp
where ename='MARTIN';
-- Traitement selon le job et alimentation d'un champ message
pour savoir ce qui a été
effectué :
. .
.
insert into resultat
values (message);
END |
1.4. Les structures
conditionnelles
1.4.1. L'instruction IF … THEN … END IF
IF THEN
IF condition
THEN
instruction ou séquence d'instructions;
END IF;
Remarque : le then peut être placé à côté du
if.
Il faut
préciser que les instructions peuvent être écrites sur 1 ou
plusieurs lignes, on peut même écrire plusieurs instructions sur
une même ligne, le principal étant de placer un point-virgule à la
fin de chaque instruction.
IF THEN ELSE
IF condition
THEN
instruction ou
séquence d'instructions;
ELSE
instruction ou séquence d'instructions;
END IF;
Remarques
:
. Il est
possible d'imbriquer les IF.
. La condition
peut utiliser des variables ainsi que les opérateurs suivants : =,
<, >, <=, >=, <>, IS NULL, IS NOT
NULL.
IF
condition1
THEN
statement1;
ELSE
IF condition2
THEN
statement2;
ELSE
IF condition3
THEN
statement3;
END
IF;
END
IF;
END
IF;
DELIMITER
|;
BEGIN
DECLARE
vjob varchar(15);
DECLARE vnom varchar(40);
DECLARE message varchar(100);
SET vnom = 'MARTIN';
Select job
into
vjob
from
emp
where
ename=vnom;
-- traitement selon le
job
If vjob is NULL
then
SET message = vnom || ' est sans
travail';
else
if
vjob = 'SALESMAN'
then
update emp
set comm=1000
where ename=vnom;
SET message = vnom , ' a 1000 Frs de commission';
else
update emp
set comm=0
where ename=vnom;
SET message = vnom , ' n''a pas de commission ';
end if;
end
if;
insert into resultat values (message);
END |
1.4.2. L'instruction CASE
Cette syntaxe,
qui diffère du CASE normal , va permettre d' effectuer une action
si une condition est vérifiée.
Il existe deux
types de syntaxes : la première se rapprochant de
l'utilisation du 'SWITCH' dans les langages de programmation,
et
l'autre étant
équivalente à une succession de 'IF ... ELSE IF ... ELSE IF ...
ELSE ...' .
Exemple
Syntaxe1 :
…
CASE var
WHEN 1 THEN SELECT 'Je suis 1';
WHEN 2 THEN SELECT 'Je suis 2';
ELSE SELECT 'Je suis autre chose que 1 et
2';
END CASE;
END |
Dans ce cas ,
la variable 'var' est comparée à chaque cas rencontré, et si aucune
des valeurs n'est vérifiée dans les WHEN, alors
l'instruction
après ELSE sera exécutée.
Exemple
Syntaxe2 :
…
BEGIN
CASE
WHEN var = 1 THEN SELECT 'Je suis 1';
WHEN var = 2 THEN SELECT 'Je suis 2';
ELSE SELECT 'Je suis autre chose que 1 et
2';
END CASE;
END |
Dans ce cas ,
la variable 'var' n'est pas évaluée ; au lieu de cela, nous
passons d' un bloc de WHEN à l'autre en comparant si une expression
est vraie. Si c'est le cas, nous exécutons alors l'instruction qui
la suit, sinon, si aucune des expressions n'est vérifiée, alors
l'instruction du ELSE est effectuée.
1.5. Les structures
itératives
PL/SQL nous offre la possibilité d'effectuer des
traitements itératifs grâce à 3 types d'instructions : LOOP, REPEAT
et WHILE.
1.5.1. L'instruction LOOP
C'est une
structure de boucle qui répète un bloc d'instructions tant qu'elle
ne rencontre pas une instruction LEAVE pour l'arrêter.
Exemple :
CREATE PROCEDURE
loop1()
BEGIN
DECLARE i INT
DEFAULT 0;
LOOP
SET i := i + 1;
SELECT i;
END LOOP;
END |
Aucune
condition d'arrêt n'a été rencontrée, et une erreur ne sera
rencontrée que lorsque la valeur maximale val i de INT sera
rencontrée, soit le chiffre : 2 147 483 647.
Il est possible
d'arrêter brusquement la boucle à l'aide d'une instruction du type
: LEAVE nom_label
Exemple d'arrêt
lorsqu'un label est présent :
CREATE PROCEDURE
loop1()
BEGIN
DECLARE i INT
DEFAULT 0;
je_suis_un_label:
LOOP
SET i := i + 1;
SELECT i;
IF i = 10 THEN
LEAVE je_suis_un_label;
END IF;
END LOOP
je_suis_un_label;
END |
Le code
s'exécute, et si i vaut 10, alors la boucle est arrêtée grâce au
nom du label.
Le label
indiqué avant l'instruction de boucle doit être le même que celui
qui la termine.
1.5.2. L'instruction REPEAT
Ce type de
boucle permet de répéter un bloc d'instructions jusqu'à ce qu'une
condition soit vérifiée.
Exemple :
CREATE PROCEDURE
repeat1()
BEGIN
DECLARE i INT
DEFAULT 0;
REPEAT
SET i := i + 1;
SELECT i;
UNTIL i = 10 END
REPEAT;
END |
Une boucle est
lancée jusqu'à ce que la valeur de variable locale i soit égale à
10.
Plus court que
la version avec LOOP pour un résultat identique.
Les labels sont
supportés de la même manière qu'avec LOOP et prennent donc la même
syntaxe.
1.5.3. L'instruction
WHILE
C'est une
structure de type boucle qui répète un bloc d'instructions tant
qu'une condition est vraie.
Exemple :
CREATE PROCEDURE
while1()
BEGIN
DECLARE i INT
DEFAULT 0;
WHILE i < 10
DO
SET i := i + 1;
SELECT i;
END
WHILE;
END |
Tant que la
variable locale i est inférieure à 10, le bloc d'instructions est
exécuté.
1.5.4. L'instruction ITERATE
ITERATE ne peut
être utilisée qu'à l'intérieur d'une boucle LOOP, REPEAT ou WHILE
et signifie : "exécute encore une fois la boucle".
Exemple avec LOOP :
CREATE PROCEDURE
loop1()
BEGIN
DECLARE i INT
DEFAULT 0;
je_suis_un_label:
LOOP
SET i := i + 1;
SELECT i;
IF i < 10 THEN ITERATE je_suis_un_label;
END IF;
SELECT 'Je suis ', i;
LEAVE je_suis_un_label;
END LOOP je_suis_un_label;
END |
La boucle se
lance, fait ses instructions , arrive sur la condition qui vérifie
que la variable locale i est inférieure à 10 ; Si c'est le cas, la
boucle est relancée.
Exemple avec REPEAT :
CREATE PROCEDURE
repeat1()
BEGIN
DECLARE i INT
DEFAULT 0;
je_suis_un_label:
REPEAT
SET i := i + 1;
SELECT i;
IF i < 10 THEN ITERATE je_suis_un_label;
END IF;
SELECT 'Je suis ', i;
UNTIL i < 20
END REPEAT je_suis_un_label;
END |
Exemple avec WHILE :
CREATE PROCEDURE
while1()
BEGIN
DECLARE i INT
DEFAULT 0;
je_suis_un_label:
WHILE i < 10 DO
SET i := i + 1;
SELECT i;
IF i < 10 THEN ITERATE je_suis_un_label;
END IF;
SELECT 'Je suis ', i;
END WHILE je_suis_un_label;
END|
Préambule : La
validation, l’annulation et la notion de
transaction
Nous avons vu que par défaut, toute erreur
non interceptée ainsi que toute erreur interceptée pour laquelle le
bloc d’exception contient raise_application_error provoquent
l’annulation de toutes les mises à jour (au sens large). Dans les
autres cas, les mises à jour sont validées (c’est à dire
enregistrées).
Il est possible
de demander explicitement la validation des mises à jour à
n’importe quel(s) endroit(s) d’un bloc Pl/Sql, il suffit pour cela
de placer l’instruction commit ; à l’endroit (ou aux
endroits) souhaité (s).
Toute erreur
non interceptée ou toute erreur interceptée et renvoyée avec
raise_application_error provoquera alors uniquement l’annulation
des mises à jour effectuées depuis le dernier commit.
Pour demander
explicitement l’annulation des mises à jour à n’importe quel
endroit du bloc, il faut placer l’instruction
rollback ;
Quand
l’exécution d’un bloc Pl/Sql démarre, démarre alors une
transaction (il y a une instructionimplicite de démarrage de
transaction) et quand l’exécution du bloc prend fin, il y a une
instruction implicite de fin de transaction.
Une
transaction est un ensemble indivisible
d’opérationsc’est à dire
que l’ensemble des opérations sera validé ou annulé.
Par défaut, MySql considère tout le bloc
comme une seule transaction car s’il y a une erreur non interceptée
ou bien une erreur interceptée et renvoyée, l’ensemble des
opérations est annulé sinon l’ensemble des opérations est
validé.
Le développeur
peut faire plusieurs transactions à l’intérieur du bloc, en effet
s’il place un commit ou un rollback dans le bloc, cela met fin à la
transaction en cours et une autre transaction démarre.
Cette notion de transaction est très
importante (par exemple pour garantir le débit/crédit lors
d’opérations sur des comptes).
2.
LES PROCEDURES ET FONCTIONS STOCKEES
2.1. Définition et
utilisation
Les procédures
ou fonctions stockées sont des blocs PL/SQL nommés
que l'on définit et stocke une seule fois dans la base.
Les procédures
ou fonctions stockées peuvent être paramétrées.
La notion de
procédure ou fonction stockée a été conçue dans l'esprit de grouper
un ensemble de commandes SQL avec des instructions procédurales,
pour constituer une unité de traitement pouvant être appelée à
partir de n'importe quel programme ou directement sous
MySql.
Intérêts d’une procédure ou fonction stockée au
niveau du développement :
-
une procédure ou fonction stockée
peut être appelée par plusieurs applications et elle reste
indépendante de la partie appelante :
ð
augmentation de la productivité lors
de l’écriture des applications,
ð
la recompilation d’une procédure ou
fonction n’exige pas la recompilation de l’ensemble du code de
l’application.
Intérêts d’une procédure lors de l’exécution de
traitements :
-
réduction du trafic sur le réseau
(le client envoie le nom de la procédure ou fonction à exécuter au
lieu d'envoyer tout le texte d'une commande SQL, ceci sera revu
dans le cours sur le client-serveur de traitements),
-
une procédure ou fonction est
compilée lors de son stockage dans la base : à l’exécution, elle
n'a plus à être compilée.
ð
gain de temps.
Intérêts d’une procédure ou fonction au niveau
de la sécurité :
-
une procédure ou fonction est un
objet de la base appartenant à un utilisateur : les mécanismes
de sécurité et de confidentialité fonctionnent (GRANT et
REVOKE),
-
l’accès à certaines tables peut
n’être autorisé qu’au travers des procédures et fonctions : un
utilisateur peut disposer d’autorisations d’exécution sur une
procédure ou fonction sans disposer d’autorisation sur les tables
manipulées par la procédure ou fonction è on peut faire l'analogie avec les vues excepté
qu'une vue est construite forcément sur un SELECT.
2.2. Les procédures
stockées
·
Ecriture d'une procédure
stockée
Version MySql :
CREATE PROCEDURE
nomprocedure [ (paramètres)]
-- bloc PL/Sql
BEGIN
[Déclaration des variables locales;]
Instructions SQL et PL/Sql;
END [nomprocedure];
Remarques :
·
Chaque paramètre est défini selon la
syntaxe suivante :
nomparametre [IN | OUT | IN OUT] type
IN : indique que le paramètre est passé en entrée (c'est le statut
par défaut),
OUT : indique que le paramètre est renseigné par la
procédure,
IN OUT : indique que le paramètre est en entrée-sortie.
·
Le corps de la procédure commence
par Begin et se termine par le mot-clé END suivi éventuellement par
le nom de la procédure.
Le corps d'une procédure comporte trois parties
:
- une partie déclarative qui est
facultative,
- une partie exécutable,
- une partie optionnelle pour la gestion des
erreurs.
·
La partie déclarative contient la
déclaration des variables locales. Le mot-clé DECLARE est
obligatoire devant chaque variable.
·
La partie exécutable doit au moins
comporter une instruction.
Exemple : Augmentation du salaire de l'employé
dont le n° est transmis, le montant à ajouter est également
transmis
Version MySql
:
CREATE PROCEDURE
AugmenterSalaire(IN NumSal double, montant double)
BEGIN
DECLARE SalaireActuel double;
Select sal
into SalaireActuel
From emp
Where empo = NumSal;
Update emp
set sal = sal + montant
Where empo = NumSal;
END |
Il n'y a aucun standard pour
l'écriture des procédures stockées en pseudo-code. On peut proposer
l'algorithme suivant pour la procédure ci-dessus :
PROCEDURE
AugmenterSalaire (données : NumSal : entier, montant :
réel)
SalaireActuel : réel
SalaireNull : Exception
DEBUT
Select sal
into SalaireActuel
From emp
Where empno =
NumSal
SI SalaireActuel =
NULL
ALORS
déclencher exception SalaireNull
SINON
Update emp
set sal = sal + montant
Where empno =
NumSal
FSI
EXCEPTION
SUIVANT
exception
NonTrouvé :
Envoyer l'erreur 'Employé inconnu'
SalaireNull :
Envoyer l'erreur 'Salaire non renseigné'
FSUIVANT
FIN
·
Création ou remplacement d'une
procédure stockée
En MySql, la création de la
procédure peut se faire sous l'onglet Sql. Il faut penser à changer
le délimitateur qui est ; par défaut. Mettre par exemple
|.
·
Mise au point d'une
procédure stockée
Un message est affiché en cas d'erreur. Sinon le
message "procédure créée…" est affiché.
·
Appel d'une procédure
stockée
Ex. : CALL
AugmenterSalaire(7369, 200);
. Dans un bloc pl/sql ou
dans une autre procédure ou fonction stockée
:
Ex.
:
. Avec des constantes en paramètres
:
BEGIN
CALL
AugmenterSalaire(7369,10.10);
…
END;
. Dans un programme hôte
:
Non étudié ici.
La suppression
est assurée par la commande suivante :
DROP PROCEDURE nomprocedure;
2.3. Les fonctions
stockées
La structure d'une fonction est identique à
celle d'une procédure, mais les fonctions possèdent une clause
RETURNS type en "entête" et au moins une clause
RETURN(valeur).
Tout ce qui a été dit concernant les droits pour
une procédure stockée est également valable pour les fonctions
stockées.
·
Ecriture d'une fonction
stockée
CREATE [OR REPLACE] FUNCTION
nomfonction [ (paramètres)]
RETURNS type
[DETERMINISTIC]
BEGIN
[Déclarations de variables locales;]
Instructions SQL et PL/Sql;
RETURN(Valeur);
END ;
Remarques :
Chaque
paramètre est défini selon la syntaxe suivante :
nomparametre [IN | OUT | IN OUT] type
Il est possible de placer plusieurs
return(valeur) dans le corps de la fonction. Un return(valeur)
provoque le retour immédiat à l'appelant avec une valeur de
retour.
Exemple : Calcul du nombre moyen d'années
d'ancienneté pour les employés exerçant le job transmis en
paramètre
DELIMITER |
CREATE
FUNCTION MoyenneAnc (jobsai VARCHAR(30)) RETURNS
float
DETERMINISTIC
BEGIN
DECLARE ancmoyen float;
select avg(YEAR(curdate()) - YEAR(hiredate))
into ancmoyen
from emp
where job = jobsai;
RETURN (ancmoyen);
END |
Il n'y a aucun standard pour
l'écriture des fonctions stockées en pseudo-code. On peut proposer
l'algorithme suivant pour la fonction ci-dessus :
FONCTION MoyenneAnc (donnée : jobsai :
chaîne de caractères) : réel
ancmoyen :
réel
DEBUT
select avg(YEAR(curdate()) - YEAR(hiredate))
into ancmoyen
from emp
where job = jobsai
·
Création ou remplacement d'une
fonction stockée
Idem procédure stockée.
·
Mise au point d'une
fonction stockée
Idem procédure stockée.
·
Appel à une fonction
stockée
SOUS MYSQL : SELECT
MoyenneAnc('CLERK');
·
Suppression d'une fonction
stockée
La suppression
est assurée par la commande suivante :
DROP FUNCTION nomfonction ;
3.
LES TRIGGERS (OU DECLENCHEURS)
*
Un trigger base de données est un
ensemble de traitements PL/Sql.
*
Un trigger base de données est
déclenché automatiquement par un ou plusieurs événements
prédéfinis,
il ne peut donc pas être appelé directement.
*
Un trigger base de données est
attaché à une et une seule table.
*
Si une table est supprimée, les
triggers base de données qui lui sont associés sont automatiquement
supprimés.
Un trigger base de données est identifié par
cinq caractéristiques :
1.
Un
séquencement,
BEFORE ou AFTER : on précise si le
trigger se déclenche avant ou après l'événement.
Les triggers BEFORE sont
généralement utilisés pour faire des contrôles.
Les triggers AFTER sont généralement
utilisés pour faire des mises à jour consécutives à l’ordre SQL
déclencheur.
2.
Un événement qui le
déclenche,
INSERT, UPDATE, DELETE : cet
événement concerne une et une seule table, celle-ci devra
être
précisée.
3.
Un
type,
par LIGNE : accès aux
informations de la ligne ayant déclenché le trigger et vérification
des valeurs par rapport aux autres lignes de la table.
4.
Les ordres du
traitement (bloc pl/sql).
Les combinaisons possibles sont les suivantes
:
Séquencement
|
Evénement
|
BEFORE
|
INSERT
|
|
UPDATE
|
|
DELETE
|
AFTER
|
INSERT
|
|
UPDATE
|
|
DELETE
|
CREATE OR REPLACE
TRIGGER nomtrigger
Séquencement (before ou after)
Evénement (insert, update ou
delete)
ON nom de la table
FOR EACH
ROW
BEGIN
ordres du traitement;
END [nomtrigger];
Remarques
:
q
UPDATE OF nomcolonne On nomtable :
permet d'indiquer que le trigger est déclenché uniquement en cas de
modification de la colonne stipulée.
q
Type : le type par défaut est par
ordre. Il faudra donc préciser le type uniquement si on souhaite la
vérification au niveau ligne (ce qui est le cas le plus fréquent),
pour cela, il faudra écrire : FOR EACH ROW.
q
Le bloc pl/sql ne peut pas contenir
d'instructions pour gérer les transactions (Commit,
Rollback).
Référencement des valeurs des colonnes
:
Pour référencer
l'ancienne et/ou la nouvelle valeur d'une colonne, on utilise deux
variables prédéfinies OLD et NEW.
|
OLD
|
NEW
|
INSERT
|
NULL
|
nouvelle
valeur
|
UPDATE
|
ancienne
valeur
|
nouvelle
valeur
|
DELETE
|
ancienne
valeur
|
NULL
|
L'accès à une colonne de :new
et de :old s’écrit respectivement :
new.nomcolonne
old.nomcolonne
Exemples :
Si on a l'ordre insert suivant :
insert into dept
values (90, 'Informatique', 'Immeuble
A');
Dans le trigger correspondant à
l'insertion dans la table dept, new.deptno vaudra 90, new.dname
vaudra Informatique et new.loc vaudra Immeuble A.
Si on a l'ordre update suivant :
update dept
set loc = 'Immeuble B'
where deptno=90;
Dans le trigger correspondant à la modification
dans la table dept, new.deptno vaudra 90, new.dname vaudra
Informatique et new.loc vaudra Immeuble B. old.deptno vaudra
90, old.dname vaudra Informatique et old.loc vaudra Immeuble
A.
Si on a l'ordre delete suivant :
delete dept
where deptno=90;
Dans le trigger correspondant à la suppression
dans la table dept, old.deptno vaudra 90, old.dname vaudra
Informatique et old.loc vaudra Immeuble B.
Déclenchement
d’erreurs :
Le trigger permet de vérifier la cohérence d’une
instruction SQL de mise à jour : Insert, Update ou Delete. Il
est souvent nécessaire de provoquer une erreur dans le trigger pour
empêcher cette mise à jour.
La commande permettant de déclencher une erreur
personnalisée est de type :
signal sqlstate "25000" set
message_text ="Votre message d'erreur""
"25000" est un exemple de numéro d'erreur. Il
faut juste choisir un nombre supérieur à 20000.
Exemple : trigger pour refuser l’insertion d’un
employé si sa commission ajoutée au total des commissions dépasse
le total autorisé :
-- Suppression du trigger ctrlcomm
si celui-ci existe
DROP TRIGGER IF EXISTS
ctrlcomm;
DELIMITER
|
-- Création
du trigger
CREATE TRIGGER ctrlcomm
BEFORE INSERT
ON emp FOR EACH
ROW
BEGIN
DECLARE totcomm float;
SELECT sum(comm)
INTO totcomm
FROM emp;
If (totcomm + new.comm) > 20000 then
signal sqlstate "32000" set message_text ="Erreur-Commission trop
importante"
end if;
end |
DELIMITER ;
Il n'y a aucun standard pour l'écriture des
triggers en pseudo-code. On peut proposer l'algorithme suivant pour
le trigger ci-dessus :
TRIGGER ctrlcomm
Déclenchement : avant insertion dans table
emp
Type trigger : niveau ligne
totcomm : réel
tot :
exception
DEBUT
select sum(comm)
into totcomm
from emp
SI totcomm + :new.comm > 20000
ALORS
Déclencher exception tot
FSI
EXCEPTION
SI exception = tot
ALORS
Envoyer
l'erreur "Erreur-Commission trop importante"
FSI
FIN
Remarque
Sur MySql, contrairement à Oracle
par exemple, un trigger base de données ne peut s'exécuter à la
fois en INSERT et/ou en UPDATE et/ou en DELETE
3.3 Création ou remplacement d'un
trigger
La création ou le remplacement d'un trigger dans
la base s'effectue sous l'onglet SQL. Le trigger (ou déclencheur)
est associé à une table. Sur les versions récentes de
PhpMyAdmin l'onglet <Déclencheur> propose une interface
graphique pour créer ou modifier les triggers.
DROP
TRIGGER nomtrigger ;
·
Implémentation des contraintes
sémantiques et donc refus des mises à jour (au sens large)
incohérentes,
·
Implémentation de règles de
validation et de sécurité complexes (on peut par exemple contrôler
la date et l'heure de l'opération effectuée),
·
Réaction aux instructions UPDATE,
DELETE, INSERT ce qui permet d'enclencher un traitement suite à
l'une de ces actions,
·
Maintenance de plusieurs tables
"miroir" sur différents sites d'un réseau : on assure ainsi le fait
que toutes les modifications soient répercutées sur tous les sites
en même temps,
*
Augmentation de la productivité de
développement car le code du trigger est écrit une seule fois au
lieu d'être écrit dans chaque programme applicatif voulant
effectuer les contrôles nécessaires,
*
Constitution d'audits
personnalisés.
Les triggers et
les contraintes de tables peuvent être utilisés tous les deux pour
assurer la cohérence de la base de données.
Cependant les
triggers et les contraintes d'intégrité de tables ne fonctionnent
pas tout à fait de la même manière.
Une contrainte
d'intégrité déclarative (primary key, foreign key, not null, unique
…) s'applique à toutes les données et ne pourra être créée si
certaines données déjà en place ne la vérifient pas.
Les triggers ne
vont pas vérifier l'ensemble des données en place lors de leur
création. Ils effectuent un traitement seulement lors de leur
déclenchement. De ce fait, un trigger ne peut pas garantir que
toutes les données présentes dans une table sont conformes aux
règles définies par le trigger associé à cette table.
Un trigger
permet de gérer la transition des données. Il permet de vérifier
une contrainte particulière au moment où une donnée change de
valeur.