Vous êtes sur la page 1sur 49

MYSQL 5

Procdures stockes
et
Triggers

MYSQL 5 - Procdures stockes et triggers

Sommaire
Chapitre 1
PROCEDURES STOCKEES.........................................................3
1.1 Procdures stockes...................................................................................4
1.1.1
Gnralits.........................................................................................4
1.1.2
Connexion.........................................................................................5
1.1.3
Stockage............................................................................................6
1.1.4
Cration d'une procdure stocke......................................................7
1.1.5
Suppression d'une procdure stocke................................................7
1.1.6
Procdures stockes sans paramtre..................................................8
1.1.7
Procdures stockes avec des paramtres IN....................................9
1.1.8
Procdure stocke avec des paramtres OUT..................................10
1.2 Fonctions stockes...................................................................................12
1.3 Notions avances.....................................................................................15
1.3.1
Les instructions de contrles...........................................................15
1.3.1.1 Le IF.............................................................................................15
1.3.1.2 LE CASE......................................................................................16
1.3.1.3 La boucle LOOP...........................................................................17
1.3.1.4 La boucle WHILE........................................................................18
1.3.1.5 La boucle REPEAT......................................................................19
1.3.2
SQL dynamique...............................................................................20
1.3.2.1 Dmarche et Syntaxes..................................................................20
1.3.2.2 Un Count......................................................................................21
1.3.2.3 Un SELECT.................................................................................23
1.3.2.4 Un SELECT WHERE.............................................................25
1.3.2.5 Un SELECT gnrique.................................................................27
1.3.2.6 Un DELETE.................................................................................28
1.3.2.7 Un INSERT..................................................................................29
1.3.3
Les curseurs : une procdure sans retour........................................30
1.3.3.1 Exemple : Transfert d'une table vers une autre............................31
1.3.3.2 Exemple : Un tableau crois dynamique......................................32
1.3.4
Curseur qui renvoie un rsultat de type VARCHAR.......................33
1.3.5
Un SELECT donc un curseur..........................................................34
1.4 La gestion des ERREURS.......................................................................35
Chapitre 2
LES TRIGGERS..........................................................................40
2.1 Syntaxes...................................................................................................40
2.2 Exemple : archiver un enregistrement de la table villes..........................42
2.3 Exercice : journalisation..........................................................................43
2.4 Les instructions de contrles dans les Triggers.......................................44
Chapitre 3
ANNEXE : BD UTILISEE..........................................................45

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 2

MYSQL 5 - Procdures stockes et triggers

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 3

MYSQL 5 - Procdures stockes et triggers

CHAPITRE 1

Pascal Buguet

PROCEDURES STOCKEES

Imprim le vendredi 8 juillet 2016

Page 4

MYSQL 5 - Procdures stockes et triggers

1.1 PROCDURES STOCKES


1.1.1 Gnralits

Objectifs

Ne pas utiliser du SQL embarqu.


Optimiser la charge Client/Serveur en rduisant le trafic rseau et la charge serveur.
Faciliter la maintenance.
Accrotre la scurit.
Encore embryonnaire, mme dans la version 5.

Droits

Le droit CREATE ROUTINE est ncessaire pour crer une procdure ou une fonction
stocke.
Le droit ALTER ROUTINE est ncessaire pour pouvoir modifier ou supprimer une
procdure ou une fonction stocke. Le droit est fourni automatiquement au crateur
d'une routine.
Le droit EXECUTE est requis pour excuter une procdure stocke.
Ce droit est fourni automatiquement au crateur d'une routine.
Les procdures stockes et les fonctions stockes (depuis MySQL 5.0.3) sont stockes
dans la table mysql.proc.

Liste des procdures stockes.

SELECT * FROM mysql.proc \G (sans le;).


ou
SELECT name FROM mysql.proc;

Visualisation du texte d'une procdure stocke.

SHOW CREATE PROCEDURE nomDeLaProcedure\G


SHOW PROCEDURE STATUS nomDeLaProcedure; affiche les caractristiques de la
procdure (Base, nom, crateur, date de cration, ...).
Exemple
SHOW CREATE PROCEDURE villesInsert\G
Ou
SHOW CREATE PROCEDURE villesInsert;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 5

MYSQL 5 - Procdures stockes et triggers

1.1.2 Connexion
C:\\mysql\bin>mysql --host=localhost --user=root --password=

Pascal Buguet

Imprim le vendredi 8 juillet 2016

--database=cours

Page 6

MYSQL 5 - Procdures stockes et triggers

1.1.3 Stockage
Soit avec un outil comme MySQLQueryBrowser dans une page de Script (pas de
ResultSet) ou dans PhpMyAdmin ou avec l'utilitaire mysql.
MySQL Query Browser

Soit en mode commande avec mysql


C:\\mysql\bin>mysql --host=localhost --user=root --password=

--database=cours

Mysql>DELIMITER $$
Mysql>CREATE PROCEDURE .
Mysql>DELIMITER;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 7

MYSQL 5 - Procdures stockes et triggers

1.1.4 Cration d'une procdure stocke


DELIMITER $$
CREATE PROCEDURE [bd.]nomDeLaProcedure ([DIRECTION argument1 TYPE [,
DIRECTION argument2 TYPE]])
BEGIN
Instruction SQL ou autre;
Instruction SQL ou autre;
END $$
DELIMITER;

Les directions sont IN, OUT, INOUT.


IN : en entre (facultatif).
OUT : en sortie.
INOUT : en entre/sortie.
Les types sont ceux de MYSQL (INT, CHAR(n), VARCHAR(n), ...) ou STRING, INTEGER,
REAL.

1.1.5 Suppression d'une procdure stocke


DROP PROCEDURE IF EXISTS nomDeLaProcedure;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 8

MYSQL 5 - Procdures stockes et triggers

1.1.6 Procdures stockes sans paramtre


Un select
DELIMITER $$
DROP PROCEDURE IF EXISTS villesSelect $$
CREATE PROCEDURE villesSelect()
BEGIN
SELECT * FROM villes;
END $$
DELIMITER;

CALL villesSelect;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 9

MYSQL 5 - Procdures stockes et triggers

1.1.7 Procdures stockes avec des paramtres IN

Exemple de procdure d'Insertion d'enregistrement

DELIMITER $$
DROP PROCEDURE IF EXISTS villesInsert $$
CREATE PROCEDURE villesInsert (IN asCp CHAR(5), IN asVille VARCHAR(50), IN asIdPays
CHAR(3))
BEGIN
INSERT INTO villes(cp, nom_ville, id_pays) VALUES(asCp, asVille, asIdPays);
END $$
DELIMITER;

Exemple de procdure de suppression d'enregistrement

