01 - SQL Procedural
01 - SQL Procedural
01 - SQL Procedural
SQL PROCEDURAL
1/19
Partie 1 : Bases du langage de programmation
1. Introduction
- La norme SQL n’intègre pas Les structures de contrôle habituelles d’un langage (IF, WHILE…)
- Elles apparaissent dans une sous-partie optionnelle de la norme (ISO/IEC 9075-5:1996. Flow-control
statements).
- Le langage procédural de MySQL est une extension de SQL, permettant de faire cohabiter les structures de
contrôle avec des instructions SQL.
2. Généralités
2.4. Identificateurs
- Permet de nommer un objet utilisé dans un bloc
- Commence par une lettre (ou un chiffre)
- N’est pas limité en nombre de caractères
Exemple :
2.5. Commentaires
- Monolignes : commençant avec le symbole « -- » et finissant à la fin de la ligne
- multilignes, commençant par « /* » et finissant par « */ »
2/19
3. Variables
- Les variables qui sont déclarées (et éventuellement initialisées) par la directive DECLARE
- Deux types de variables sont disponibles sous MySQL :
o scalaires : recevant une seule valeur d’un type SQL (ex : colonne d’une table)
o externes : définies dans la session
3.2. Affectations
Il existe plusieurs possibilités pour affecter une valeur à une variable :
- l’affectation comme on la connaît dans les langages de programmation : SET variable := expression
- la directive DEFAULT (voir plus haut)
- la directive INTO d’une requête (SELECT… INTO variable FROM…)
3.3. Restrictions
Exemple : Ici , l’instruction DELETE supprime tous les pilotes de la table (et non pas seulement le pilote de nom
'Bougara'), car MySQL considère les deux identificateurs comme étant la même variable
- Solutions:
o nommer toutes les variables différemment des colonnes (utiliser un préfixe, par exemple).
o utiliser une étiquette de bloc
3/19
Exemple :
3.5. Opérateurs
- Les opérateurs SQL étudiés au chapitre ‘Rappel SQL’ (logiques, arithmétiques, de concaténation…) sont
disponibles au sein d’un sous-programme.
- Les règles de priorité sont les mêmes que dans le cas de SQL.
- L’opérateur IS NULL permet de tester une formule avec la valeur NULL. Toute expression arithmétique
contenant une valeur nulle est évaluée à NULL.
Exemple :
Exemple :
4/19
3.8. Exemple de Bloc
- Restriction Mysql : pas possible d’exécuter des blocs anonymes (sous-programme sans nom et qui n’est pas
stocké dans la base)
- Un bloc doit être inclus dans une procédure cataloguée a appellée dans l’interface de commande
La redéfinition du délimiteur à « $ » permet d'utiliser, dans le bloc, le symbole « ; » pour terminer chaque instruction.
Exemple :
5/19
3.9.1.2. Structure CASE
Deux façons d’utiliser le CASE :
6/19
3.9.2.2. Structure « REPEAT .. UNTIL »
Syntaxe :
Exemple : Reprenons l’exemple qui calcul la somme des 100 premiers entiers en utilisant deux boucles
sans fin. La directive ITERATE force à reprendre l’exécution au début de la boucle.
7/19
Notes :
LEAVE peut être aussi utilisé pour sortir d’un bloc (s’il est étiqueté).
LEAVE et ITERATE peuvent aussi être employés au sein de structures REPEAT ou WHILE.
LOOP devient sans fin si vous n’utilisez pas l’instruction LEAVE qui passe en séquence du
END LOOP.
Remarque : la directive INTO permet de charger des variables à partir de valeurs de colonnes.
Exemple 1 : extraction de la colonne « compa » pour le pilote de code 'PL-2' dans différents contextes :
Note : Pour traiter des requêtes renvoyant plusieurs enregistrements, il faudra utiliser des curseurs (étudiés
plus loin).
3.10.2.1. Insertions
Exemple :
Note : Dans le cas d’une erreur, une exception qui précise la nature du problème est levée et peut être
interceptée par la directive HANDLER (voir plus loin). Si une telle directive n’existe pas dans le bloc
qui contient l’instruction INSERT, la première exception fera s’interrompre le programme.
3.10.2.2. Modifications
Syntaxe :
9/19
3.10.2.3. Suppressions
Syntaxe :
3.11. Transactions
Définition : Une transaction est un bloc d’instructions LMD faisant passer la base de données d’un état
cohérent à un autre état cohérent. Toutes les instructions de la transaction doivent s’exécuter
entièrement ou pas du tout. Si une erreur survient au cours d’une transaction, toutes les instructions
déjà exécutées sont annulées.
Propriétés : (ACID)
Une transaction assure :
- l’Atomicité des instructions qui sont considérées comme une seule opération (principe du
tout ou rien)
- la Cohérence : passage d’un état cohérent de la base à un autre état cohérent
- l’Isolation des transactions entre elles
- la Durabilité des opérations : les mises à jour perdurent même si une panne se produit après
la transaction
Note :
1. Entre BEGIN et END d’un programme MySQL, il est possible d’écrire plusieurs transactions.
2. Le fait de commencer une transaction termine implicitement celle qui précédait.
10/19
b) implicitement :
1. à la première commande SQL du LDD rencontrée (CREATE, ALTER, DROP…)
2. à la fin normale d’une session utilisateur avec déconnexion
3. à la fin anormale d’une session utilisateur (sans déconnexion).
3.11.2.Mode de validation
Deux modes de fonctionnement sont possibles :
- celui par défaut (autocommit) qui valide systématiquement toutes les instructions reçues par la
base. Dans ce mode, il est impossible de revenir en arrière afin d’annuler une instruction.
- Le mode inverse (autocommit off) qui se déclare à l’aide de l’instruction suivante
Syntaxe :
3.11.3.Exemple de transaction
Etant donnée la procédure suivante :
Etape 1 :
Exécution du bloc dans l’interface,
Etape 2 :
Déconnection soit en cassant la fenêtre (icône en haut à droite), soit proprement avec exit.
Etape 3 :
- On se reconnecte,
- Résultat : l’enregistrement n’est pas présent dans la table ‘TableaVous’. Même quand la fin du
programme est normale, la transaction n’est pas validée (car il manque COMMIT).
Etape 4 :
- Relance du bloc en ajoutant l’instruction COMMIT après l’insertion.
- Résultat : l’enregistrement est présent dans la table, même après une déconnexion douce ou dure.
11/19
L’instruction SAVEPOINT déclare un point de validation :
Syntaxe : SAVEPOINT Label ;
Exemple : Le tableau suivant décrit une transaction MySQL découpée en trois parties. Le programmeur aura le choix
entre les instructions ROLLBACK TO SAVEPOINT indiquées en commentaire pour valider tout ou partie de la
transaction. Il faudra finalement choisir entre COMMIT et ROLLBACK.
Note : Il n’est pas possible d’invalider par ROLLBACK une commande SQL du LDD rencontrée (CREATE,
ALTER, DROP…).
12/19
Partie 2 : Programmation avancée
Cette partie est consacrée à des caractéristiques avancées du langage procédural de MySQL Stored
1.1. Généralités
Une procédure peut être appelée à l’aide :
- de l’interface de commande (par CALL),
- dans un programme externe (Java, PHP, C…),
- par d’autres procédures ou fonctions,
- dans le corps d’un déclencheur.
où :
Délimiteur : délimiteur de commandes différent de « ; » (symbole utilisé obligatoirement en fin de chaque
déclaration et instruction du langage procédural de MySQL
1.4.1. Compilation :
Pour compiler ces sous-programmes à partir de l’interface de commande, il faut procéder comme suit :
delimiter $
Sous programme ;
13/19
$
1.4.2. Appel
La procédure s’appelle toujours par CALL, la fonction par son nom.
Exemple :
a)
delimiter ;
SET @vs_compa = 'AF';
SET @vs_nompil = '';
SET @vs_heures = '';
CALL PlusExperimente (@vs_compa, @vs_nompil, @vs_heures);
b)
delimiter ;
SELECT EffectifsHeure ('AF',300) ;
c)
SET @vs_compa = NULL$
SET @vs_nompil = ''$
SET @vs_heures = ''$
CREATE PROCEDURE test.sp1()
BEGIN
CALL PlusExperimente (@vs_compa,@vs_nompil,@vs_heures);
END;
$
CALL test.sp1()$
2.1. Instructions
Les instructions disponibles pour travailler avec des curseurs sont définies dans le tableau suivant :
Note : Positionnement sur la ligne suivante et chargement de l’enregistrement courant dans une ou
plusieurs variables.
4. Fermeture de curseur : Close
Exemple : CLOSE curs1;
14/19
3. Gestion des exceptions
Afin d’éviter qu’un programme ne s’arrête dès la première erreur suite à une instruction SQL, il est
indispensable de prévoir les cas potentiels d’erreurs et d’associer à chacun de ces cas la programmation d’une
exception (handler dans le vocabulaire de MySQL).
3.1. Syntaxe
DECLARE { CONTINUE | EXIT }
HANDLER FOR
{ SQLSTATE [VALUE] ‘valeur_sqlstate’ | nomException | SQLWARNING
| NOT FOUND | SQLEXCEPTION | code_erreur_mysql }
instructions_MySQL;
où :
- CONTINUE est une directive (appelée handler) qui force la poursuite de l’exécution de programme
lorsqu’il se passe un événement prévu dans la clause FOR.
- EXIT est une directive qui fait sortir l’exécution du bloc courant (entre BEGIN et END).
instructions_MySQL : une ou plusieurs instructions du langage de MySQL (bloc, appel possibles par CALL
d’une fonction ou d’une procédure stockée).
Exemple :
15/19
4. Mise en place de déclencheurs (Triggers)
À la différence des sous-programmes, l’exécution d’un déclencheur n’est pas explicite (par CALL par
exemple), c’est l’événement lui même qui déclenche automatiquement le code programmé dans le
déclencheur.
16/19
serveur. Rappelons qu’avant la version 5.0.10, les déclencheurs ne pouvaient même pas accéder à la
base !
- Mysql dans sa version 5, ne prend en charge que les déclencheurs de type LMD.
4.4. Syntaxe
CREATE TRIGGER nomDéclencheur
{ BEFORE | AFTER } { DELETE | INSERT | UPDATE }
ON nomTable
FOR EACH ROW
{ instruction; |
[etiquette:] BEGIN
instructions;
END [etiquette];
}
Note :
- Chaque enregistrement qui tente d’être supprimé d’une table, qui inclut un déclencheur de type
DELETE FOR EACH ROW, est désigné par OLD au niveau du code du déclencheur. L’accès aux
colonnes de ce pseudo-enregistrement dans le corps du déclencheur se fait par la notation pointée.
- Chaque enregistrement qui tente d’être ajouté dans une table est désigné par NEW au niveau du code
du déclencheur. L’accès aux colonnes de ce pseudo-enregistrement dans le corps du déclencheur se
fait par la notation pointée.
Dans tout déclencheur (de type BEFORE ou AFTER), une erreur lors de l’exécution et toutes les
instructions du bloc sont invalidées.
L’invalidation dans un déclencheur se traduit en général par le déclenchement d’une exception (qui fait
avorter l’instruction LMD), et par le retour d’un message d’erreur personnalisé.
Les procédures et déclencheurs MySQL ne permettent pour l’instant ni de provoquer une exception
système ni de retourner un code SQL personnalisé. Il n’est pas non plus possible d’utiliser ROLLBACK
dans un déclencheur
Une seule solution, qui n’est pas du tout satisfaisante, comme nous allons le voir, consisterait à provoquer
artificiellement une erreur (mais pas une erreur système, par exemple accéder à une table inexistante). Il
faut une erreur sémantiquement correcte qui pose problème à l’exécution (NULL dans une clé primaire).
Exemple :
Considérons la contrainte que « tout pilote ne peut être qualifié sur plus de trois types d’appareils ». Ici, il s’agit
d’assurer la cohérence entre la valeur de la colonne nbQualif de la table Pilote et les enregistrements de la
table Qualifications.
17/19
Ensuite:
Syntaxe :
DROP TRIGGER [nomBase.]nomDéclencheur;
Note : Le fait de détruire une table a pour conséquence d’effacer aussi tous les déclencheurs qui lui sont
associés.
- L’instruction EXECUTE lance l’ordre paramétré avec éventuellement la clause USING qui reliera les
paramètres aux variables de session.
- supprime le contenu de l’ordre (une fin de session désalloue tous les ordres ouverts)
18/19
Exemple 1 : Considérons la table Avion suivante :
La procédure suivante utilise la construction dynamique de l’extraction des avions dont le nombre d’heures de vol
est égal à un paramètre spécifié par une variable de session (ici évaluée à 1 000). La requête est elle-même stockée
dans une variable de session.
Delimiter $
-- Déclaration des variables de session
SET @vs_chaine = ‘SELECT * FROM Avion WHERE nbHVol=?’ $
SET @vs_nbhVol = 1000$
-- Déclaration de la procédure
CREATE PROCEDURE sousProg()
BEGIN
-- Préparation de l’ordre.
PREPARE etat FROM @vs_chaine;
-- Exécution de l’ordre
EXECUTE etat USING @vs_nbhVol;
19/19