DELIMITER $$
DROP PROCEDURE IF EXISTS villesDelete $$
CREATE PROCEDURE villesDelete(IN asCp CHAR(5))
BEGIN
DELETE FROM villes WHERE cp = asCp;
END $$
DELIMITER;

Excution d'une procdure stocke.

CALL villesInsert('75021','Paris 21', '033');

CALL villesDelete('75021');

Exercice : CRUD sur Pays.

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 10

MYSQL 5 - Procdures stockes et triggers

1.1.8 Procdure stocke avec des paramtres OUT.


Pour dclarer une variable : DECLARE nom_de_variable type DEFAULT valeur;
Pour affecter une valeur une variable : SET nom_de_variable = expression;
Pour affecter une valeur une variable dans un ordre SELECT : SELECT ... INTO variable
FROM ...;

Exemple d'une procdure stocke avec un paramtre OUT

DELIMITER $$
DROP PROCEDURE IF EXISTS villesNbProc $$
CREATE PROCEDURE villesNbProc(OUT aiVilles INT)
BEGIN
SELECT COUNT(*) INTO aiVilles FROM villes;
END $$
DELIMITER;

Excution (avec mysql, PHPMyADMIN ou un langage applicatif type PHP,


JAVA, VB, )

Avec mysql
mysql>CALL villesNbProc(@Resultat);
mysql>SELECT @Resultat;

Avec MySQL Query Browser (Dans une page de resultSet).

CALL villesNbProc(@Resultat);
SELECT @Resultat;

Avec @ pour que ce ne soit pas pris pour champ mais bien une variable de session.

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 11

MYSQL 5 - Procdures stockes et triggers

Une procdure stocke avec des paramtres IN et OUT

DELIMITER $$
DROP PROCEDURE IF EXISTS villesUneProc $$
CREATE PROCEDURE villesUneProc(IN asCp CHAR(5) , OUT asNomVille VARCHAR(50))
BEGIN
SELECT nom_ville INTO asNomVille FROM villes WHERE cp = asCp;
END $$
DELIMITER;

Excution avec l'utilitaire mysql


mysql>CALL villesUneProc('75011', @Resultat);
mysql>SELECT @Resultat;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 12

MYSQL 5 - Procdures stockes et triggers

1.2 FONCTIONS STOCKES


Une fonction stocke renvoie un seul rsultat.
Les arguments des fonctions stockes ne peuvent tre que de direction IN.
De ce fait cette clause de direction ne doit pas tre prcise.
Pas de COMMIT ni de ROLLBACK dans les fonctions.
Syntaxe

CREATE [AGGREGATE] FUNCTION nom_de_fonction([argument1 type [, ...]]) RETURNS


type
BEGIN
DECLARE variable Type DEFAULT valeur_par_defaut;
SET variable = expression;
RETURN variable | expression;
END

Le type des paramtres ou retourn par une fonction peut tre STRING, INTEGER ou
REAL ou un type SQL (CHAR(5), ).
Une fonction AGGREGATE se comporte comme une fonction agrgat native (SUM, COUNT,
).

Excution

SELECT nom_de_fonction(arguments);

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 13

MYSQL 5 - Procdures stockes et triggers

Exemple : additionner deux entiers

La fonction
DELIMITER $$
DROP FUNCTION IF EXISTS addition $$
CREATE FUNCTION addition(aiX INT , aiY INT) RETURNS INT
BEGIN
DECLARE nTotal INT DEFAULT 0;
SET n_total = aiX + aiY;
RETURN nTotal;
END $$
DELIMITER;

Excution
SELECT addition(3,4);

Autre Exemple : Calculer un prix TTC

La fonction
DELIMITER $$
DROP FUNCTION IF EXISTS TTC $$
CREATE FUNCTION TTC(aiPrixHT DOUBLE) RETURNS DOUBLE
[DETERMINISTIC]
BEGIN
RETURN aiPrixHT * 1.195;
END $$
DELIMITER;

Excution
SELECT prix "Prix HT", TTC(prix) "Prix TTC" FROM produits;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 14

MYSQL 5 - Procdures stockes et triggers

Autre Exemple : compter le nombre de villes de la table Villes

DELIMITER $$
DROP FUNCTION IF EXISTS villesNbFct $$
CREATE FUNCTION villesNbFct() RETURNS INT
BEGIN
DECLARE nVilles INT DEFAULT 0;
SELECT COUNT(*) INTO nVilles FROM villes;
RETURN nVilles;
END $$
DELIMITER;

Excution : SELECT villesNbFct();

Autre exemple : rcuprer le nom d'une ville en fonction de son CP

DELIMITER $$
DROP FUNCTION IF EXISTS villesUneFct $$
CREATE FUNCTION villesUneFct(asCp CHAR(5)) RETURNS VARCHAR(50)
BEGIN
DECLARE lsNomVille VARCHAR(50);
SELECT nom_ville INTO lsNomVille FROM villes WHERE cp = asCp;
RETURN lsNomVille;
END $$
DELIMITER;

Excution : SELECT villesUneFct('75011') "La ville en question";


Note : pas de IN (direction) pour l'argument.
Problme avec les jeux de caractres sous MySQL Query Browser. Cf exemple suivant.

Exercices :

Le code Pays en fonction du nom du pays.


Fonction de conversion Euro/Dollar avec passage du taux.

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 15

MYSQL 5 - Procdures stockes et triggers

1.3 NOTIONS AVANCES


1.3.1 Les instructions de contrles
1.3.1.1

Le IF

Exprime une condition

IF condition THEN
Action;
ELSE
Action;
END IF;

Exemple
La mme fonction que prcdemment qui renvoie le nom de la ville en fonction du CP
mais avec un message si le CP n'existe pas.
Script de cration de la fonction stocke
DELIMITER $$
DROP FUNCTION IF EXISTS villesUneAvecIf $$
CREATE FUNCTION villesUneAvecIf(asCp CHAR(5)) RETURNS VARCHAR(50)
BEGIN
DECLARE nbVilles INT(1);
DECLARE lsNomVille VARCHAR(50);
SELECT COUNT(*) INTO nbVilles FROM villes WHERE cp = asCp;
IF nbVilles = 1 THEN
SELECT nom_ville INTO lsNomVille FROM villes WHERE cp = asCp;
ELSE
SET lsNomVille = 'Pas de ville pour ce CP';
END IF;
RETURN lsNomVille;
END $$
DELIMITER;

Test
SET CHARACTER_SET_SERVER = 'latin1';
SET COLLATION_SERVER ='latin1_general_ci';
SELECT villesUneAvecIf('75011') "La ville en question";

Problme avec les jeux de caractres sous MySQL Query Browser. A tester sous PHPMyADMIN.

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 16

MYSQL 5 - Procdures stockes et triggers

1.3.1.2

LE CASE

Exprime une condition

CASE variable
WHEN valeur THEN action;
[WHEN valeur THEN action;]
[ELSE action;]
END CASE;

Exemple
La mme fonction que prcdemment qui renvoie le nom de la ville en fonction du CP
mais avec un message si le CP n'existe pas.
Script de cration de la fonction stocke
DELIMITER $$
DROP FUNCTION IF EXISTS villesUneAvecCase $$
CREATE FUNCTION villesUneAvecCase(asCp CHAR(5)) RETURNS VARCHAR(50)
BEGIN
DECLARE nbVilles INT(1);
DECLARE lsNomVille VARCHAR(50);
SET nbVilles = 0;
SELECT COUNT(*) INTO nbVilles FROM villes WHERE cp = asCp;
CASE nb_villes
WHEN 1 THEN SELECT nom_ville INTO lsNomVille FROM villes WHERE cp = asCp;
WHEN 0 THEN SET lsNomVille = 'Pas de ville pour ce CP';
END CASE;
RETURN lsNomVille;
END $$
DELIMITER;

Test
-- Pour ne pas avoir ce message-ci :
-- #1267 - Illegal mix of collations (latin1_general_ci,IMPLICIT) and
(latin1_swedish_ci,IMPLICIT) for operation '='
SET CHARACTER_SET_SERVER = 'latin1';
SET COLLATION_SERVER ='latin1_general_ci';
SELECT villesUneAvecCase('75011') "La ville en question";

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 17

MYSQL 5 - Procdures stockes et triggers

1.3.1.3

La boucle LOOP

Ralise une boucle de type FOR ! Boucle infinie avec un "exit".

tiquette: LOOP
instruction;
IF condition THEN LEAVE tiquette; END IF;
instruction;
END LOOP tiquette;

Exemple : factorielle.
Script
DELIMITER $$
DROP FUNCTION IF EXISTS fctLoop $$
CREATE FUNCTION fctLoop(aiN INT) RETURNS INT
BEGIN
DECLARE liC INT;
DECLARE liFactorielle INT;
SET liC = 2;
SET liFactorielle = 1;
calcul: LOOP
SET liFactorielle = liFactorielle * liC;
IF liC = aiN THEN LEAVE calcul; END IF;
SET liC = liC + 1;
END LOOP calcul;
RETURN liFactorielle;
END $$
DELIMITER;

Test
SELECT fctLoop(4);

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 18

MYSQL 5 - Procdures stockes et triggers

1.3.1.4

La boucle WHILE

Ralise une boucle de type TANT QUE. Tant que la condition est Vrai on boucle.

WHILE condition DO
Instructions;
END WHILE;

Exemple : factorielle.
Script
DELIMITER $$
DROP FUNCTION IF EXISTS fctWhile $$
CREATE FUNCTION fctWhile(aiN INT) RETURNS INT
BEGIN
DECLARE liC INT;
DECLARE liFactorielle INT;
SET liC = 2;
SET liFactorielle = 1;
WHILE liC <= aiN DO
SET liFactorielle = liFactorielle * liC;
SET liC = liC + 1;
END WHILE;
RETURN liFactorielle;
END $$
DELIMITER;

Test
SELECT fctWhile(3);

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 19

MYSQL 5 - Procdures stockes et triggers

1.3.1.5

La boucle REPEAT

Ralise une boucle de type FAIRE JUSQU'A. On boucle juqu' ce que la condition soit
VRAI.

REPEAT
Instructions;
UNTIL condition END REPEAT;

Script
DELIMITER $$
DROP FUNCTION IF EXISTS fctRepeat $$
CREATE FUNCTION fctRepeat(aiN INT) RETURNS INT
BEGIN
DECLARE liC INT;
DECLARE liFactorielle INT;
SET liC = 1;
SET liFactorielle = 1;
REPEAT
SET liFactorielle = liFactorielle * li_c;
SET liC = liC + 1;
UNTIL liC > aiN END REPEAT;
RETURN liFactorielle;
END $$
DELIMITER;

Test
SELECT fctRepeat(3);

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 20

MYSQL 5 - Procdures stockes et triggers

1.3.2 SQL dynamique


Le SQL dynamique permet d'excuter des instructions SQL composes la vole dans
des procdures stockes.
Valable seulement dans les procdures (Pas dans les fonctions ni dans les triggers).

1.3.2.1

Dmarche et Syntaxes

Dclarer une variable de type VARCHAR ou TEXT ou BLOB pour stocker la commande
SQL. C'est un objet!

DECLARE cmd VARCHAR(255);

Affecter une variable de session (@var) l'ordre SQL avec la fonction CONCAT(). La
variable NE DOIT PAS tre dclare au pralable.

SET @lsSql = CONCAT(chane1, chane2 [, chane3]);

Compiler l'ordre SQL dans la variable commande.

PREPARE cmd FROM @lsSql;

Excuter la commande.

EXECUTE cmd;

Librer la mmoire.

DEALLOCATE PREPARE cmd;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 21

MYSQL 5 - Procdures stockes et triggers

1.3.2.2

Un Count

Ce premier exemple va renvoyer un COUNT(*) sur n'importe quelle table.


Syntaxes
La commande doit tre une commande de session prcde d'un @ affecte via un SET.
Elle doit tre prpare puis excute.
Puis le rsultat est rcupr via une autre variable de session donc aussi prcde d'un
@ dans le paramtre OUT.
Script (Count sur n'importe quelle table)
DELIMITER $$
DROP PROCEDURE IF EXISTS sqlDynCount $$
CREATE PROCEDURE sqlDynCount(IN asTable VARCHAR(50), OUT nb INTEGER)
BEGIN
/* DECLARE lsSql VARCHAR(50);
SURTOUT PAS DE DECLARE de la variable qui contient le SQL qui doit tre de
session
donc avec @ dans un SET
*/
DECLARE cmd
VARCHAR(255);
SET @lsSql = CONCAT('SELECT COUNT(*) INTO @resultat FROM ', asTable);
PREPARE cmd FROM @lsSql;
EXECUTE cmd;
DEALLOCATE PREPARE cmd;
SET nb = @resultat;
END $$
DELIMITER;

Test (avec l'utilitaire mysql ou MySQL Query Browser)


Ouvrir une cmd.
C:\\mysql\bin>mysql -h localhost -u root -D cours p
Mysql>use cours;
SET @r = 0;
CALL sqlDynCount('villes', @r);
SELECT @r;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 22

MYSQL 5 - Procdures stockes et triggers


Exemple d'utilisation avec PHP et PDO
<?php
header("Content-Type: text/html; charset=UTF-8");
try
{
$cn = new PDO('mysql:host=localhost;dbname=cours','root','');
}
catch(PDOException $e)
{
echo $e->getMessage();
}
$cmd = $cn->prepare("CALL sqlDynCount('villes', @outputParam)");
if($cmd->errorCode() != '00000')
{
$erreurInfo = $cmd->errorInfo();
echo "<br />PDOPrepare::errorCode(): ", $cmd->errorCode();
echo "<br />PDO::errorInfo(): ", $erreurInfo[2];
}
$cmd->execute();
if($cmd->errorCode() != '00000')
{
$erreurInfo = $cmd->errorInfo();
echo "<br />PDO Execute::errorCode(): ", $cmd->errorCode();
echo "<br />PDO::errorInfo(): ", $erreurInfo[2];
}
$rs = $cn->query("SELECT @outputParam");
if($rs->errorCode() != '00000')
{
$erreurInfo = $rs->errorInfo();
echo "<br />PDOQuery::errorCode(): ", $rs->errorCode();
echo "<br />PDO::errorInfo(): ", $erreurInfo[2];
}
echo "<br/>Nombre d'enregistrements : ", $rs->fetchColumn();
if($rs->errorCode() != '00000')
{
$erreurInfo = $rs->errorInfo();
echo "<br />PDOQuery::errorCode(): ", $rs->errorCode();
echo "<br />PDO::errorInfo(): ", $erreurInfo[2];
}
$cn = null;
?>

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 23

MYSQL 5 - Procdures stockes et triggers

1.3.2.3

Un SELECT

Une procdure stocke qui renvoie un curseur sur n'importe quelle table.
Le paramtre IN de la PS est le nom de la table.

DELIMITER $$
DROP PROCEDURE IF EXISTS sqlDynTable $$
CREATE PROCEDURE sqlDynTable(IN asTable VARCHAR(50))
BEGIN
/* DECLARE lsSql VARCHAR(50);
SURTOUT PAS DE DECLARE de la variable qui contient le SQL qui doit tre de
session
donc avec @
*/
DECLARE cmd

VARCHAR(255);

SET @lsSql = CONCAT('SELECT * FROM ', asTable);


PREPARE cmd FROM @lsSql;
EXECUTE cmd;
DEALLOCATE PREPARE cmd;
END $$
DELIMITER;

Test dans MySQL Query Browser


CALL sqlDynTable('villes');

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 24

MYSQL 5 - Procdures stockes et triggers


Exemple d'utilisation avec PHP et PDO
<?php
// --- pdo_ps_dyn_select.php
header("Content-Type: text/html; charset=UTF-8");
try
{
$cn = new PDO('mysql:host=localhost;dbname=cours','root','');
$cn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$rs = $cn->query("CALL sqlDynTable('villes')");
$rs->setFetchMode(PDO::FETCH_ASSOC);
while($enr = $rs->fetch())
{
foreach($enr as $champ)
{
echo $champ, "-";
}
echo "<br/>";
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
$cn = null;
?>

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 25

MYSQL 5 - Procdures stockes et triggers

1.3.2.4

Un SELECT WHERE

Objectif

Renvoyer un curseur correspondant une valeur d'une colonne.

Syntaxe

Les paramtres IN de la PS sont le nom de la table, le nom de la colonne et la valeur de


la colonne.

Number
DELIMITER $$
DROP PROCEDURE IF EXISTS sqlDynSelectWhereNum $$
CREATE PROCEDURE sqlDynSelectWhereNum(IN asTable VARCHAR(50), IN asCol VARCHAR(50),
IN asValeur VARCHAR(50))
BEGIN
DECLARE cmd VARCHAR(255);
SET @lsSql = CONCAT('SELECT * FROM ', asTable, ' WHERE ', asCol, '=' ,
asValeur);
PREPARE cmd FROM @lsSql;
EXECUTE cmd;
DEALLOCATE PREPARE cmd;
END $$
DELIMITER;

Test dans MySQL Query Browser


CALL sqlDynSelectWhereNum('clients', 'id_client', 3);

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 26

MYSQL 5 - Procdures stockes et triggers


String
DELIMITER $$
DROP PROCEDURE IF EXISTS sqlDynSelectWhereString $$
CREATE PROCEDURE sqlDynSelectWhereString(IN asTable VARCHAR(50), IN asCol
VARCHAR(50), IN asValeur VARCHAR(50))
BEGIN
DECLARE cmd

VARCHAR(255);

SET @lsSql = CONCAT('SELECT * FROM ', asTable, ' WHERE ', asCol, '=\'' ,
asValeur, '\'');
PREPARE cmd FROM @lsSql;
EXECUTE cmd;
DEALLOCATE PREPARE cmd;
END $$
DELIMITER;

Test dans MySQL Query Browser


CALL sqlDynSelectWhereString('villes','nom_ville','Lille');

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 27

MYSQL 5 - Procdures stockes et triggers

1.3.2.5

Un SELECT gnrique

Cette PS fait un SELECT Dynamique avec ou sans condition sur une colonne numrique
ou String.
Permet de rcuprer toute une table ou une projection ou une restriction ou une
Projection/Restriction.
DELIMITER $$
DROP PROCEDURE IF EXISTS sqlDynSelect $$
CREATE PROCEDURE sqlDynSelect(IN asTable VARCHAR(50), IN asCols VARCHAR(200), IN
asColWhere VARCHAR(50), IN asValeur VARCHAR(100))
BEGIN
DECLARE cmd VARCHAR(255);
IF asColWhere = '' THEN
SET @lsSql = CONCAT('SELECT ', asCols, ' FROM ', asTable);
ELSE
SET @lsSql = CONCAT('SELECT ', asCols, ' FROM ', asTable, ' WHERE ',
asColWhere, '=\'' , asValeur, '\'');
END IF;
PREPARE cmd FROM @lsSql;
EXECUTE cmd;
DEALLOCATE PREPARE cmd;
END $$
DELIMITER;

CALL sqlDynSelect ('villes', '*', '', '');


CALL sqlDynSelect ('villes', 'nom_ville', '', '');
CALL sqlDynSelect ('clients', '*', 'id_client', '1');
CALL sqlDynSelect ('villes', '*', 'nom_ville', 'Paris XI');

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 28

MYSQL 5 - Procdures stockes et triggers

1.3.2.6

Un DELETE

Mmes remarques sur les String et les Num que prcdemment.


Crer une PS pour supprimer un ou plusieurs enregistrements dans n'importe quelle table
en fonction d'une valeur d'une colonne.
Les paramtres IN de la PS sont le nom de la table, le nom d'une colonne et la valeur de
la colonne.

DELIMITER $$
DROP PROCEDURE IF EXISTS sqlDynDelete $$
CREATE PROCEDURE sqlDynDelete(IN asTable VARCHAR(50), IN asCol VARCHAR(50), IN
asValeur VARCHAR(50))
BEGIN
/* DECLARE lsSql VARCHAR(50);
SURTOUT PAS DE DECLARE de la variable qui contient le SQL qui doit tre de
session donc avec @
*/
DECLARE cmd

VARCHAR(255);

SET @lsSql = CONCAT('DELETE FROM ', asTable, ' WHERE ', asCol, '=' , asValeur);
PREPARE cmd FROM @lsSql;
EXECUTE cmd;
DEALLOCATE PREPARE cmd;
END $$
DELIMITER;

Test dans MySQL Query Browser


CALL sqlDynDelete('villes','cp','75021');

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 29

MYSQL 5 - Procdures stockes et triggers

1.3.2.7

Un INSERT

Crer une PS pour insrer un enregistrement dans n'importe quelle table.


Les paramtres IN de la PS sont le nom de la table, les noms des colonnes et les valeurs
des colonnes.

DELIMITER $$
DROP PROCEDURE IF EXISTS cours.sqlDynInsert $$
CREATE PROCEDURE sqlDynInsert(IN asTable VARCHAR(50), IN asCols VARCHAR(50), IN
asValeurs VARCHAR(50))
BEGIN
/* DECLARE lsSql VARCHAR(50);
SURTOUT PAS DE DECLARE de la variable qui contient le SQL qui doit tre de
session donc avec @
*/
DECLARE cmd

VARCHAR(255);

SET @lsSql = CONCAT('INSERT INTO ', asTable, '(', asCols, ') VALUES(', asValeurs,
')');
PREPARE cmd FROM @lsSql;
EXECUTE cmd;
DEALLOCATE PREPARE cmd;
END $$
DELIMITER;

Test dans MySQL Query Browser


CALL sqlDynInsert('villes', 'cp, nom_ville', '\'75021\',\'Paris 21\'')

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 30

MYSQL 5 - Procdures stockes et triggers

1.3.3 Les curseurs : une procdure sans retour

Syntaxes

Dclaration d'un curseur

DECLARE nom_de_curseur CURSOR FOR SELECT ;

Ouverture d'un curseur

OPEN nom_de_curseur;

Rcupration d'un enregistrement

FETCH nom_de_curseur INTO variables;

Fermeture du curseur

CLOSE nom_de_curseur;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 31

MYSQL 5 - Procdures stockes et triggers

1.3.3.1

Exemple : Transfert d'une table vers une autre

Objectif

Insrer dans une table nomme villes_94 les enregistrements du 94.


Ces trois villes existent dans la table villes.
INSERT INTO villes(cp, nom_ville) VALUES ('94100','Saint-Mand');
INSERT INTO villes(cp, nom_ville) VALUES ('94200','Vincennes');
INSERT INTO villes(cp, nom_ville) VALUES ('94300','Nogent-sur-Marne');
Au pralable crer la table avec l'instruction suivante.
CREATE TABLE villes_94 AS SELECT * FROM villes WHERE cp = '0';

Script

DELIMITER $$
DROP PROCEDURE IF EXISTS ajout_94 $$
CREATE PROCEDURE ajout_94()
BEGIN
DECLARE fin INTEGER DEFAULT 0;
DECLARE ls_cp, ls_nom_ville VARCHAR(50);
DECLARE c_villes_94 CURSOR FOR SELECT cp, nom_ville FROM villes WHERE cp LIKE
'94%';
-- Dclare un handler pour basculer l'indicateur "boolen" utilis dans la boucle
-- de balayage du curseur afin de sortir de la boucle
-- quand la fin du curseur est atteinte
-- il doit tre dclar juste aprs la dclaration du curseur
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET fin = 1;
OPEN c_villes_94;
FETCH c_villes_94 INTO ls_cp, ls_nom_ville;
WHILE fin = 0 DO
-- Parcours du curseur
INSERT INTO villes_94(cp, nom_ville) VALUES (ls_cp, ls_nom_ville);
FETCH c_villes_94 INTO ls_cp, ls_nom_ville;
END WHILE;
CLOSE c_villes_94;
END $$
DELIMITER;

Test

CALL ajout_94();

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 32

MYSQL 5 - Procdures stockes et triggers

1.3.3.2

Exemple : Un tableau crois dynamique

Objectif

TCD Ventes par Produits par Vendeurs.

Dmarche

Cration d'une fonction stocke qui renvoie l'ordre SQL SELECT ncessaire pour la
cration du TCD.

Script de cration de la fonction stocke

DELIMITER $$
DROP FUNCTION IF EXISTS tcdDynVentesVendeursProduits $$
CREATE FUNCTION tcdDynVentesVendeursProduits() RETURNS VARCHAR(1000)
BEGIN
DECLARE fin INTEGER DEFAULT 0;
DECLARE lsDesignation VARCHAR(50);
DECLARE lsSelectDesignations VARCHAR(1000) DEFAULT '';
DECLARE lsSelectTcd VARCHAR(1000) DEFAULT '';
DECLARE curseurDesignation CURSOR FOR SELECT DISTINCT designation FROM produits;
-- Dclare un handler pour basculer l'indicateur "boolen" utilis dans la boucle
-- de balayage du curseur afin de sortir de la boucle
-- quand la fin du curseur est atteinte
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET fin = 1;
-- Cration de la partie du SELECT avec les SUM bass sur la table produits et
la colonne designation
OPEN curseurDesignation;
FETCH curseurDesignation INTO lsDesignation;
WHILE fin= 0 DO
-- Parcours du curseur
SET lsSelectDesignations = CONCAT(lsSelectDesignations,"SUM(IF(designation =
'", lsDesignation,"', vente, 0)) AS """ , lsDesignation, """ ,");
FETCH curseurDesignation INTO lsDesignation;
END WHILE;
CLOSE curseurdesignation;
SET lsSelectDesignations = SUBSTRING(lsSelectDesignations, 1,
LENGTH(lsSelectDesignations) - 1);
SET lsSelectTcd =
CONCAT("SELECT nom, ", lsSelectDesignations, " FROM ventes ve, vendeurs v ,
produits p WHERE ve.id_vendeur = v.id_vendeur AND ve.id_produit = p.id_produit
GROUP BY nom" );
-- Retour du rsultat
RETURN lsSelectTcd;
END $$
DELIMITER;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 33

MYSQL 5 - Procdures stockes et triggers

1.3.4 Curseur qui renvoie un rsultat de type VARCHAR


Le rsultat : 75011-Paris 11;75012-Paris 12;75019-Paris 19;

Script MySQL

DELIMITER $$
DROP PROCEDURE IF EXISTS villesCurseurOut $$
CREATE PROCEDURE villesCurseurOut(OUT as_resultat VARCHAR(2000))
BEGIN
DECLARE fin INTEGER DEFAULT 0;
DECLARE v_cp, v_nom_ville VARCHAR(50);
DECLARE v_resultat VARCHAR(2000);
DECLARE curseur_villes CURSOR FOR SELECT cp, nom_ville FROM villes;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET fin = 1;
SET v_resultat = '';
OPEN curseur_villes;
FETCH curseur_villes INTO v_cp, v_nom_ville;
WHILE NOT fin DO
SET v_resultat = concat(v_resultat, v_cp, '-', v_nom_ville, ';');
FETCH curseur_villes INTO v_cp, v_nom_ville;
END WHILE;
SET as_resultat = v_resultat;
CLOSE curseur_villes;
END $$
DELIMITER;

PHP avec PDO

<?php
$cn = new PDO("mysql:host=localhost;dbname=cours", "root", "");
$cmd = $cn->prepare("CALL villesCurseurOut(@o_param)");
$cmd->execute();
$rs = $cn->query("SELECT @o_param");
echo "CPs : ", $rs->fetchColumn();
$cn = null;
?>

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 34

MYSQL 5 - Procdures stockes et triggers

1.3.5 Un SELECT donc un curseur

La procdure

DELIMITER $$
DROP PROCEDURE IF EXISTS cours.villesCpsNoms $$
CREATE PROCEDURE cours.villesCpsNoms ()
BEGIN
SELECT cp, nom_ville FROM villes;
END $$
DELIMITER;

PHP avec MYSQLI

<?php
$mysqli = new mysqli("localhost", "root", "", "cours");
if ($cmd = $mysqli->prepare("CALL villesCpsNoms()"))
{
$cmd->execute();
$cmd->bind_result($col1, $col2);
while($cmd->fetch())
{
printf("%s-%s<br />\n", $col1, $col2);
}
$cmd->close();
}
$mysqli->close();
?>

PHP avec PDO

<?php
$cn = new PDO("mysql:host=localhost;dbname=cours", "root", "");
$rs = $cn->query("CALL villesCpsNoms()");
while($enr = $rs->fetch())
{
echo "<br />$enr[0]-$enr[1]";
}
$cn = null;
?>

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 35

MYSQL 5 - Procdures stockes et triggers

1.4 LA GESTION DES ERREURS

Objectif

Faire une gestion d'erreurs (Leve d'Exceptions).

Syntaxe

DECLARE typeHandler HANDLER FOR condition instructionSQL;

TypeHandler peut prendre les valeurs :


CONTINUE
EXIT
Condition peut prendre les valeurs suivantes :

SQLSTATE 'valeur' '23000' par exemple pour duplicate key,


Code erreur MySQL 1062 par exemple pour duplicate key,
SQLWARNING,
SQLEXCEPTION,
NOT FOUND,
Condition personnalise.

Cration d'une condition personnalise

DECLARE nomConditionPerso CONDITION FOR SQLSTATE 'nombre';

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 36

MYSQL 5 - Procdures stockes et triggers

Exemples

Gestion standard
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET codeErreur = 1;

Qui signifie : si une exception SQL est leve alors la variable codeErreur passe 1 et le
script continue d'tre excut.

Gestion personnalise
En premier lieu cration d'une condition personnalise nomme CLE_DUPLIQUEE
correspondant l'erreur SQL 23000;
En second lieu affectation de la valeur 1 codeErreur et ordre de continuer l'excution du
script.
DECLARE CLE_DUPLIQUEE CONDITION FOR SQLSTATE '23000';
DECLARE CONTINUE HANDLER FOR CLE_DUPLIQUEE SET codeErreur = 1;

Quelques codes d'erreurs.


Erreur
Pas d'erreur
PK duplique
FK errone
Table inexistante
Champ obligatoire
Nombre de colonnes incorrecte
Erreur gnrale

SQLSTATE (ANSI)
'00000'
'23000'
'23000'
'42S02'
'23000'
'21S01'
'HY000'

Code MySQL
0
1062
1452
1146
1048
1136

Les codes MYSQL n'ont pas ncessairement un correspondant ou un correspondant


unique dans la liste des codes ANSI.
Les valeurs de SQLSTATE sont spcifies par les normes ANSI SQL et ODBC.
Pour une liste des valeurs possibles :
http://dev.mysql.com/doc/refman/5.1/en/error-handling.html
Pour les erreurs serveur
http://dev.mysql.com/doc/refman/5.1/en/error-messages-server.html
Pour les erreurs client (problme de connexion )
http://dev.mysql.com/doc/refman/5.1/en/error-messages-client.html

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 37

MYSQL 5 - Procdures stockes et triggers


Crez au pralable une table erreurs(id_erreur INT, texte VARCHAR(50), heure
DATETIME).
CREATE TABLE erreurs (
id_erreur INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
texte VARCHAR(255) NOT NULL ,
heure DATETIME NOT NULL
) ENGINE = MYISAM ;

Script : gestion gnrique

DELIMITER $$
DROP PROCEDURE IF EXISTS villesInsertErreur $$
CREATE PROCEDURE villesInsertErreur(IN asCp CHAR(5), IN asVille VARCHAR(50), IN
asIdPays CHAR(3))
BEGIN
-- Cette procdure gre les erreurs d'insertions
-- Dclaration de la variable qui permettra l'aiguillage en cas d'erreur
DECLARE codeErreur INT;
-- Dclaration de l'action entreprendre en cas d'exception SQL
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET codeErreur = 1;
-- Initialisation du code d'erreur 0
SET codeErreur = 0;
-- Ordre SQL majeur
INSERT INTO villes(cp, nom_ville, id_pays) VALUES(asCp, asVille, asIdPays);
-- Tests sur le code d'erreur et insertion dans la table des erreurs en
consquence
IF codeErreur = 0 THEN
INSERT INTO erreurs(texte, heure) VALUES('Insertion ville 0K', now());
END IF;
IF codeErreur = 1 THEN
INSERT INTO erreurs(texte, heure) VALUES('Insertion ville KO - Problme de Cl
primaire', now());
END IF;
END $$
DELIMITER;

CALL villesInsertErreur('75021','Paris 21', '033');

SELECT * FROM erreurs;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 38

MYSQL 5 - Procdures stockes et triggers

Script : Gestion personnalise et plus spcifique

La gestion est faite avec les codes MySQL, plus prcis, plutt qu'avec les codes ANSI
moins prcis.
DELIMITER $$
DROP PROCEDURE IF EXISTS villesInsertErreur $$
CREATE PROCEDURE villesInsertErreur(IN asCp CHAR(5), IN asVille VARCHAR(50), IN
asIdPays CHAR(3))
BEGIN
-- Cette procdure gre les erreurs d'insertions
-- Dclaration de la variable qui permettra l'aiguillage en cas d'erreur
DECLARE codeErreur INT;
-- Dclaration des erreurs
-DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET codeErreur = 1; -- Duplicate
Key
-DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET codeErreur = 2; -- Table
inexistante
DECLARE CONTINUE HANDLER FOR 1062 SET codeErreur = 1; -- Duplicate Key
DECLARE CONTINUE HANDLER FOR 1146 SET codeErreur = 2; -- Table inexistante
-- Initialisation du code d'erreur 0
SET codeErreur = 0;
-- Ordre SQL majeur
INSERT INTO ville(cp, nom_ville, id_pays) VALUES(asCp, asVille, asIdPays);
-- Tests sur le code d'erreur et insertion dans la table des erreurs en
consquence
IF codeErreur = 0 THEN
INSERT INTO erreurs(texte, heure) VALUES('0K', NOW());
END IF;
IF codeErreur = 1 THEN
INSERT INTO erreurs(texte, heure) VALUES('Insertion ville KO - Problme de
Cl primaire', NOW());
END IF;
IF codeErreur = 2 THEN
INSERT INTO erreurs(texte, heure) VALUES('Insertion ville KO - Problme de
Table inexistante', NOW());
END IF;
END $$
DELIMITER;

Exercice

Rajoutez la gestion d'erreur pour la cl trangre.

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 39

MYSQL 5 - Procdures stockes et triggers

Corrig

DELIMITER $$
DROP PROCEDURE IF EXISTS villesInsertErreur $$
CREATE PROCEDURE villesInsertErreur(IN asCp CHAR(5), IN asVille VARCHAR(50), IN
asIdPays CHAR(3))
BEGIN
-- Cette procdure gre les erreurs d'insertions
-- Dclaration de la variable qui permettra l'aiguillage en cas d'erreur
DECLARE codeErreur INT;
-- Dclaration des erreurs
-DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET codeErreur = 1; -- Duplicate
Key
-DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET codeErreur = 2; -- Table
inexistante
DECLARE
DECLARE
DECLARE
DECLARE

CONTINUE
CONTINUE
CONTINUE
CONTINUE

HANDLER
HANDLER
HANDLER
HANDLER

FOR
FOR
FOR
FOR

1062
1146
1452
1048

SET
SET
SET
SET

codeErreur
codeErreur
codeErreur
codeErreur

=
=
=
=

1;
2;
3;
4;

-----

Duplicate Key
Table inexistante
FK inexistante
Colonne NOT NULL

-- Initialisation du code d'erreur 0


SET codeErreur = 0;
-- Ordre SQL majeur
INSERT INTO villes(cp, nom_ville, id_pays) VALUES(asCp, asVille, asIdPays);
-- Tests sur le code d'erreur et insertion dans la table des erreurs en
consquence
IF codeErreur = 0 THEN
INSERT INTO erreurs(texte, heure) VALUES('0K', NOW());
END IF;
IF codeErreur = 1 THEN
INSERT INTO erreurs(texte, heure) VALUES('Insertion ville KO - Problme de
Cl primaire', NOW());
END IF;
IF codeErreur = 2 THEN
INSERT INTO erreurs(texte, heure) VALUES('Insertion ville KO - Problme de
Table inexistante', NOW());
END IF;
IF codeErreur = 3 THEN
INSERT INTO erreurs(texte, heure) VALUES('Insertion ville KO - Problme de
cl trangre', NOW());
END IF;
IF codeErreur = 4 THEN
INSERT INTO erreurs(texte, heure) VALUES('Insertion ville KO - Colonne NOT
NULL', NOW());
END IF;
END $$
DELIMITER;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 40

MYSQL 5 - Procdures stockes et triggers

CHAPITRE 2

LES TRIGGERS

Un trigger est un dclencheur.


Un dclencheur est un objet de la base de donnes qui est associ une table, et qui
s'active lorsqu'un vnement spcifi survient, principalement une mise jour sur la
table en question.
Les triggers existent depuis la version 5.0.2.
Ils requirent le droit SUPER.
Un TRIGGER peut servir effectuer des oprations en cascade (Comme la clause DELETE
CASCADE des Foreign Keys)
Un TRIGGER peut permettre la ralisation de contrles lors des mises jour.
Les TRIGGERS sont parfois interdits dans certains services informatiques cause des
risques de boucles infinies.

2.1 SYNTAXES
Pour crer un trigger

CREATE TRIGGER nomDuTrigger


BEFORE | AFTER INSERT | DELETE | UPDATE
ON nomDeLaTable
FOR EACH ROW
[BEGIN]
instruction SQL;
[END]

Notes :
BEGIN et END sont ncessaires si plusieurs instructions sont requises.
La clause obligatoire (!!!) FOR EACH ROW prcise que l'action SQL sera dclenche pour
chaque vnement (Ce n'est pas le cas avec Oracle).
Les rfrences OLD.nom_de_colonne et NEW.nom_de_colonne permettent d'accder aux
valeurs des colonnes de la table. OLD pour les triggers DELETE et UPDATE et NEW pour
les triggers INSERT et UPDATE.
Action / Variable
INSERT

Pascal Buguet

OLD

Imprim le vendredi 8 juillet 2016

NEW
X

Page 41

MYSQL 5 - Procdures stockes et triggers


UPDATE
DELETE

X
X

IF NOT EXISTS nexiste pas.


CREATE OR REPLACE non plus.

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 42

MYSQL 5 - Procdures stockes et triggers


Pour supprimer un trigger

DROP TRIGGER nomDuTrigger;

Pour lister les triggers

SELECT * FROM information_schema.triggers\G

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 43

MYSQL 5 - Procdures stockes et triggers

2.2 EXEMPLE : ARCHIVER UN ENREGISTREMENT DE LA TABLE VILLES.

Objectif

Crer un trigger qui va ajouter le ou les enregistrement(s) supprims de la table Villes


vers la table villes_arch.

Cration de la table villes_arch

CREATE TABLE villes_arch AS SELECT * FROM villes WHERE cp = '00000';


DESC villes_arch;
DESC villes;

Cration du trigger

DROP TRIGGER villes_avant_suppression;


CREATE TRIGGER villes_avant_suppression
BEFORE DELETE
ON villes
FOR EACH ROW
INSERT INTO villes_arch(cp, nom_ville) VALUES(OLD.cp , OLD.nom_ville);

Test du trigger

SELECT * FROM villes v;


DELETE FROM villes WHERE cp = '75021';
SELECT * FROM villes_arch;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 44

MYSQL 5 - Procdures stockes et triggers

2.3 EXERCICE : JOURNALISATION


Crer une journalisation sur la table Produits (Insert, Delete, Update).
Avec cette structure de table 'journal' et un exemple avec la suppression d'une ville.
CREATE TABLE journal
(id_journal INTEGER AUTO_INCREMENT,
action_maj VARCHAR(50),
table_action VARCHAR(50),
date_action DATETIME,
PRIMARY KEY (id_journal));

CREATE TRIGGER villes_apres_suppression


AFTER DELETE
ON villes
FOR EACH ROW
INSERT INTO journal(action_maj, table_action, date_action)
VALUES('DELETE','VILLES',NOW());

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 45

MYSQL 5 - Procdures stockes et triggers

2.4 LES INSTRUCTIONS DE CONTRLES DANS LES TRIGGERS

Un traitement conditionnel

IF condition THEN
Action;
END IF;

L'objectif est de limiter le prix d'un produit 150 euros lors d'une augmentation de prix.
Le trigger
DELIMITER //
CREATE TRIGGER produits_avant_update
BEFORE UPDATE
ON produits
FOR EACH ROW
BEGIN
IF NEW.prix > 150 THEN
SET NEW.prix = 150;
END IF;
END //
DELIMITER;
La commande SQL de mise jour des prix.
UPDATE produits SET prix = prix * 1.1;
Pour vrifier
SELECT * FROM produits;

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 46

MYSQL 5 - Procdures stockes et triggers

CHAPITRE 3

ANNEXE : BD UTILISEE

--- Structure de la table cdes


-CREATE TABLE cdes (
id_cde int(5) NOT NULL auto_increment,
date_cde date NOT NULL,
id_client int(5) NOT NULL,
PRIMARY KEY (id_cde),
KEY FK_cdes_client (id_client)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--- Contenu de la table cdes
-INSERT INTO cdes (id_cde, date_cde, id_client) VALUES (1, '2005-10-03', 1),
(2, '2005-10-10', 2),
(3, '2005-11-01', 1),
(4, '2000-07-09', 1),
(5, '2000-06-04', 2);
-- ---------------------------------------------------------- Structure de la table clients
-CREATE TABLE clients (
id_client int(5) NOT NULL auto_increment,
nom_client varchar(50) NOT NULL,
date_naissance date default NULL,
cp char(5) NOT NULL,
prenom_client varchar(50) NOT NULL default '',
PRIMARY KEY (id_client),
KEY FK_clients_ville (cp),
KEY I_clients_nom_prenom (nom_client,prenom_client)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--- Contenu de la table clients
-INSERT INTO clients (id_client, nom_client, date_naissance, cp, prenom_client)
VALUES (1, 'Buguet', '1965-09-03', '75011', 'Pascal'),
(2, 'Buguet', NULL, '75011', 'Sophie'),
(3, 'Fassiola', NULL, '75011', 'Annabelle'),
(4, 'Roux', NULL, '94100', 'Franoise');
-- ---------------------------------------------------------- Structure de la table ligcdes
--

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 47

MYSQL 5 - Procdures stockes et triggers


CREATE TABLE ligcdes (
id_cde int(5) NOT NULL,
id_produit int(5) NOT NULL,
qte int(5) NOT NULL,
PRIMARY KEY (id_cde,id_produit),
KEY FK_ligcdes_id_produit (id_produit)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--- Contenu de la table ligcdes
-INSERT
(1, 2,
(2, 1,
(3, 1,
(3, 2,
(3, 3,
(4, 1,
(5, 2,

INTO ligcdes (id_cde, id_produit, qte) VALUES (1, 1, 2),


3),
2),
2),
2),
1),
10),
10);

-- ---------------------------------------------------------- Structure de la table pays


-CREATE TABLE pays (
id_pays char(3) NOT NULL default '',
nom_pays varchar(45) NOT NULL default '',
PRIMARY KEY (id_pays)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--- Contenu de la table pays
-INSERT INTO pays (id_pays, nom_pays) VALUES ('033', 'France'),
('035', 'Angleterre'),
('039', 'Italie');
-- ---------------------------------------------------------- Structure de la table produits
-CREATE TABLE produits (
id_produit int(5) NOT NULL auto_increment,
designation varchar(50) NOT NULL,
prix double(7,2) default NULL,
qte_stockee int(5) default NULL,
PRIMARY KEY (id_produit)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--- Contenu de la table produits
-INSERT INTO produits (id_produit, designation, prix, qte_stockee) VALUES (1,
'Evian', 1.50, 24),
(2, 'Badoit', 1.75, 10),
(3, 'Graves', 12.00, 50),
(4, 'Ruinard', 40.00, 10);
-- ---------------------------------------------------------

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 48

MYSQL 5 - Procdures stockes et triggers


-- Structure de la table villes
-CREATE TABLE villes (
cp char(5) NOT NULL,
nom_ville varchar(50) NOT NULL,
id_pays char(3) NOT NULL default '',
PRIMARY KEY (cp),
KEY FK_villes_id_pays (id_pays)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--- Contenu de la table villes
-INSERT INTO villes (cp, nom_ville, id_pays) VALUES ('14000', 'CAEN', '033'),
('75011', 'PARIS 11', '033'),
('75012', 'PARIS 12', '033'),
('75019', 'PARIS 19', '033'),
('94100', 'ST MAND', '033');
-- ---------------------------------------------------------- Contraintes pour la table cdes
-ALTER TABLE cdes
ADD CONSTRAINT FK_cdes_client FOREIGN KEY (id_client) REFERENCES clients
(id_client) ON DELETE CASCADE ON UPDATE CASCADE;
--- Contraintes pour la table clients
-ALTER TABLE clients
ADD CONSTRAINT FK_clients_ville FOREIGN KEY (cp) REFERENCES villes (cp) ON DELETE
CASCADE ON UPDATE CASCADE;
--- Contraintes pour la table ligcdes
-ALTER TABLE ligcdes
ADD CONSTRAINT FK_ligcdes_id_cde FOREIGN KEY (id_cde) REFERENCES cdes (id_cde)
ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT FK_ligcdes_id_produit FOREIGN KEY (id_produit) REFERENCES
produits (id_produit) ON DELETE CASCADE ON UPDATE CASCADE;
--- Contraintes pour la table villes
-ALTER TABLE villes
ADD CONSTRAINT FK_villes_id_pays FOREIGN KEY (id_pays) REFERENCES pays
(id_pays);

Pascal Buguet

Imprim le vendredi 8 juillet 2016

Page 49

Vous aimerez peut-être aussi