Search for notes by fellow students, in your own course and all over the country.
Browse our notes for titles which look like what you need, you can preview any of the notes via a sample of the contents. After you're happy these are the notes you're after simply pop them into your shopping cart.
Document Preview
Extracts from the notes are below, to see the PDF you'll receive please use the links above
CHEZ LE MÊME ÉDITEUR
Du même auteur
C
...
– De UML à SQL
...
C
...
– SQL pour Oracle – 2e édition
...
Autour de SQL et MySQL
P
...
PRATT – Initiation à SQL
...
A
...
TAYLOR
...
N°25413, 2002, 428 pages
...
LENTZNER
...
N°25359, 2001, 254 pages
...
KOFLER
...
Guide de lʼadministrateur et du développeur
...
J
...
AQUILINA
...
N°25451, 2002, 384 pages
...
-M
...
– PHP/MySQL avec Flash MX 2004
...
P
...
CHARNAY et J
...
ROUET
...
N°11678, 2005, 212 pages
...
-M
...
– PHP/MySQL avec Dreamweaver 2004 (best of)
...
����������������
���������
���
����
�����
��������������������������
ÉDITIONS EYROLLES
61, bd Saint-Germain
75240 Paris Cedex 05
www
...
com
Le code de la propriété intellectuelle du 1er juillet 1992 interdit en effet expressément la photocopie à
usage collectif sans autorisation des ayants droit
...
En application de la loi du 11 mars 1957, il est interdit de reproduire intégralement ou partiellement le
présent ouvrage, sur quelque support que ce soit, sans autorisation de l’éditeur ou du Centre Français d’Exploitation du
Droit de Copie, 20, rue des Grands-Augustins, 75006 Paris
...
Pour René et Lydie, Jean et Denise qui sont devenus mes parents
...
XVII
Avant-propos
...
XX
Première partie : SQL de base
...
XX
Troisième partie : langages et outils
...
XX
Typographie
...
XXII
Introduction
...
Modèle de données
...
Les clés
...
Un peu d’histoire
...
Licences
...
Notion de schéma (database)
...
Aspects étudiés
...
Installation
...
Reconfiguration
...
L’interface de commande
...
Connexion au serveur
...
Options de base
...
Votre prompt, et vite !
...
1
2
2
3
3
4
5
6
6
6
7
8
9
9
10
10
10
10
11
12
12
13
14
14
15
© Éditions Eyrolles
VII
Apprendre SQL avec MySQL
Partie I
Table des matières
SQL de base
...
37
Insertions d’enregistrements (INSERT)
...
Renseigner toutes les colonnes
...
Plusieurs enregistrements
...
Données binaires
...
Dates et heures
...
Utilisation en tant que clé primaire
...
Utilisation en tant que clé étrangère
...
Syntaxe (UPDATE)
...
Modification de plusieurs colonnes
...
Ne pas respecter les contraintes
...
Création d’une table (CREATE TABLE)
...
Sensibilité à la casse
...
Premier exemple
...
Conventions recommandées
...
Structure d’une table (DESCRIBE)
...
Index
...
Création d’un index (CREATE INDEX)
...
Destruction d’un schéma
...
Ordre des suppressions
...
2
Définition des données
...
Dates et intervalles
...
Suppressions d’enregistrements
...
Instruction TRUNCATE
...
Syntaxe
...
Contraintes côté « père »
...
Clés composites et nulles
...
Cohérence du père vers le fils
...
Insertions à partir d’un fichier
...
3
Évolution d’un schéma
...
Modifications structurelles (ALTER TABLE)
...
Renommer des colonnes
...
Valeurs par défaut
...
Modifications comportementales
...
Suppression de contraintes
...
Réactivation des contraintes
...
Exercices
...
83
Généralités
...
Pseudotable
...
Extraction de toutes les colonnes
...
Alias
...
© Éditions Eyrolles
83
84
84
85
86
86
87
87
IX
Apprendre SQL avec MySQL
Table des matières
Expressions et valeurs nulles
...
Concaténation
...
Limitation du nombre de lignes
...
Opérateurs de comparaison
...
Opérateurs intégrés
...
Fonctions
...
Numériques
...
Dates
...
Comparaisons
...
Autres fonctions
...
Fonctions de groupe
...
Opérateurs ensemblistes
...
Exemple
...
Opérateurs UNION et UNION ALL
...
Ordonner les résultats
...
Bilan
...
Classification
...
Jointures SQL2
...
Équijointure
...
Inéquijointure
...
Jointures procédurales
...
Sous-interrogations synchronisées
...
X
88
89
89
90
90
91
92
93
93
95
95
95
99
100
101
105
106
107
108
109
110
111
114
114
115
115
116
117
118
119
120
121
121
122
122
123
123
125
127
128
132
136
137
140
© Éditions Eyrolles
Table des matières
Apprendre SQL avec MySQL
Division
...
Classification
...
Division exacte
...
Écriture dans un fichier
...
5
142
143
143
144
144
145
146
147
Contrôle des données
...
Classification
...
Modification d’un utilisateur
...
Suppression d’un utilisateur (DROP USER)
...
Création d’une base (CREATE DATABASE)
...
Modification d’une base (ALTER DATABASE)
...
Privilèges
...
Tables de la base mysql
...
user
...
Table mysql
...
Table mysql
...
Table mysql
...
Table mysql
...
Table mysql
...
Révocation de privilèges (REVOKE)
...
Accès distants
...
Table mysql
...
Vues
...
Classification
...
Vues complexes
...
Transmission de droits
...
© Éditions Eyrolles
152
152
152
154
154
155
155
156
157
158
158
158
159
159
160
163
167
167
168
168
168
170
172
172
173
173
175
176
177
177
181
185
188
188
XI
Apprendre SQL avec MySQL
Table des matières
Visualisation d’une vue (SHOW CREATE VIEW)
...
Dictionnaire des données
...
Modèle graphique du dictionnaire des données
...
Classification des vues
...
Composition d’une base
...
Structure d’une table
...
Composition des contraintes d’une table
...
Privilèges des utilisateurs d’une base de données
...
Exercices
...
207
6
Bases du langage de programmation
...
Environnement client-serveur
...
Structure d’un bloc
...
Casse et lisibilité
...
Commentaires
...
Variables scalaires
...
Restrictions
...
Opérateurs
...
Conventions recommandées
...
Structures de contrôle
...
Structures répétitives
...
Extraire des données
...
XII
189
189
190
190
191
191
193
194
195
195
196
198
199
200
201
203
205
209
209
210
210
211
211
212
212
212
213
213
213
214
214
215
215
216
217
217
219
222
223
224
© Éditions Eyrolles
Table des matières
Apprendre SQL avec MySQL
Transactions
...
Début et fin d’une transaction
...
Votre première transaction
...
Transactions imbriquées
...
7
227
227
228
228
228
229
230
231
Programmation avancée
...
Généralités
...
Fonctions cataloguées
...
Exemples
...
Compilation
...
Récursivité
...
Modification d’un sous-programme
...
Restrictions
...
Généralités
...
Parcours d’un curseur
...
Restrictions
...
Généralités
...
Exceptions avec EXIT
...
Gestion des autres erreurs (SQLEXCEPTION)
...
Exceptions nommées
...
Généralités
...
Mécanisme général
...
Déclencheurs LMD (de lignes)
...
Dictionnaire des données
...
Invalidation dans le déclencheur
...
Restrictions
...
SQL dynamique
...
Exemples
...
Exercices
...
287
Utilisation avec Java
...
Classification des pilotes (drivers)
...
sql
...
Test de votre configuration
...
Base Access
...
Interface Connection
...
Interfaces disponibles
...
États simples (interface Statement)
...
Correspondances de types
...
Suppression de données
...
Modification d’enregistrements
...
Curseurs statiques
...
Curseurs modifiables
...
Modifications
...
XIV
271
272
273
275
277
278
278
278
279
280
281
284
289
290
291
291
292
293
294
295
295
296
296
296
297
298
298
300
300
301
301
301
302
303
307
309
310
310
© Éditions Eyrolles
Table des matières
Apprendre SQL avec MySQL
Gestion des séquences
...
Curseur modifiable
...
Interface DatabaseMetaData
...
Extraction de données (executeQuery)
...
Instruction LDD (execute)
...
Exemple
...
Points de validation
...
Affichage des erreurs
...
Exercices
...
327
Configuration adoptée
...
Fichiers de configuration
...
Test d’Apache, de PHP et de MySQL
...
Connexion
...
Extractions
...
Gestion des séquences
...
Procédures cataloguées
...
Exercices
...
349
MySQL Administrator
...
Connexion nommée
...
Gestion des privilèges
...
Options scripts SQL
...
© Éditions Eyrolles
349
349
350
351
351
352
353
354
XV
Apprendre SQL avec MySQL
Table des matières
Composition d’une table
...
Modification d’un schéma
...
MySQL Query Browser
...
Extraction
...
phpMyAdmin
...
Structure d’une table
...
Extractions
...
Exporter
...
TOAD for MySQL
...
Instructions en ligne
...
Création d’objets
...
Exportations
...
Création d’une table
...
Création d’une requête
...
Gestion des utilisateurs
...
Création d’une table
...
Procédures cataloguées
...
Gestion des privilèges
...
355
356
356
358
359
359
360
361
362
363
364
364
365
366
367
368
368
369
370
371
371
373
374
374
375
376
377
378
378
379
380
382
382
383
383
384
Annexe : bibliographie et webographie
...
387
XVI
© Éditions Eyrolles
Remerciements
Je n’ai que deux personnes à remercier
...
Ils sont talentueux et désintéressés, ce qui devient tellement rare dans ce
monde d’individualisme exacerbé
...
Le second dirige la rubrique MySQL du site
Developpez
...
Merci, Pierre Caboche, pour la lecture de la première moitié de l’ouvrage, pour tes remarques
que j’ai (presque) toutes prises en compte, pour les compléments en ligne à propos des opérateurs ensemblistes dans les requêtes
...
Merci pour ton activité et tes tutoriels mis en ligne
sur le site de Developpez
...
© Éditions Eyrolles
XVII
Avant-propos
Nombre d’ouvrages traitent de SQL et de MySQL ; certains résultent d’une traduction hasardeuse et sans vocation pédagogique, d’autres ressemblent à des Bottin téléphoniques ou
proviennent de la traduction de la documentation officielle en moins bien
...
Ce livre a été rédigé avec une volonté de concision et de progression dans sa démarche ; il est
illustré par ailleurs de nombreux exemples et figures
...
mysql
...
Chaque notion importante est introduite par
un exemple simple et que j’espère démonstratif
...
La documentation en ligne de MySQL (MySQL 5 Reference Manual) représente une dizaine
de mégaoctets au format HTML
...
J’ai tenté d’en
extraire seulement les aspects fondamentaux sous la forme d’une synthèse
...
Ce livre résulte de mon expérience de l’enseignement dans le domaine des bases de données
en premier, deuxième et troisième cycles universitaires dans des cursus d’informatique à
vocation professionnelle (IUT, licences et masters professionnels)
...
Les étudiants et enseignants trouveront des exemples pédagogiques pour chaque concept
q
abordé, ainsi que des exercices thématiques
...
q
© Éditions Eyrolles
XIX
Apprendre SQL avec MySQL
Guide de lecture
Ce livre s’organise autour de trois parties distinctes mais complémentaires
...
La deuxième partie décrit la programmation avec le langage procédural
de MySQL
...
Première partie : SQL de base
Cette partie présente les différents aspects du langage SQL de MySQL, en étudiant en détail
les instructions de base
...
Nous étudions aussi SQL dans un
contexte multi-utilisateur (droits d’accès), et au niveau du dictionnaire de données
...
Le chapitre 6 traite
des éléments de base (structure d’un programme, variables, structures de contrôle, interactions
avec la base et transactions)
...
Troisième partie : langages et outils
Cette partie intéressera les programmeurs qui envisagent d’exploiter une base MySQL en
utilisant un langage de programmation
...
0 qui permet de
manipuler une base MySQL 5 par l’intermédiaire d’un programme Java
...
Le chapitre 10 synthétise les fonctionnalités de plusieurs outils graphiques tels que MySQL
Administrator, MySQL Query Browser et phpMyAdmin
...
Annexe
L’annexe contient une bibliographie et des adresses Web
...
(ex : SELECT nom FROM Pilote)
...
Les noms des tables, index, vues, fonctions, procédures… sont précédés d’une
majuscule (exemple : la table CompagnieAerienne contient la colonne nomComp)
...
Dans une instruction SQL, les symboles { } désignent une liste d’éléments, et le symbole « | »
un choix (exemple CREATE { TABLE | VIEW }
...
Ce sigle introduit une définition, un concept ou une remarque importante
...
Ce sigle annonce soit une impossibilité de mise en œuvre d’un concept soit une mise en garde
...
J’en profite pour faire passer le message suivant : si vous travaillez en version 4 de MySQL,
certaines instructions décrites dans ce livre ne fonctionneront pas
...
Web
Ce sigle indique que le code source est téléchargeable à partir du site des éditions Eyrolles
(www
...
com)
...
Ce sigle signale une astuce ou un conseil personnel
...
fr
...
Par ailleurs, un site d’accompagnement de l’ouvrage (errata, corrigés des exercices, source
des exemples et compléments) est en ligne et accessible via www
...
com
...
Nous décrivons, pour
finir, la procédure d’installation de MySQL sous Windows et l’utilisation de l’interface de
commande en ligne pour que vous puissiez programmer en SQL dès le chapitre 1
...
La première norme (SQL1) date de 1987
...
SQL2 a été normalisée en
1992
...
Les
langages SQL des principaux éditeurs sont tous conformes au premier niveau et ont beaucoup
de caractéristiques relevant des niveaux supérieurs
...
Elle comporte de nombreuses parties (concepts objets, entrepôts de données, séries temporelles, accès à des sources non SQL, réplication des données, etc
...
q
SQL peut s’interfacer avec des langages de troisième génération comme C ou Cobol, mais
q
aussi avec des langages plus évolués comme C++, Java ou C#
...
Les SGBD rendent indépendants programmes et données (la modification d’une structure de
q
données n’entraîne pas forcément une importante refonte des programmes d’application)
...
Ils intègrent des outils de développement comme les précompilateurs, les générateurs de
q
code, d’états, de formulaires
...
) dans des champs appelés LOB (Large Object Binary)
...
La table relationnelle (relational table) est la structure de données de base
qui contient des enregistrements appelés aussi « lignes » (rows)
...
Tables et données
Considérons la figure suivante qui présente deux tables relationnelles permettant de stocker
des compagnies, des pilotes et le fait qu’un pilote soit embauché par une compagnie :
Figure 0-1 Deux tables
Compagnie
comp
nrue rue
ville
nomComp
AF
SING
10
7
Paris
Singapour
Air France
Singapore AL
Gambetta
Camparols
Pilote
brevet
2
nom
nbHVol compa
PL-1
PL-2
PL-3
Louise Ente
Jules Ente
Paul Soutou
450
900
1000
AF
AF
SING
© Éditions Eyrolles
Introduction
Les clés
La clé primaire (primary key) d’une table est l’ensemble minimal de colonnes qui permet
d’identifier de manière unique chaque enregistrement
...
La colonne
comp représente le code de la compagnie et la colonne brevet décrit le numéro du brevet
...
Une table peut contenir plusieurs clés candidates ou aucune
...
Une clé étrangère (foreign key) référence dans la majorité des cas une clé primaire d’une autre
table (sinon une clé candidate sur laquelle un index unique aura été défini)
...
Une table peut contenir plusieurs clés étrangères ou aucune
...
Le modèle relationnel est ainsi fondamentalement basé sur les valeurs
...
Les théoriciens considèrent
celles-ci comme des pointeurs logiques
...
MySQL
MySQL est à la fois le nom du SGBD et le nom de la société (qui se nomme en fait
MySQL AB, décrite sur http://www
...
com) dont le siège se trouve en Suède à Uppsala –
compter une cinquantaine de kilomètres au nord de Stockholm
...
D’un point de vue coût, l’utilisation du SGBD sur des projets importants
(entre 250 000 € et 500 000 €) ferait économiser 90 % sur le prix des licences du serveur,
60 % sur les ressources système, 70 % sur le prix du matériel, 50 % sur les tâches d’administration et de support
...
Téléchargée près d’un million de fois en trois semaines (en octobre 2005), la version
production de MySQL doit sa popularité du fait de son caractère open source, de ses fonctionnalités de plus en plus riches, de ses performances, de son ouverture à tous les principaux
langages du marché, de son fonctionnement sur les systèmes les plus courants (les distributions classiques de Linux, Windows, Mac OS, BSD, Novell et les dérivés d’Unix) et de sa
facilité d’utilisation pour des applications Web de taille moyenne
...
Une version majeure comme 3
...
q
bêta correspond à l’implémentation des nouvelles fonctionnalités de la phase alpha, sans
apport important de code
...
q
production est l’étape suivante aussi appelée GA (Generally Available)
...
q
old correspond à la précédente version de production (par rapport à la courante)
...
1
...
0 l’était aussi
...
23
...
23
...
0
...
1
...
0
...
1
...
4
© Éditions Eyrolles
Introduction
Ce qui n’est pas encore planifié reste la prise en charge du stockage de données au format
XML et les extensions objets de SQL3 (principalement les types abstraits, les héritage et les
méthodes)
...
mysql
...
y/en/news
...
y étant le numéro de version majeure, par
exemple actuellement 5
...
iconarchive
...
Figure 0-2 Offre MySQL
API : C, JDBC, ODBC,
...
Fichiers et logs
Données – index - …
Les API permettent d’intégrer SQL dans des programmes de différents langages
...
Le langage procédural de MySQL permet
d’incorporer nativement tout ordre SQL dans un programme
...
Les pilotes ODBC, JDBC, API pour les langages C et C++, et
les outils MySQL Administrator, MySQL Query Browser, et MySQL Migration Toolkit sont à
télécharger puis à installer séparément
...
Dans le cadre d’un
développement d’application entièrement sous licence GPL, MySQL est gratuit
...
Dans tous les autres cas, il est nécessaire d’obtenir une licence commerciale
...
Et la concurrence ?
Elle fait rage
...
Dans la première catégorie, citons principalement Interbase 6 et Firebird de Borland,
PostgreSQL et Berkeley DB
...
Depuis peu, les
grands éditeurs s’ouvrent à la distribution gratuite
...
q
Fin 2004, Sybase offrait ASE Express Edition
...
q
Oracle annonçait, en novembre 2005, une version gratuite avec Oracle Database XE
(Express Edition)
...
q
Peu de temps avant, IBM avait aussi annoncé une licence gratuite de DB2 Express
...
Tout le monde est donc sur les rangs
...
Bien malin
qui pourra prédire qui gagnera sur ce terrain
...
) pouvant être stockés à différents endroits de l’espace
disque
...
On peut aussi assimiler ce concept à la notion de schéma, pour ceux qui connaissent Oracle
...
6
© Éditions Eyrolles
Introduction
q
Pour tous, un utilisateur sera associé à un mot de passe pour pouvoir se connecter et manipuler des tables (s’il en a le droit, bien sûr)
...
) à un
utilisateur
...
Ainsi, deux utilisateurs distincts
(Jules et Paul) se connectant sur la même base (database) ne pourront pas créer chacun
une table de nom Compagnie
...
q
Pour Oracle ou d’autres SGBD, chaque objet appartient à un schéma (user)
...
Compagnie, la seconde Paul
...
La figure suivante illustre deux utilisateurs travaillant sur différentes bases par une interface
qui peut être la fenêtre de commande en ligne (dans la majeure partie des enseignements), ou
un langage de programmation comme C, Java ou PHP (utilisation d’une API)
...
Figure 0-3 Notions de base et d’utilisateur MySQL
Jules
Paul
Interface
mysql
test
bdjules
information_schema
bdpaul
MySQL
Notion d’hôte
MySQL dénomme host la machine hébergeant le SGBD
...
La notion d’identité est basée sur le couple
nom d’utilisateur MySQL (user) côté serveur, machine cliente
...
S’il s’agit du même, il faudra, au
niveau du serveur, éventuellement composer un ensemble de prérogatives équivalent pour les
deux accès (voir le chapitre 5)
...
La figure suivante illustre le fait que deux utilisateurs
peuvent se connecter par deux accès différents
...
Figure 0-4 Notion d’hôte MySQL
Paul
camparols
TCP-IP
gambetta
brassens
jules @gambetta
paul @camparols
Jules
Paul
paul@gambetta
mysql
test
...
Nous étudierons au
chapitre 9 des outils graphiques d’aide à l’administration
...
Ce livre utilise essentiellement l’interface de commande en ligne
fournie avec le SGBD, mais aussi Java via JDBC, et le navigateur Web au travers de PHP
...
Le tableau suivant indique
dans quel chapitre du livre les principaux éléments d’un schéma sont étudiés :
Tableau 0-3 Éléments d’une base MySQL
Éléments étudiés – Chapitre
Déclencheurs (triggers) – 7
Fonctions et procédures – 7
Tables et index – 1
Séquences – 2, 5
Vues (views) et utilisateurs – 5
8
Aspects non étudiés
Clusters – Moteurs de stockage (storage
engine) – Partitionnement – Données spatiales
© Éditions Eyrolles
Introduction
Mise en œuvre de MySQL (sous Windows)
Si tout se passe bien, comptez quelques minutes pour installer MySQL
...
Extraire l’archive téléchargée sur le site officiel de MySQL AB
(http://dev
...
com/downloads/) dans un répertoire temporaire (exemple : C:\Temp), puis
exécuter Setup
...
Installation
Le premier choix est donné pour le type d’installation : typique, complète et personnalisée –
choisir typique dans un premier temps
...
La suite concerne la configuration du serveur de données (choisir la configuration détaillée
pour suivre les différentes étapes et mieux comprendre le paramétrage de votre serveur)
...
J’ai opté pour le premier choix
...
J’ai opté pour le premier choix
...
J’ai opté pour le choix par défaut
...
J’ai opté pour le premier choix (vingt connexions maximum)
...
J’ai opté pour le
premier choix (mode strict)
...
J’ai
opté pour les choix par défaut (West European et latin1)
...
Penser aussi à inclure dans le path le
chemin de l’exécutable mysql de manière à pouvoir lancer une connexion en ligne de
commande
...
q
Saisissez un mot de passe pour root ; vous pouvez aussi créer un compte anonyme
(connexion fantôme sans utilisateur ni mot de passe)
...
Voilà, MySQL est installé
...
Dernière chose, si vous n’utilisez pas souvent MySQL, pensez à arrêter et à positionner sur
Manuel le service (ce n’est pas pour l’espace qu’il occupe : 10 Mo en RAM)
...
Désinstallation
Pour supprimer une configuration, vous trouverez un assistant dans Démarrer/Tous les
programmes/MySQL/…/MySQL Server Instance Wizard, choix Remove Instance
...
De même qu’en ce qui concerne les entrées dans le menu Démarrer, je ne parle pas de la base de registres qui est inchangée…
Dans Panneau de configuration, Ajout/Suppression de programmes, supprimer
MySQL Server
...
Le répertoire MySQL sous
Program Files a diminué de taille, mais il est toujours présent
...
Prudence si vous modifiez les
chemins des répertoires des données entre plusieurs installations
...
Vous avez aussi la possibilité de
« réparer » (option Repair) une configuration existante
...
Il s’agit de stocker vos fichiers de commande qui pourront servir
à différentes actions (créations de tables, de vues ou d’utilisateurs, insertions, modifications
ou suppressions d’enregistrements, élaboration de requêtes, de procédures cataloguées, etc
...
Cette interface ressemble
à une fenêtre DOS ou telnet et permet de dialoguer de la plus simple façon avec la base de
données
...
Quand l’utilisation est interactive
10
© Éditions Eyrolles
Introduction
(c’est le mode le plus courant), le résultat des extractions est présenté sous une forme tabulaire
au format ASCII
...
) ;
q
de compiler des procédures cataloguées et des déclencheurs ;
q
de réaliser des tâches d’administration (création d’utilisateurs, attribution de privilèges,
etc
...
Figure 0-5 Principe général de l’interface de commande en ligne
mysql [options] [nomBase] [entrées-sorties]
mysql
mysql> INSERT …
Système
d’exploitation
mysql> CREATE …
mysql> SELECT …
…
mysql>
quit ou exit
nomBase
N’ayez pas honte de bien maîtriser cette interface au lieu de connaître toutes les options d’un
outil graphique (comme PhpMyAdmin, MySQL Administrator ou autre)
...
Imaginez-vous un jour à Singapour sur une machine ne disposant pas d’outils graphiques, que
le client vous demande la réduction que vous pouvez lui faire sur la vente d’une piscine intérieure d’un Airbus A380 et que vous devez interroger (ou mettre à jour) une table sur le
serveur du siège social à Blagnac
...
Ouvrez le fichier premierPas
...
Changez « util » par le nom de l’utilisateur à créer (modifiez aussi le nom de la base)
...
Enregistrez ce fichier dans un de vos répertoires
...
mysql --user=root -p
Figure 0-6 Interface en mode ligne de commande
Une fois connecté, par copier-coller (en effectuant un clic droit dans la fenêtre de commande
MySQL), exécutez une à une les différentes instructions (création de la base, de l’utilisateur,
des privilèges et déconnexion de root)
...
Les lignes précédées de « -- » sont des commentaires
...
Pour tester votre connexion,
lancez la commande suivante qui se connecte au serveur sur la base bdutil, sous l’utilisateur util
...
mysql --version
Si vous êtes déjà connecté, la commande « SELECT VERSION(); » vous renseignera également à propos de la version du SGBD
...
Pour ma part lors de la
rédaction de cet ouvrage, cette commande a renvoyé le résultat suivant :
12
© Éditions Eyrolles
Introduction
+-----------+
| VERSION() |
+-----------+
| 5
...
15-nt |
+-----------+
Options de base
Les principales options au lancement de mysql sont résumées dans le tableau suivant :
Tableau 0-4 Principales options de la commande mysql
Option
Commentaire
--help ou -?
Affiche les options disponibles, l’état des variables d’environnement et
rend la main
...
--database=nomBD
ou –D nomBD
Sélection de la base de données à utiliser après la connexion
...
--html ou -H
Formate le résultat des extractions en HTML
...
-p
Demande le mot de passe sans l’employer en tant que paramètre
...
Évitez cette
option et préférez la précédente…
--prompt=parametre
Personnalise l’invite de commande (par défaut mysql>)
...
--skip-column-names
ou -N
N’écrit aucun en-tête de colonne pour les résultats d’extraction
...
--tee=cheminNomFichier Copie la trace de toute la session dans le fichier que vous indiquez
...
--version ou -V
Affiche la version du serveur et rend la main
...
--xml ou -X
© Éditions Eyrolles
Désigne l’utilisateur devant se connecter
...
Les noms de balises
générées sont
pour chaque ligne et
...
txt
--database=bdsoutou va se connecter
anonymement à la base bdsoutou en inscrivant le contenu de la trace de la session dans le
fichier sortiemysql
...
Le tableau suivant résume les principaux paramètres pour afficher les invites de commande
(relatives à l’option prompt)
...
\d
Base de données en cours d’utilisation
...
\u
Nom d’utilisateur
...
\_
Un espace
...
\m
Minutes
...
\Y
Année sur quatre chiffres
...
\c
Compteur d’instructions
...
sql », il faut
préciser le chemin du fichier et celui qui contiendra les éventuels résultats (c’est du « brut de
décoffrage » !)
...
sql situé
dans le répertoire D:\dev (notez l’utilisation du double back-slash pour désigner une arborescence Windows)
...
txt du même répertoire
...
sql >D:\\dev\\sortie
...
L’invite de commande à l’affichage sera de la forme suivante :
14
© Éditions Eyrolles
Introduction
(root@localhost) [bdsoutou]> une fois que root aura sélectionné la base bdsoutou (par la commande « use nombase; »)
...
ini situé en
principe dans le répertoire C:\Program Files\MySQL\MySQL Server xx de la manière qui
vous convient le plus
...
#mon prompt
prompt=(\\u@\\h) [\\d]\\_mysql>\\_
Une fois le serveur redémarré, en considérant que votre compte s’appelle util, toutes vos
commandes SQL devraient en principe être préfixées de la syntaxe suivante :
(util@localhost) [bdutil] mysql>
Commandes de base
Une fois connecté, vous pouvez utiliser des commandes ou faire des copier-coller d’un éditeur
de texte dans l’interface mysql (ce moyen de faire correspond plus à un environnement de
test qui conviendra à l’apprentissage)
...
Tableau 0-6 Commandes de base du buffer d’entrée
Commande
Commentaire
?
Affichage des commandes disponibles
...
use nomBase
Rend une base de données courante
...
quit ou exit
Quitte l’interface
...
sql
Charge et exécute dans le buffer le contenu du
cheminNomFichier
...
sql exécutera le script
Testbatch
...
tee nomFichierSortie
Création nomFichierSortie dans le répertoire
C:\Program Files\MySQL\MySQL Server n
...
La commande source est très utile pour éviter les copier-coller de trop nombreuses instructions
...
À cet effet, nous verrons notamment comment déclarer une table avec ses éventuels index et contraintes
...
Création d’une table (CREATE
TABLE)
Pour pouvoir créer une table dans votre base, il faut que vous ayez reçu le privilège CREATE
...
La syntaxe SQL simplifiée est la suivante :
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] [nomBase
...
)
[ENGINE= InnoDB | MyISAM |
...
Deux connexions peuvent ainsi créer deux tables
temporaires de même nom sans risquer de conflit
...
q
IF NOT EXISTS : permet d’éviter qu’une erreur se produise si la table existe déjà (si
c’est le cas, elle n’est aucunement affectée par la tentative de création)
...
») s’il est omis, il sera assimilé à la base connectée
...
Nous aborderons ces points dans
le chapitre Contrôle des données et nous considérerons jusque-là que nous travaillons dans
la base courante (ce sera votre configuration la plupart du temps)
...
colonnei typei : nom d’une colonne (mêmes caractéristiques que pour les noms des
tables) et son type (INTEGER, CHAR, DATE…)
...
La directive DEFAULT fixe une valeur par défaut
...
NULL représente une valeur qu’on peut considérer comme non disponible, non affectée, inconnue ou inapplicable
...
q
COMMENT : (jusqu’à 60 caractères) permet de commenter une colonne
...
q
nomContraintei typeContraintei : nom de la contrainte et son type (clé primaire,
q
q
clé étrangère, etc
...
ENGINE : définit le type de table (par défaut InnoDB, bien adapté à la programmation de
transactions et adopté dans cet ouvrage)
...
D’autres types existent, citons MEMORY pour les tables temporaires, ARCHIVE, etc
...
Délimiteurs
En mode ligne de commande, il est possible (par la directive delimiter) de choisir le
symbole qui terminera chaque instruction
...
delimiter $
CREATE TABLE Test (t CHAR(8))$
Sensibilité à la casse
Alors que MySQL est sensible par défaut à la casse (au niveau des noms de base et de table)
dans la plupart des distributions Unix, il ne l’est pas pour Windows ! En revanche, concernant
les noms de colonnes, index, alias de colonnes, déclencheurs et procédures cataloguées,
20
© Éditions Eyrolles
chapitre n° 1
Définition des données
MySQL n’est pas sensible à la casse tous systèmes confondus
...
La variable lower_case_table_names permet de forcer la sensibilité à la casse pour
les noms des tables et des bases de données (si elle vaut 0, la sensibilité à la casse est active et
les noms sont stockés en minuscules ; 1, pas de sensibilité à la casse et les noms sont
stockés en minuscules ; 2, pas de sensibilité à la casse et les noms sont stockés en respectant la
casse)
...
De plus, c’est l’option par défaut sur
Linux
...
ini, sous la section serveur identifiée par [mysqld], ajouter la
ligne et le commentaire suivants :
# Rend sensible à la CASSE les noms de tables et de database
lower_case_table_names=0
Refusez ce type de programmation (rendue impossible d’ailleurs si la variable lower_case_
table_names est positionnée à 0)
...
capacite > 150;
Par ailleurs, la casse devrait toujours avoir (quel que soit le SGBD concerné) une incidence
majeure dans les expressions de comparaison entre colonnes et valeurs, que ce soit dans une
instruction SQL ou un test dans un programme
...
Donc, si vous désirez vérifier la casse au sein même des données, il faudra utiliser la fonction
BINARY() qui convertit en bits une expression
...
Commentaires
Dans toute instruction SQL (déclaration, manipulation, interrogation et contrôle des données),
il est possible d’inclure des retours chariot, des tabulations, espaces et commentaires (sur une
ligne précédée de deux tirets « – - », en fin de ligne à l’aide du dièse « # », au sein d’une
ligne ou sur plusieurs lignes entre « /* » et « */ »)
...
;
CREATE TABLE Test (
/* une plus grande description
des colonnes */
COLONNE /* type : */ DECIMAL(38,8));
CREATE TABLE
Test
(colonne
DECIMAL(38,8)
);
Comme nous le conseillons dans l’avant-propos, il est préférable d’utiliser les conventions
suivantes :
• Tous les mots-clés de SQL sont notés en majuscules
...
• Les noms de colonnes et de contraintes en minuscules
...
Premier exemple
Le tableau ci-après décrit l’instruction SQL qui permet de créer la table Compagnie illustrée
par la figure suivante, dans la base bdsoutou (l’absence du préfixe « bdsoutou
...
Figure 1-1 Table à créer
Compagnie
comp
22
nrue rue
ville
nomComp
© Éditions Eyrolles
chapitre n° 1
Définition des données
Tableau 1-2 Création d’une table et de ses contraintes
Instruction SQL
Commentaires
CREATE TABLE bdsoutou
...
La
colonne ville est commentée
...
Contraintes
Les contraintes ont pour but de programmer des règles de gestion au niveau des colonnes des
tables
...
Les contraintes peuvent être déclarées de deux manières :
q
En même temps que la colonne (valable pour les contraintes monocolonnes) ; ces contraintes sont dites « en ligne » (inline constraints)
...
q
Après que la colonne est déclarée ; ces contraintes ne sont pas limitées à une colonne et
peuvent être personnalisées par un nom (out-of-line constraints)
...
Étudions à présent les types de contraintes nommées
(out-of-line)
...
)
PRIMARY KEY (colonne1 [,colonne2]
...
)
REFERENCES nomTablePere [(colonne1 [,colonne2]
...
q
La contrainte PRIMARY KEY déclare la clé primaire de la table
...
Les colonnes clés primaires ne peuvent
être ni nulles ni identiques (en totalité si elles sont composées de plusieurs colonnes)
...
Ces contraintes définissent l’intégrité référentielle que nous aborderons plus tard
...
La contrainte CHECK impose un domaine de valeurs ou une condition simple ou complexe entre
colonnes (exemple : CHECK (note BETWEEN 0 AND 20), CHECK (grade='Copilote' OR
grade='Commandant'))
...
1
...
Nous verrons au chapitre 3 comment ajouter, supprimer, désactiver et réactiver des contraintes
(options de la commande ALTER TABLE)
...
• Pour une contrainte clé primaire, suffixez du nom de la table la contrainte (exemple pk_
Avion)
...
En respectant nos conventions, déclarons les tables de l’exemple suivant (Compagnie avec sa
clé primaire et Avion avec sa clé primaire et sa clé étrangère)
...
Cela résulte de la traduction d’une association un-à-plusieurs entre les deux
tables (De UML à SQL, Eyrolles 2002)
...
24
© Éditions Eyrolles
chapitre n° 1
Définition des données
Figure 1-2 Deux tables reliées à créer
Pilote
brevet
nom
nbHVol compa
Compagnie
comp
nrue rue
ville
nomComp
Tableau 1-3 Contraintes en ligne et nommées
Tables
Contraintes
CREATE TABLE Compagnie
(comp CHAR(4), nrue INTEGER(3),
rue CHAR(20), ville CHAR(15) DEFAULT 'Paris'
COMMENT 'Par defaut : Paris',
nomComp CHAR(15) NOT NULL,
CONSTRAINT pk_Compagnie PRIMARY KEY(comp));
Deux contraintes en ligne
et une contrainte nommée
de clé primaire
...
• PRIMARY KEY équivaut à : UNIQUE + NOT NULL + index
...
Il faut créer d’abord les tables « pères » puis les tables « fils »
...
© Éditions Eyrolles
25
Partie I
SQL de base
Types des colonnes
Pour décrire les colonnes d’une table, MySQL fournit les types prédéfinis suivants (built-in
datatypes) :
q
q
caractères (CHAR, VARCHAR, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT) ;
valeurs numériques (TINYINT, SMALLINT, MEDIUMINT, INT, INTEGER, BIGINT,
FLOAT, DOUBLE, REAL, DECIMAL, NUMERIC, et BIT) ;
q
date/heure (DATE, DATETIME, TIME, YEAR, TIMESTAMP) ;
q
données binaires (BLOB, TINYBLOB, MEDIUMBLOB, LONGBLOB) ;
q
énumérations (ENUM, SET)
...
Nous verrons comment utiliser les plus courants au chapitre 2
et les autres au fil de l’ouvrage
...
Les valeurs sont
stockées en ajoutant, s’il le faut, des espaces (trailing spaces) à concurrence de la taille
définie
...
Le type VARCHAR permet de stocker des chaînes de caractères de taille variable
...
Depuis la version 5
...
3
de MySQL, les éventuels espaces de fin de chaîne seront stockés et extraits en conformité
avec la norme SQL
...
Tableau 1-4 Types de données caractères
Type
Commentaire pour une colonne
Chaîne fixe de n
octets ou caractères
...
VARCHAR(n) [BINARY]
Chaîne variable de n
caractères ou octets
...
BINARY(n)
Chaîne fixe de n
octets
...
VARBINARY(n)
Chaîne variable de n
octets
...
TINYTEXT(n)
Flot de n octets
...
TEXT(n)
Flot de n octets
...
MEDIUMTEXT(n)
Flot de n octets
...
LONGTEXT(n)
26
Description
CHAR(n) [BINARY | ASCII
| UNICODE]
Flot de n octets
...
© Éditions Eyrolles
chapitre n° 1
Définition des données
Les types BINARY et VARBINARY sont similaires à CHAR et VARCHAR, excepté par le fait
qu’ils contiennent des chaînes d’octets sans tenir compte d’un jeu de caractères en particulier
...
Ces types sont associés à un jeu de caractères
...
Valeurs numériques
De nombreux types sont proposés par MySQL pour définir des valeurs exactes (entiers ou décimaux
positifs ou négatifs : INTEGER et SMALLINT), et des valeurs à virgule fixe ou flottante (FLOAT,
DOUBLE et DECIMAL)
...
Le tableau suivant décrit ces types :
q
n indique le nombre de positions de la valeur à l’affichage (le maximum est de 255)
...
Tableau 1-5 Types de données numériques
Type
Ensemble de n bits
...
TINYINT[(n)] [UNSIGNED]
[ZEROFILL]
Entier (sur un octet) de -128 à 127 signé, 0 à 255 non signé
...
Le non-zéro est considéré comme vrai
...
SMALLINT[(n)] [UNSIGNED]
[ZEROFILL]
Entier (sur 2 octets) de – 32 768 à 32 767 signé, 0 à 65 535 non
signé
...
INTEGER[(n)] [UNSIGNED]
[ZEROFILL]
Entier (sur 4 octets) de –2 147 483 648 à 2 147 483 647 signé,
0 à 4 294 967 295 non signé
...
FLOAT[(n[,p])] [UNSIGNED]
[ZEROFILL]
Flottant (de 4 à 8 octets) p désigne la précision simple (jusqu’à
7décimales) de -3
...
1 10-38, 0, signé, et de 1
...
4 10+38 non signé
...
7 10+308 à -2
...
2 10-308
à 1
...
DECIMAL[(n[,p])] [UNSIGNED]
[ZEROFILL]
© Éditions Eyrolles
Description
BIT[(n)]
Décimal à virgule fixe, p désigne la précision (nombre de chiffres
après la virgule, maximum 30)
...
27
Partie I
SQL de base
q
q
La directive UNSIGNED permet de considérer seulement des valeurs positives
...
En déclarant une colonne ZEROFILL, MySQL l’affecte automatiquement aussi à UNSIGNED
...
• DOUBLE PRECISION et REAL sont synonymes de DOUBLE
...
• SERIAL est un alias pour BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE
...
5)
...
Les fonctions NOW() et SYSDATE() retournent la date et l’heure courantes
...
Tableau 1-6 Types de données dates et heures
Type
Description
1er
Commentaire pour une colonne
DATE
Sur 3 octets
...
DATETIME
Dates et heures (de 0 h de la première
date à 23 h 59 minutes 59 secondes de
la dernière date)
...
L’affichage est au format
‘YYYY-MM-DD HH:MM:SS’
...
Sur 2 positions : de 70 à
69 (désignant 1970 à 2069)
...
Le format
d’affichage est ‘YYYY’
...
L’heure au format ‘HHH:MM:SS’ sur
3 octets
...
-C
...
‘YYYY-MM-DD HH:MM:SS’) ; mise à
jour à chaque modification sur la table
...
Les quatre types de colonnes BLOB sont
TINYBLOB, BLOB, MEDIUMBLOB et LONGBLOB
...
Tableau 1-7 Types de données binaires
Type
Description
Commentaire pour une colonne
Taille fixe (maximum de 255 octets)
...
Flot de n octets
...
LONGBLOB(n)
Taille fixe (maximum de 4,29 gigaoctets)
...
q
Le type ENUM définit une liste de valeurs permises (chaînes de caractères)
...
Tableau 1-8 Types de données énumération
Type
Description
ENUM('valeur1','valeur2',
...
SET('valeur1','valeur2',
...
Structure d’une table (DESCRIBE)
DESCRIBE (écriture autorisée DESC) est une commande qui vient de SQL*Plus d’Oracle et
qui a été reprise par MySQL
...
DESCRIBE [nomBase
...
Retrouvons la structure
des tables Compagnie et Pilote précédemment créées
...
Les unicités sont
désignées par UNI dans la
colonne Key
...
Les contraintes NOT NULL
nommées (définies via les
contraintes CHECK)
n’apparaissent pas
...
mysql> DESCRIBE Compagnie;
+---------+----------+------+-----+---------+-------+
| Field
| Type
| Null | Key | Default | Extra |
+---------+----------+------+-----+---------+-------+
| comp
| char(4) | NO
| PRI |
|
|
| nrue
| int(3)
| YES |
| NULL
|
|
| rue
| char(20) | YES |
| NULL
|
|
| ville
| char(15) | YES |
| Paris
|
|
| nomComp | char(15) | NO
|
|
|
|
+---------+----------+------+-----+---------+-------+
Restrictions
Les contraintes CHECK définies ne sont pas encore opérationnelles
...
fraction'
...
Les colonnes de type SET sont évaluées par des chaînes de caractères séparés par des « , »
(‘Airbus, Boeing’)
...
Les noms des objets (base, tables, colonnes, contraintes, vues, etc
...
Index
Comme l’index de cet ouvrage vous aide à atteindre les pages concernées par un mot recherché, un index MySQL permet d’accélérer l’accès aux données d’une table
...
Le principe
d’un index est l’association de l’adresse de chaque enregistrement avec la valeur des colonnes
indéxées
...
Avec un index, ce nombre tendra vers log(n) et augmentera donc bien
plus faiblement en fonction de la montée en charge des enregistrements
...
Arbres balancés
La figure suivante illustre un index sous la forme d’un arbre
...
Cette figure est caricaturale, car un index n’est pas un arbre binaire
(plus de deux liens peuvent partir d’un nœud)
...
Figure 1-3 Index sur la colonne nom
Index (nom)
nom ≥ ’D’
nom < ’D’
≥ ’Am’
< ’Am’
< ’Aj’
ROWID
≥ ’Aj’
A
< ’B’
≥ ’T’
< ’T’
≥ ’B’
< ’Q’
C
≥ ’Q’
≥ ’Thl’
F
D
H
ROWID
brevet
nom
nbHVol
PL-1
PL-2
PL-3
PL-4
PL-5
PL-6
PL-7
PL-8
Amélie Sulpice
Thomas Sulpice
Paul Soutou
Aurélia Ente
Agnès Bidal
Sylvie Payrissat
Thierry Guibert
Cathy Castaings
450
900
1000
850
500
2500
600
400
B
compa
A
B
C
D
E
F
G
H
E
≥ ’Thl’
AF
AF
SING
ALIB
SING
SING
ALIB
AF
Pilote
G
Un index est associé à une table et peut être défini sur une ou plusieurs colonnes (dites
« indéxées »)
...
Ils sont mis à jour automatiquement après rafraîchissement de la table (ajouts et suppressions d’enregistrements ou modification des colonnes indéxées)
...
© Éditions Eyrolles
31
Partie I
SQL de base
La plupart des index de MySQL (PRIMARY KEY, UNIQUE, INDEX, et FULLTEXT) sont stockés dans des arbres équilibrés (balanced trees : B-trees)
...
La particularité des index B-tree est qu’ils conservent en permanence une arborescence symétrique (balancée)
...
Le temps de recherche est
ainsi à peu près constant quel que soit l’enregistrement cherché
...
Toutes les feuilles de
l’index sont chaînées entre elles
...
Ces index, premiers apparus, sont désormais très fiables et performants, ils
ne se dégradent pas lors de la montée en charge de la table
...
Si l’utilisateur a le privilège INDEX, il peut créer et supprimer des index dans sa base
...
La syntaxe de création d’un index est la suivante :
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX nomIndex
[USING BTREE | HASH]
ON nomTable (colonne1 [(taille1)] [ASC | DESC],
...
q
FULLTEXT permet de bénéficier de fonctions de recherche dans des textes (flot de caractè-
res)
...
q
ASC et DESC précisent l’ordre (croissant ou décroissant)
...
Tableau 1-10 Créations d’index
Instruction SQL
Index B-tree, ordre décroissant sur les trois
premiers caractères du nom des pilotes
...
© Éditions Eyrolles
chapitre n° 1
Définition des données
Bilan
• Un index ralentit les rafraîchissements de la base (conséquence de la mise à jour de l’arbre
ou des bitmaps)
...
• Il est conseillé de créer des index sur des colonnes (majoritairement des clés étrangères)
utilisées dans les clauses de jointures (voir chapitre 4)
...
• Les index sont pénalisants lorsqu’ils sont définis sur des colonnes très souvent modifiées ou
si la table contient peu de lignes
...
Bien
entendu, si des données sont déjà présentes dans les tables, et que vous souhaitez les garder, il
faudra utiliser une stratégie pour les réimporter dans les nouvelles tables
...
Nous avons vu qu’il fallait créer d’abord les tables « pères » puis les tables « fils » (si des
contraintes sont définies en même temps que les tables)
...
Dans notre exemple, il serait malvenu de supprimer la table Compagnie avant la
table Pilote
...
Suppression d’une table (DROP
TABLE)
Pour pouvoir supprimer une table dans une base, il faut posséder le privilège DROP sur cette
base
...
DROP [TEMPORARY] TABLE [IF EXISTS]
[nomBase
...
]nomTable2,
...
Les transactions en cours ne sont pas
affectées
...
q
RESTRICT et CASCADE ne sont pas encore opérationnels
...
Le second répercutera la destruction à tous les éléments référencés
...
Attention, une suppression ne peut pas être
par la suite annulée
...
Le tableau suivant présente deux écritures possibles pour détruire des schémas
...
Tableau 1-11 Scripts équivalents de destruction
Avec CASCADE (pas encore opérationnel)
DROP TABLE Compagnie CASCADE;
DROP TABLE Pilote;
34
Les « fils » puis les « pères »
DROP TABLE Pilote;
DROP TABLE Compagnie;
© Éditions Eyrolles
chapitre n° 1
Définition des données
Exercices
L’objectif de ces exercices est de créer des tables, leur clé primaire et des contraintes de vérification (NOT NULL et CHECK)
...
1
Présentation de la base de données
Une entreprise désire gérer son parc informatique à l’aide d’une base de données
...
Chaque étage possède son réseau (ou segment distinct) éthernet
...
Un poste de travail est une machine sur
laquelle sont installés certains logiciels
...
La base de données devra aussi décrire les
installations de logiciels
...
120
...
2
Création des tables
Écrire puis exécuter le script SQL (que vous appellerez creParc
...
•
Le domaine de valeurs de la colonne ad s’étend de 0 à 255
...
•
La colonne dateIns est égale à la date du jour par défaut
...
3
nLog
numIns
dateIns
indIP
ad
typePoste
nSalle
prix
delai
nomType
Structure des tables
Écrire puis exécuter le script SQL (que vous appellerez descParc
...
Comparer le résultat obtenu avec le
schéma ci-dessus
...
4
Destruction des tables
Écrire puis exécuter le script SQL de destruction des tables (que vous appellerez dropParc
...
Lancer ce script puis celui de la création des tables à nouveau
...
Nous
verrons que SQL propose trois instructions pour manipuler des données :
l’insertion d’enregistrements : INSERT ;
la modification de données : UPDATE ;
la suppression d’enregistrements : DELETE (et TRUNCATE)
...
q
q
Insertions d’enregistrements (INSERT)
Pour pouvoir insérer des enregistrements dans une table, il faut que vous ayez reçu le privilège
INSERT
...
Syntaxe
La syntaxe simplifiée de l’instruction INSERT monoligne est la suivante :
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] [nomBase
...
)]
VALUES ({expression | DEFAULT},
...
]
q
q
q
q
© Éditions Eyrolles
DELAYED indique que l’insertion est différée (si la table est modifiée par ailleurs, le
serveur attend qu’elle se libère pour y insérer périodiquement de nouveaux enregistrements si elle redevient active entre-temps)
...
HIGH_PRIORITY annule l’option low priority du serveur
...
37
Partie I
SQL de base
q
ON DUPLICATE KEY UPDATE permet de mettre à jour l’enregistrement présent dans
la table, qui a déclenché l’erreur de doublon (dans le cas d’un index UNIQUE ou d’une
clé primaire)
...
À l’aide d’exemples, nous allons détailler les possibilités de cette instruction en considérant la
majeure partie des types de données proposés par MySQL
...
La deuxième insertion utilise le mot-clé DEFAULT pour affecter explicitement
la valeur par défaut à la colonne ville
...
Tableau 2-1 Insertions
Web
Instruction SQL
Commentaires
INSERT INTO Compagnie
Toutes les valeurs sont renseignées
VALUES ('SING', 7, 'Camparols', 'Singapour', dans l’ordre de la structure de la table
...
INSERT INTO Compagnie
VALUES ('AN1', NULL, 'Hoche', 'Blagnac',
'Air Nul1');
NULL explicite
...
La
première insertion affecte implicitement la valeur par défaut à la colonne ville
...
Tableau 2-2 Insertions de certaines colonnes
Web
Instruction SQL
Commentaires
DEFAULT implicite
...
La table Compagnie contient à présent les lignes suivantes :
38
© Éditions Eyrolles
chapitre n° 2
Manipulation des données
Figure 2-1 Table après les insertions
Compagnie
Valeur par défaut
Valeur NULL
comp
nrue
rue
ville
nomComp
SING
AF
AN1
AC
AN2
7
10
Camparols
Gambetta
Hoche
Champs Elysées
Foch
Singapour
Paris
Blagnac
Paris
Blagnac
Singapore AL
Air France
Air Nul1
Castanet Air
Air Nul2
8
Plusieurs enregistrements
Le script suivant ajoute trois nouvelles compagnies en une seule instruction INSERT
...
Paoli','Bastia','Corse Air');
Ne pas respecter des contraintes
Insérons des enregistrements dans la table Pilote, qui ne respectent pas des contraintes
...
La première erreur vient de la clé primaire,
la seconde de l’unicité du nom
...
Nous reviendrons sur ce dernier problème dans la
section Erreur ! Source du renvoi introuvable
...
Des fonctions sont disponibles
pour programmer le « ET », le « OU » exclusif ou inclusif, etc
...
Notez l’utilisation du préfixe « b » pour initialiser un tel type
...
Toute valeur d’une
colonne de ce type devra appartenir à cette liste établie lors de la création de la table
...
On ne stocke qu’un seul diplôme par étudiant
...
Brouard
F
...
Notez que les parenthèses
sont optionnelles pour désigner la colonne ENUM
...
Brouard', ('BTS'));
INSERT INTO UnCursus VALUES
'F
...
Supposons qu’on désire stocker plusieurs
diplômes par étudiant
...
Brouard
F
...
Tableau 2-5 Insertions avec un SET
Création
Insertions (deux bonnes une illicite)
mysql> INSERT INTO Cursus VALUES ('E1',
CREATE TABLE Cursus
'F
...
Degrelle','Licence,INSA,DUT';
CONSTRAINT pk_Cusus PRIMARY KEY(num));
mysql> INSERT INTO Cursus VALUES ('E3',
'Bug', ('BTS,INSA,ENAC'));
ERROR 1265 (01000): Data truncated for
column 'diplomes' at row 1
Dates et heures
Nous avons décrit au chapitre 1 les caractéristiques générales des types MySQL pour stocker
des éléments de type date/heure
...
Nous
verrons que MySQL peut les considérer soit en tant que chaînes de caractères soit comme
numériques
...
Tout autre délimiteur est autorisé comme :
'2005
...
31 11%30%45' (pour les colonnes DATE, '65
...
31', '65/12/31', et
'65@12@31' sont équivalents et désignent tous le réveillon de l’année 1965)
...
Ainsi '19650205063000' est interprété comme le 5 février 1965 à 6 heures et 30 minutes
...
© Éditions Eyrolles
41
Partie I
SQL de base
q
Considérés comme numériques dans les formats suivants : YYYYMMDDHHMMSS ou
YYMMDDHHMMSS (pour les DATE YYYYMMDD ou YYMMDD) en supposant que le nombre ait
un sens en tant que date
...
Par contre 19650205069000 n’a pas de sens du fait des minutes (il
sera interprété comme 00000000000000)
...
INSERT INTO Pilote
VALUES ('PL-1', 'Christian Soutou', '1965-02-05', 900, SYSDATE(), 'AF');
Nous verrons au chapitre 4 comment extraire les années, mois, jours, heures, minutes et
secondes
...
Exemple avec TIME et YEAR
Par analogie aux différents formats des dates, les heures (type TIME 'HH:MM:SS' ou
'HHH:MM:SS') peuvent aussi être manipulées sous la forme de chaînes ou de nombres
...
fraction' avec le nombre de jours (0 à 34) et la fraction de
seconde (pas encore opérationnelle), 'HH:MM:SS
...
q
Chaîne sans les délimiteurs sous réserve que la chaîne ait un sens
...
q
Nombre en raisonnant comme les chaînes
...
Les formats suivants sont aussi corrects : SS, MMSS, HHMMSS
...
CREATE TABLE Pilote
(brevet VARCHAR(6), nom VARCHAR(20), pasVolDepuis TIME, retraite YEAR,
CONSTRAINT pk_Pilote PRIMARY KEY(brevet));
42
© Éditions Eyrolles
chapitre n° 2
Manipulation des données
Les insertions suivantes utilisent différents formats
...
INSERT
INSERT
INSERT
INSERT
INSERT
INTO
INTO
INTO
INTO
INTO
Pilote VALUES ('PL-1', 'Hait', '1 23:0:0', '2002');
Pilote VALUES ('PL-2', 'Crampes', '152630', 2006);
Pilote VALUES ('PL-3', 'Tuffery', '4 23:00', 05);
Pilote VALUES ('PL-4', 'Mercier', 032750, '07');
Pilote VALUES ('PL-5', 'Albaric', '1 23:0:0
...
Exemple avec TIMESTAMP
Toute colonne du type TIMESTAMP est actualisée à chaque modification de l’enregistrement :
la première fois à l’INSERT, puis à chaque UPDATE (quelle que soit la colonne mise à jour)
...
CREATE TABLE Pilote
(brevet VARCHAR(6), nom VARCHAR(20), misaJour TIMESTAMP,
CONSTRAINT pk_Pilote PRIMARY KEY(brevet));
L’insertion du pilote suivant initialisera la colonne à la date système (comme SYSDATE)
...
© Éditions Eyrolles
43
Partie I
SQL de base
Même si vous croyez mettre à NULL cette colonne avec une instruction UPDATE, elle contiendra toujours l’instant de votre vaine tentative !
Fonctions utiles
Les fonctions CURRENT_TIMESTAMP(), CURRENT_DATE() et CURRENT_TIME(), UTC_
TIME(), renseignent sur l’instant, la date, l’heure et l’heure GMT de la session en cours
...
L’exemple suivant montre que la requête a été exécutée le 1er novembre 2005 à
10 heures, 11 minutes et 27 secondes
...
mysql> SELECT CURRENT_TIMESTAMP(), CURRENT_TIME(), CURRENT_DATE(), UTC_
TIME();
+---------------------+----------------+----------------+------------+
| CURRENT_TIMESTAMP() | CURRENT_TIME() | CURRENT_DATE() | UTC_TIME() |
+---------------------+----------------+----------------+------------+
| 2005-11-01 10:11:27 | 10:11:27
| 2005-11-01
| 09:11:27
|
+---------------------+----------------+----------------+------------+
Séquences
Bien que « séquence » ne soit pas dans le vocabulaire de MySQL, car le mécanisme qu’il
propose n’est pas aussi puissant que celui d’Oracle, MySQL offre la possibilité de générer
automatiquement des valeurs numériques
...
Ce mécanisme répond en grande partie à ce qu’on attendrait d’une séquence
...
Cette colonne est clé primaire, ou unique et non nulle
...
Utilisation en tant que clé primaire
La figure suivante illustre la séquence appliquée à la colonne numAff pour initialiser les
valeurs de la clé primaire de la table Affreter
...
44
© Éditions Eyrolles
chapitre n° 2
Manipulation des données
Figure 2-4 Séquence appliquée à une clé primaire
Affreter
numAff
comp
immat
dateAff
nbPax
1
2
3
4
AF
SING
AF
AF
F-WTSS
F-GAFU
F-WTSS
F-GLFS
13-05-2005
05-02-2005
11-09-2005
11-09-2005
LAST_INSERT_ID()
85
155
90
75
⇒ 4
AUTO_INCREMENT
Le tableau suivant décrit la création de cette table et différentes écritures pour les insertions
...
Seules les valeurs à venir de la séquence modifiée seront changées (heureusement pour les données existantes des tables)
...
Le prochain affrètement sera estimé à 100 et les insertions suivantes prendront en
compte le nouveau point de départ tout en laissant intactes les données existantes des tables
...
Servons-nous aussi de la séquence de la table Affreter pour indiquer le dernier vol de
chaque passager
...
Figure 2-5 Séquence appliquée à une clé étrangère
Passager
LAST_INSERT_ID()
⇒ 101
numPax
nom
siege
dernie rVol
100
101
Payrissat
Castaings
7A
2E
2
3
AUTO_INCREMENT
Affreter
LAST_INSERT_ID()
numAff
comp
immat
dateAff
1
2
3
AF
SING
AF
F-WTSS
F-GAFU
F-WTSS
13-05-2005
05-02-2005
15-05-2005
85
155
82
⇒ 3
nbPax
AUTO_INCREMENT
Le script SQL de définition et de manipulation des données est indiqué ci-après
...
Notez également
l’utilisation de la fonction LAST_INSERT_ID dans les insertions pour récupérer la valeur de
la clé primaire
...
Pour pouvoir modifier
des enregistrements d’une table, il faut que cette dernière soit dans votre base ou que vous
ayez reçu le privilège UPDATE sur la table
...
] nomTable
SET col_name1=expr1 [, col_name2=expr2
...
]
[WHERE (condition)]
[ORDER BY listeColonnes]
[LIMIT nbreLimite]
q
q
q
© Éditions Eyrolles
LOW_PRIORITY indique que la modification est différée à la libération complète de la
table (option à ne pas utiliser sur des tables MyISAM)
...
La clause SET actualise une colonne en lui affectant une expression (valeur, valeur par
défaut, calcul ou résultat d’une requête)
...
Si aucune condition
n’est précisée, tous les enregistrements seront actualisés
...
ORDER BY indique l’ordre de modification des colonnes
...
Modification d’une colonne
Modifions la compagnie de code 'AN1' en affectant la valeur 50 à la colonne nrue
...
UPDATE Compagnie SET nrue = 14, ville = DEFAULT WHERE comp = 'AN2';
La table Compagnie contient à présent les données suivantes :
Figure 2-6 Table après les modifications
Compagnie
Modification 1
comp
nrue
rue
ville
nomComp
SING
AF
AN1
AC
AN2
7
10
50
8
14
Camparols
Gambetta
Hoche
Champs Elysées
Foch
Modifications 2
Singapour
Paris
Blagnac
Paris
Paris
Singapore AL
Air France
Air Nul1
Castanet Air
Air Nul2
Modification de plusieurs enregistrements
Modifions les deux premières compagnies (par ordre de clé primaire, ici 'AC' et 'AF') en affectant la valeur 'Toulouse' à la colonne ville
...
Dans le cas inverse, une erreur est renvoyée (le nom de la contrainte apparaît) et la mise à
jour n’est pas effectuée
...
La mise à jour d’une clé étrangère est possible si elle n’est pas référencée
par une clé primaire (voir la section Intégrité référentielle)
...
Dates et intervalles
Le tableau suivant résume les principales opérations possibles entre des colonnes de type dateheure
...
INSERT INTO Pilote VALUES
('PL-1', 'Thierry Albaric','1967-03-25','2005-10-30', SYSDATE(),
'2005-11-13 15:30:00', NULL, NULL, NULL, NULL, NULL, 'AF');
Les mises à jour par UPDATE sur cet enregistrement vont consister, sur la base de ces quatre
dates, à calculer les intervalles illustrés à la figure suivante :
50
© Éditions Eyrolles
chapitre n° 2
Manipulation des données
Figure 2-9 Intervalles à calculer
nombreJoursNaisBoulot
intervalleEntreVols
dernierVol
30-10-2005
dateNais
23/5/1967
qui passe à 12h35
intervalleNaisBoulot
dateEmbauche
02-11-2005
x h y min
qui passe à
09-11-2005
x h y+10 min
intervalleEmbaucheControle
prochainVolControle
13-11-2005
15h30
intervalleVolExterieur
Modification d’une heure
On modifie une date en précisant une heure via la fonction en rajoutant le format 'HH:MM:SS'
quels que soient les délimiteurs (ici « : »)
...
L’ajout d’un intervalle s’opère par la fonction DATE_ADD couplée à la directive DAY_MINUTE qui permet de
spécifier un jour, une heure et une minute
...
UPDATE Pilote
SET dateEmbauche = DATE_ADD(dateEmbauche,INTERVAL '7 0:10' DAY_MINUTE)
WHERE brevet
= 'PL-1';
Différence entre deux dates
La différence entre deux dates peut se programmer à l’aide de la fonction DATEDIFF qui
renvoie un entier correspondant au nombre de jours séparant les deux dates
...
Cette
fonction effectue la différence entre deux dates suivant un format d’intervalle donné (ici on
obtient des secondes qu’on divise par (24*3600) pour convertir en jours)
...
UPDATE Pilote SET
intervalleEmbaucheControle =
SEC_TO_TIME((intervalleEntreVols - intervalleVolExterieur)*24*3600)
WHERE brevet = 'PL-1';
La ligne contient désormais les informations suivantes
...
On trouve qu’il a fallu 14 109,126875 jours pour que ce pilote soit embauché
...
14,645833 jours, séparent son dernier vol de son prochain contrôle en vol
...
Figure 2-10 Ligne modifiée par des calculs de dates
Pilote
brevet nom
PL-1
Thierry Albaric
nombreJoursNaisBoulot
13186
...
645833
dateNaiss
dernierVol
1967-03-25
1967-03-25 12:35:00
intervalleNaisBoulot
2005-10-30
dateEmbauche
2005-11-02 15:27:42
2005-11-09 15:37:42
2005 -11-13 15:30:00
intervall eVolExterieur
14109
...
651181
compa
AF
Nous verrons au chapitre 4, comment convertir en jours, heures, minutes et secondes un décimal de grande taille
...
• DATE_FORMAT(date,format) convertit une date (heure) suivant un certain format
...
• FROM_DAYS(n) retourne une date à partir d’un entier (le 1/1/0001 correspond à 366) ;
UNIX_TIMESTAMP(date) retourne le nombre de secondes qui se sont écoulées depuis le
1er janvier 1970 jusqu’à la date (heure) en paramètre
...
• SEC_TO_TIME(secondes) convertit un nombre en un type TIME et son inverse TIME_TO_
SEC(time)
...
• TIME(expression)extrait d’une date (heure) un type TIME
...
Les tableaux suivants présentent quelques exemples d’utilisation de ces fonctions :
Tableau 2-11 Quelques formats pour DATE_FORMAT et STR_TO_DATE
Expression
Résultat
Commentaire
DATE_FORMAT(SYSDATE(),'%j')
306
Ce n’est pas la vitesse de Daniel
dans Taxi2, mais le numéro du jour
de l’année (ici il s’agit du
2 novembre 2005)
...
STR_TO_DATE('11/09/2005
15:37:42','%d/%m/%Y
%H:%i:%s')
2005-09-11 15:37:42
Conversion d’une chaîne typée date
française au format DATETIME
...
EXTRACT(MONTH FROM dateNaiss)
3
Extraction du mois contenu dans la colonne
...
8850 Le 2 novembre 2005 au soir, 13 089 jours et
des poussières s’étaient écoulés depuis
1970
...
Il faut avoir les privilèges INSERT et DELETE sur la
table
...
Si la table ne dispose pas d’une contrainte PRIMARY KEY ou UNIQUE, l’utilisation de REPLACE
n’a pas de sens et devient équivalente à INSERT
...
] nomTable [(colonne1,
...
]
q
LOW_PRIORITY et DELAYED ont la même signification que pour INSERT et UPDATE
...
L’instruction suivante remplace l’enregistrement relatif à la compagnie de code 'AN1' (voir
figure 2-6) :
REPLACE INTO Compagnie VALUES ('AN1', 24, 'Salas', 'Ramonville',
'Air RENATO');
Suppressions d’enregistrements
Les instructions DELETE et TRUNCATE permettent de supprimer un ou plusieurs enregistrements d’une table
...
Instruction DELETE
La syntaxe simplifiée de l’instruction DELETE est la suivante :
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM [nomBase
...
© Éditions Eyrolles
chapitre n° 2
Manipulation des données
QUICK (pour les tables de type MyISAM) ne met pas à jour les index associés pour accélérer
le traitement
...
Si aucune condition n’est précisée, toutes les lignes seront détruites
...
q
ORDER BY réalise un tri des enregistrements qui seront effacés dans cet ordre
...
La première commande supprime tous les pilotes de la compagnie de code 'AF',
la seconde, avec une autre écriture, détruit la compagnie de code 'AF'
...
Il s’affiche une erreur qui sera expliquée dans la section Intégrité référentielle
...
DELETE FROM Compagnie LIMIT 2;
Instruction TRUNCATE
La commande TRUNCATE est une extension de SQL qui a été proposée par Oracle et reprise
par MySQL
...
La syntaxe est la suivante :
TRUNCATE [TABLE] [nomBase
...
Pour les autres moteurs,
l’opération diffère de DELETE de la manière suivante :
q
La table est supprimée (DROP) puis recréée (CREATE), ce qui est plus rapide que de
détruire les enregistrements un à un
...
q
Le nombre d’enregistrements supprimés n’est pas retourné
...
© Éditions Eyrolles
55
Partie I
SQL de base
Il n’est pas possible de « tronquer » une table qui est référencée par des clés étrangères actives
...
Intégrité référentielle
L’intégrité référentielle forme le cœur de la cohérence d’une base de données relationnelle
...
Ce faisant, la plupart des contrôles côté client (interface)
sont ainsi déportés côté serveur
...
Il faut savoir que les déclencheurs sont
plus pénalisants que des contraintes dans un mode transactionnel
...
Pour la table « père », ces colonnes composent la clé primaire (ou candidate avec un
index unique)
...
Syntaxe
C’est seulement dans sa version 3
...
44 en 2002 (dix ans après Oracle), que MySQL a inclus
dans son offre les contraintes référentielles pour les tables InnoDB
...
Il est conseillé de nommer la
contrainte, sinon MySQL s’en charge
...
Les deux tables ne doivent pas être temporaires
...
Une table peut être « père » pour
une contrainte et « fils » pour une autre (c’est le cas de la table Avion)
...
Il est
cependant possible d’insérer un « fils » (ou de modifier sa clé étrangère) sans rattacher
d’enregistrement « père », à la condition qu’il n’existe pas de contrainte NOT NULL au
niveau de la clé étrangère
...
Il est possible de supprimer les « fils » associés (DELETE CASCADE), d’affecter la valeur nulle aux clés étrangères
des « fils » associés (DELETE SET NULL) ou de répercuter une modification de la clé primaire du père (UPDATE CASCADE et UPDATE SET NULL)
...
Contraintes côté « père »
Le tableau suivant illustre les deux possibilités (clé primaire ou candidate) dans le cas de la
table Compagnie
...
© Éditions Eyrolles
57
Partie I
SQL de base
Tableau 2-13 Écritures des contraintes de la table « père »
Clé primaire
Clé candidate
CREATE TABLE Compagnie
(comp CHAR(4), nrue INTEGER(3),
rue CHAR(20), ville CHAR(15),
nomComp CHAR(15),
CONSTRAINT pk_Compagnie PRIMARY
KEY(comp));
CREATE TABLE Compagnie
(comp CHAR(4) NOT NULL, nrue INTEGER(3),
rue CHAR(20), ville CHAR(15),
nomComp CHAR(15),
CONSTRAINT un_Compagnie UNIQUE(comp),
CONSTRAINT pk_Compagnie PRIMARY
KEY(nomComp));
Contraintes côté « fils »
Indépendamment de l’écriture de la table « père », plusieurs écritures sont possibles au niveau
de la table « fils » selon qu’on créé les index ou qu’on laisse MySQL le faire, et selon qu’on
nomme ou pas la contrainte de clé étrangère
...
La
deuxième ne nomme pas la contrainte, mais définit l’index (sans option toutefois)
...
Tableau 2-14 Écritures des contraintes de la table « fils »
Contrainte nommée sans index
Contrainte pas nommée et index
CREATE TABLE Pilote
(brevet CHAR(6), nom CHAR(15),
nbHVol DECIMAL(7,2), compa CHAR(4),
CONSTRAINT pk_Pilote
PRIMARY KEY(brevet),
CONSTRAINT fk_Pil_compa_Comp
FOREIGN KEY (compa)
REFERENCES Compagnie(comp));
CREATE TABLE Pilote
(brevet CHAR(6), nom CHAR(15),
nbHVol DECIMAL(7,2), compa CHAR(4),
CONSTRAINT pk_Pilote
PRIMARY KEY(brevet),
INDEX (compa),
FOREIGN KEY (compa) REFERENCES
Compagnie(comp));
Clés composites et nulles
Les clés étrangères ou primaires peuvent être définies sur plusieurs colonnes (16 au maximum), on parle de composite keys
...
Décrivons à présent le script SQL qui convient à notre exemple (la syntaxe de création des
deux premières tables a été discutée plus haut) et étudions ensuite les mécanismes programmés par ces contraintes
...
58
© Éditions Eyrolles
chapitre n° 2
Manipulation des données
CREATE TABLE Avion
(immat CHAR(6), typeAvion CHAR(15), nbhVol DECIMAL(10,2),
proprio CHAR(4) NOT NULL, CONSTRAINT pk_Avion PRIMARY KEY(immat),
INDEX (proprio),
CONSTRAINT fk_Avion_comp_Compag
FOREIGN KEY(proprio) REFERENCES Compagnie(comp));
CREATE TABLE Affreter
(compAff CHAR(4), immat CHAR(6), dateAff DATE, nbPax INTEGER(3),
CONSTRAINT pk_Affreter PRIMARY KEY (compAff, immat, dateAff),
INDEX (immat),
CONSTRAINT fk_Aff_na_Avion
FOREIGN KEY(immat) REFERENCES Avion(immat),
INDEX (compAff),
CONSTRAINT fk_Aff_comp_Compag
FOREIGN KEY(compAff) REFERENCES Compagnie(comp));
Cohérence du fils vers le père
Si la clé étrangère est déclarée NOT NULL, l’insertion d’un enregistrement « fils » n’est possible
que s’il est rattaché à un enregistrement « père » existant
...
Le tableau suivant décrit des insertions correctes et une incorrecte
...
Tableau 2-15 Insertions correctes et incorrectes
Insertions correctes
Web
-- fils avec père
INSERT INTO Pilote VALUES
('PL-3', 'Paul Soutou', 1000, 'SING');
-- fils sans père
INSERT INTO Pilote VALUES
('PL-4', 'Un Connu', 0, NULL);
-- fils avec pères
INSERT INTO Avion VALUES
('F-WTSS', 'Concorde', 6570, 'SING');
INSERT INTO Affreter VALUES
('AF', 'F-WTSS', '15-05-2003', 82)
Insertion incorrecte
-- avec père inconnu
mysql> INSERT INTO Pilote VALUES
('PL-5', 'Pb de Compagnie', 0, '?' );
ERROR 1452 (23000): Cannot add or update
a child row: a foreign key constraint
fails (`bdsoutou/pilote`, CONSTRAINT
`fk_Pil_compa_Comp` FOREIGN KEY (`compa`)
REFERENCES `compagnie` (`comp`))
Pour insérer un affrètement, il faut donc avoir ajouté au préalable au moins une compagnie et
un avion
...
Ici il faut insérer d’abord les compagnies, puis les pilotes (ou les avions),
enfin les affrètements
...
Cohérence du père vers le fils
En fonction des options choisies au niveau de la contrainte référentielle se trouvant dans la
table « fils » :
CONSTRAINT nomContrainte FOREIGN KEY … REFERENCES …
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
plusieurs scénarios sont possibles pour assurer la cohérence de la table « père » vers la table « fils » :
q
Prévenir la modification ou la suppression d’une clé primaire (ou candidate) de la table
« père »
...
Soit vous n’ajoutez pas d’option à la clause
REFERENCES – dans notre exemple, toutes les clés étrangères sont ainsi composées –, soit
vous utilisez NO ACTION pour les directives ON DELETE et ON UPDATE
...
q
Propager la suppression des enregistrements « fils » associés à l’enregistrement « père »
supprimé
...
Dans notre exemple, nous pourrions ainsi décider de supprimer tous les affrètements dès qu’on retire un avion
...
Ce mécanisme est réalisé par la directive ON UPDATE CASCADE
...
q
Propager l’affectation de la valeur nulle aux clés étrangères des enregistrements « fils »
associés à l’enregistrement « père » supprimé ou modifié
...
Dans ces deux cas, il ne faut pas poser de contrainte NOT
NULL sur la clé étrangère
...
Nous ne pourrions pas appliquer ce mécanisme à la table Affreter qui
dispose de contraintes NOT NULL sur ses clés étrangères (car composant la clé primaire)
...
Elle concerne les SGBD compatibles avec les contraintes différées
...
Les options DELETE
CASCADE et DELETE SET NULL sont disponibles depuis la
version 3
...
50, celles relatives à ON UPDATE sont disponibles depuis la version 4
...
8
...
Tableau 2-16 Alternatives de cohérence du « père » vers les « fils »
Alternatives
Syntaxe / Message d’erreur
Prévenir la modification de
l’immatriculation d’un avion ou
la suppression d’un avion
...
--dans Affreter
CONSTRAINT fk_Aff_na_Avion
FOREIGN KEY(immat) REFERENCES Avion(immat)
ON DELETE CASCADE
Propager la modification de
l’immatriculation d’un avion
...
Affecter la valeur
nulle dans la table Pilote
suite à la suppression d’une
compagnie, tout en préservant
l’intégrité avec la table Avion
...
MySQL ne permet pas encore de propager une valeur par défaut (set default) comme la norme
SQL le prévoit
...
Correcte si la clé étrangère est
référencée dans la table « père » ou
est nulle (partiellement ou en
totalité)
...
Correcte si la nouvelle clé étrangère
référence un enregistrement
« père » existant
...
Correcte sans condition
...
Sans objet
...
Sans objet
...
Sans objet
...
Sans objet
...
Un tel mécanisme lit un fichier dans un répertoire du serveur et insère tout ou partie des informations dans une table
...
txt'
[REPLACE | IGNORE] INTO TABLE nomTable
[FIELDS [TERMIATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char' ] ]
[LINES [STARTING BY 'string'] [TERMINATED BY 'string'] ]
[IGNORE number LINES];
q
q
62
REPLACE : option à utiliser pour remplacer systématiquement les anciens enregistrements
par les nouveaux (valeur de clé primaire ou d’index unique)
...
© Éditions Eyrolles
chapitre n° 2
Manipulation des données
q
FIELDS décrit comment sont formatées dans le fichier les valeur à insérer dans la table
...
– FIELDS TERMINATED BY décrit le caractère qui sépare deux valeurs de colonnes
...
q
q
– FIELDS ESCAPED BY permet de contrôler les caractères spéciaux
...
En
l’absence de cette clause, TERMINATED BY vaut '\n' et STARTING BY vaut ''
...
Lisons le fichier « pilotes
...
Notez l’utilisation du double « \ » pour désigner une arborescence Windows
...
Figure 2-12 Importation de données
LOAD DATA INFILE 'D:\\dev\\pilotes
...
00 | AF
|
| PL-1
| Gratien Viel
| 450
...
00 | CAST |
| PL-3
| Richard Grin
| 1000
...
2
...
sql) afin d’insérer les données
dans les tables suivantes :
Tableau 2-18 Données des tables
Table
Segment
INDIP
----------130
...
80
130
...
81
130
...
82
Salle
NSALLE
------s01
s02
s03
s11
s12
s21
s22
s23
NOMSALLE
NBPOSTE INDIP
-------------------- ---------- ----------Salle 1
3 130
...
80
Salle 2
2 130
...
80
Salle 3
2 130
...
80
Salle 11
2 130
...
81
Salle 12
1 130
...
81
Salle 21
2 130
...
82
Salle 22
0 130
...
83
Salle 23
0 130
...
83
Poste
64
Données
NPOSTE
------p1
p2
p3
p4
p5
p6
p7
p8
p9
p10
p11
p12
NOMPOSTE
-------------------Poste 1
Poste 2
Poste 3
Poste 4
Poste 5
Poste 6
Poste 7
Poste 8
Poste 9
Poste 10
Poste 11
Poste 12
NOMSEGMENT
ETAGE
-------------------- ---------Brin RDC
Brin 1er étage
Brin 2e
étage
INDIP
----------130
...
80
130
...
80
130
...
80
130
...
80
130
...
80
130
...
80
130
...
80
130
...
81
130
...
81
130
...
81
130
...
82
130
...
82
AD
--01
02
03
04
05
06
07
01
02
03
01
02
TYPEPOSTE
--------TX
UNIX
TX
PCWS
PCWS
UNIX
TX
UNIX
TX
UNIX
PCNT
PCWS
NSALLE
------s01
s01
s01
s02
s02
s03
s03
s11
s11
s12
s21
s21
© Éditions Eyrolles
chapitre n° 2
Manipulation des données
Tableau 2-18 Données des tables (suite)
Table
Données
Logiciel
NLOG
----log1
log2
log3
log4
log5
log6
log7
log8
Types
TYPELP
--------TX
UNIX
PCNT
PCWS
NC
2
...
2
UNIX
3000
Oracle 8
1999-09-15 8i
UNIX
5600
SQL Server
1998-04-12 7
PCNT
2700
Front Page
1997-06-03 5
PCWS
500
WinDev
1997-05-12 5
PCWS
750
SQL*Net
2
...
I
...
2002-04-12 2
PCNT
810
DreamWeaver
2003-09-21 2
...
3
Modification de données
Écrire le script modification
...
120
...
120
...
120
...
Diminuer de 10 % le prix des logiciels de type 'PCNT'
...
Nous verrons qu’il est
possible de modifier une base de données d’un point de vue structurel (colonnes et index) mais
aussi comportemental (contraintes)
...
Elle
permet aussi d’ajouter et de supprimer des contraintes
...
Renommer une table (RENAME)
L’instruction RENAME renomme une ou plusieurs tables ou vues
...
RENAME [nomBase
...
] nouveauNomTable
[,[nomBase
...
]nouveauNom2]];
Les contraintes d’intégrité, index et prérogatives associés à l’ancienne table sont automatiquement transférés sur la nouvelle
...
Il est aussi possible d’utiliser l’option RENAME TO de l’instruction ALTER TABLE pour
renommer une table existante
...
Cette colonne est initialisée à NULL pour tous les enregistrements (à moins de spécifier
une contrainte DEFAULT, auquel cas tous les enregistrements de la table sont mis à jour avec
une valeur non nulle)
...
Le script suivant ajoute trois colonnes à la table Pilote
...
La deuxième commande ajoute deux colonnes initialisées à une valeur non nulle
...
Web
ALTER TABLE Pilote ADD (nbHVol DECIMAL(7,2));
ALTER TABLE Pilote
ADD (compa VARCHAR(4) DEFAULT 'AF',
ville VARCHAR(30) DEFAULT 'Paris' NOT NULL);
La table est désormais la suivante :
Figure 3-2 Table après l’ajout de colonnes
Pilote
brevet
68
nom
PL-1
Agnès Labat
nbHVol
compa
ville
AF
Paris
© Éditions Eyrolles
chapitre n° 3
Évolution d’un schéma
Renommer des colonnes
Il faut utiliser l’option CHANGE de l’instruction ALTER TABLE pour renommer une colonne
existante
...
Le type (avec
une éventuelle contrainte) doit être reprécisé
...
La syntaxe générale de cette option est la suivante :
ALTER TABLE [nomBase]
...
]
[FIRST|AFTER nomColonne];
L’instruction suivante permet de renommer la colonne ville en adresse en la positionnant
avant la colonne compa :
ALTER TABLE Pilote CHANGE ville adresse VARCHAR(30) AFTER nbHVol;
Modifier le type des colonnes
L’option MODIFY de l’instruction ALTER TABLE modifie le type d’une colonne existante
sans pour autant la renommer
...
nomTable MODIFY [COLUMN] nomColonneAmodifier
typeMySQL [NOT NULL | NULL] [DEFAULT valeur]
[AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]
[COMMENT 'chaine'] [REFERENCES
...
Attention à ne pas réduire les colonnes indexées à une taille inférieure à celle déclarée lors de
la création de l’index
...
Une fois la colonne
changée, les nouvelles contraintes s’appliqueront aux mises à jour ultérieures de la table, et les
données présentes devront toutes vérifier cette nouvelle contrainte
...
INSERT INTO Pilote (brevet, nom)
VALUES ('PL-2', 'Laurent Boutrand');
ALTER TABLE Pilote
MODIFY compa CHAR(4) NOT NULL;
Diminue la colonne et modifie également son type
de VARCHAR en CHAR tout en le déclarant NOT
NULL (possible car les données contenues dans la
colonne ne dépassent pas quatre caractères)
...
La table est désormais la suivante :
Figure 3-3 Après modification des colonnes
CHAR(4)
NULL possible
Défaut : ‘SING’
Pilote
brevet
nom
adresse
compa
PL-1
Agnès Labat
nbHVol
Paris
AF
PL-2
Laurent Boutrand
Paris
SING
Valeurs par défaut
L’option ALTER COLUMN de l’instruction ALTER TABLE modifie la valeur par défaut d’une
colonne existante
...
nomTable ALTER [COLUMN] nomColonneAmodifier
{SET DEFAULT ‘chaine’ | DROP DEFAULT};
Le script suivant définit une valeur par défaut pour la colonne adresse puis supprime celle
relative à la colonne compa :
ALTER TABLE Pilote ALTER COLUMN adresse SET DEFAULT 'Blagnac';
ALTER TABLE Pilote ALTER COLUMN compa DROP DEFAULT;
Supprimer des colonnes
L’option DROP de l’instruction ALTER TABLE permet de supprimer une colonne (aussi un
index ou une clé que nous étudierons plus loin)
...
Lorsqu’une colonne est supprimée, les
index qui l’utilisent sont mis à jour voire éliminés si toutes les colonnes qui le composent sont
effacées
...
nomTable DROP
{ [COLUMN] nomColonne | PRIMARY KEY
| INDEX nomIndex | FOREIGN KEY nomContrainte }
Il n’est pas possible de supprimer avec cette instruction :
• toutes les colonnes d’une table ;
• les colonnes qui sont clés primaires (ou candidates par UNIQUE) référencées par des clés
étrangères
...
Faisons évoluer le schéma suivant
...
Figure 3-4 Schéma à faire évoluer
Compagnie
comp
nrue rue
ville
nomComp
AF
SING
10
7
Paris
Singapour
Air France
Singapore AL
Gambetta
Camparols
Avion
Affreter
compAff
immat
dateAff
nbPax
immat
typeAvion
nbHVol
proprio
AF
SING
AF
F-WTSS
F-GAFU
F-WTSS
2003-05-13
2003-02-05
2003-05-15
85
155
82
F-WTSS
F-GAFU
F-GLFS
Concorde
A320
TB-20
6570
3500
2000
SING
AF
SING
Ajout de contraintes
Jusqu’à présent, nous avons créé les contraintes en même temps que les tables
...
Les outils de
conception (Win’Design, Designer ou PowerAMC) adoptent cette démarche lors de la génération automatique de scripts SQL
...
Il est aussi possible d’ajouter un index
...
nomTable ADD
{ INDEX [nomIndex] [typeIndex] (nomColonne1,
...
)
PRIMARY KEY (colonne1 [,colonne2]
...
)
REFERENCES nomTablePère (col1 [,col2]
...
Un index est
automatiquement généré sur cette colonne à présent :
ALTER TABLE Compagnie ADD CONSTRAINT un_nomC UNIQUE (nomComp);
Clé étrangère
Ajoutons la clé étrangère (indexée) à la table Avion au niveau de la colonne proprio en lui
assignant une contrainte NOT NULL :
ALTER TABLE Avion ADD INDEX (proprio);
ALTER TABLE Avion ADD CONSTRAINT fk_Avion_comp_Compag
FOREIGN KEY(proprio) REFERENCES Compagnie(comp);
ALTER TABLE Avion MODIFY proprio CHAR(4) NOT NULL;
Clé primaire
Ajoutons à la table Affreter, en une seule instruction, sa clé primaire et deux clés étrangères (une vers la table Avion et l’autre vers Compagnie) :
ALTER TABLE Affrete ADD (
CONSTRAINT pk_Affreter
CONSTRAINT fk_Aff_na_Avion
PRIMARY KEY (compAff, immat, dateAff),
FOREIGN KEY(immat) REFERENCES
Avion(immat),
CONSTRAINT fk_Aff_comp_Compag FOREIGN KEY(compAff)
REFERENCES Compagnie(comp));
72
© Éditions Eyrolles
chapitre n° 3
Évolution d’un schéma
Pour que l’ajout ou la modification d’une contrainte soient possibles, il faut que les données
présentes dans la table concernée ou référencée respectent la nouvelle contrainte
...
Il faut donc utiliser une directive différente de l’instruction ALTER
TABLE pour supprimer chaque type de contrainte
...
Dans notre exemple, détruisons la contrainte
NOT NULL de la clé étrangère proprio dans la table Avion
...
Dans notre exemple, effaçons la contrainte portant sur le nom de la
compagnie
...
ALTER TABLE Compagnie DROP INDEX un_nomC;
© Éditions Eyrolles
73
Partie I
SQL de base
Clé étrangère
L’option DROP FOREIGN KEY de l’instruction ALTER TABLE permet de supprimer une clé
étrangère d’une table
...
nomTable DROP FOREIGN KEY nomContrainte;
Le nom de la contrainte est celui qui a été déclaré lors de la création de la table, soit lors de sa
modification (dans CREATE TABLE ou ALTER TABLE)
...
nomTable permet de le découvrir
...
ALTER TABLE Avion DROP FOREIGN KEY fk_Avion_comp_Compag;
Clé primaire
L’option DROP PRIMARY KEY de l’instruction ALTER TABLE permet de supprimer une clé
primaire
...
Ce n’est plus le cas depuis la version 5
...
Si la colonne clé primaire à supprimer contient des clés étrangères, il faut d’abord retirer les
contraintes de clé étrangère
...
Ainsi, pour supprimer la clé primaire de la table Affreter, il faut d’abord enlever les deux
contraintes de clé étrangère concernant des colonnes composant la clé primaire
...
Aucun ordre particulier n’est nécessaire pour supprimer ces trois contraintes, car il n’y a plus
de contrainte référentielle active
...
Il suffit, pour éviter toute incohérence,
de détruire les contraintes dans l’ordre inverse d’apparition dans le script de création
...
Ce mécanisme améliore aussi les performances de programmes batchs qui ne modifient pas des
données concernées par l’intégrité référentielle, ou pour lesquelles on vérifie la cohérence de
la base à la fin
...
Syntaxe
L’instruction SET
FOREIGN_KEY_CHECKS=0 permet de désactiver temporairement
(jusqu’à la réactivation) toutes les contraintes référentielles d’une base
...
Cette option concerne les tables MyISAM et spécifie seulement de ne pas
mettre à jour les index non uniques
...
© Éditions Eyrolles
75
Partie I
SQL de base
Figure 3-7 Avant la désactivation de contraintes
Web
Compagnie
referenced / parent
UNIQUE
comp
nrue rue
ville
nomComp
AF
SING
10
7
Paris
Singapour
Air France
Singapore AL
Gambetta
Camparols
dependent / child
Avion
Affreter dependent / child
compAff
immat
dateAff
nbPax
immat
AF
F-WTSS
2003-05-13
85
F-WTSS
NOT NULL
typeAvion
nbHVol
proprio
Concorde
6570
SING
referenced / parent
Tableau 3-3 Insertions après la désactivation de l’intégrité référentielle
Web
Instructions valides
Instructions non valides
mysql> SET FOREIGN_KEY_CHECKS=0;
mysql> INSERT INTO Avion VALUES
('F-GLFS' , 'TB-22', 500, 'Toto');
Query OK, 1 row affected (0
...
10 sec)
mysql> INSERT INTO Affreter VALUES
('AF', 'Toto', '2005-05-13', 0);
Query OK, 1 row affected (0
...
02 sec)
mysql> INSERT INTO Compagnie VALUES
('GTR', 1, 'Brassens', 'Blagnac', 'Air
France' );
ERROR 1062 (23000): Duplicate entry 'Air
France' for key 2
mysql> INSERT INTO Avion VALUES
('Bidon1', 'TB-20', 2000, NULL);
ERROR 1048 (23000): Column 'proprio'
cannot be null
mysql> INSERT INTO Avion VALUES
('F-GLFS' , 'TB-21', 1000, 'AF');
ERROR 1062 (23000): Duplicate entry 'FGLFS' for key 1
mysql> INSERT INTO Affreter VALUES
('GTI', 'Toto', '2005-11-07',40);
Query OK, 1 row affected (0
...
Toute autre contrainte
(UNIQUE, PRIMARY KEY et NOT NULL) reste active
...
Bien qu’il semble incohérent de réactiver les contraintes sans s’occuper au préalable des
valeurs ne respectant pas l’intégrité référentielle (données notées en gras), nous verrons qu’il
est possible de le faire
...
N’essayez pas de désactiver l’intégrité référentielle avec l’option ENABLE KEYS de l’instruction
ALTER TABLE
...
Syntaxe
La réactivation totale de l’intégrité référentielle de la base se programme ainsi :
mysql> SET FOREIGN_KEY_CHECKS=1;
L’intégrité est assurée de nouveau mais ne concerne que les mises à jour à venir (ajouts
d’enregistrements, modifications de colonnes et suppressions d’enregistrements)
...
En conséquence, il faut programmer des requêtes d’extraction (étudiées au chapitre 4) qui
permettent des recherches d’enregistrements sous critères
...
Ici nous extrayons les avions qui référencent une compagnie inexistante, et
les affrètements qui référencent une compagnie inexistante ou un avion inexistant
...
Il apparaît que quatre enregistrements ne respectent pas des contraintes
...
Dans notre exemple, choisissons :
q
D’affecter la compagnie 'AF' aux avions appartenant à des compagnies non référencées
dans la table Avion
...
SET FOREIGN_KEY_CHECKS=0;
UPDATE Avion SET proprio = 'AF '
WHERE proprio NOT IN (SELECT comp FROM Compagnie) ;
q
De modifier la compagnie 'GTI' par la compagnie 'SING' dans la table Affreter et toute
immatriculation d’avion inexistant en 'F-GLFS'
...
L’état de la base avec les
contraintes réactivées est le suivant (les mises à jour sont en gras) :
78
© Éditions Eyrolles
chapitre n° 3
Évolution d’un schéma
Figure 3-9 Tables après modifications et réactivation des contraintes
Compagnie
referenced / parent
comp
nrue rue
ville
nomComp
AF
SING
10
7
Paris
Singapour
Air France
Singapore AL
Gambetta
Camparols
Avion
dependent / child
NOT NULL
immat
typeAvion
nbHVol
proprio
F-WTSS
F-GLFS
Concorde
TB-22
6570
500
SING
AF
Affreter dependent / child
compAff immat
dateAff
nbPax
AF
AF
SING
SING
2003-05-13
2005-05-13
2005-11-07
2005-11-07
85
0
10
40
F-WTSS
F-GLFS
F-WTSS
F-GLFS
Contraintes différées
Les contraintes que nous avons étudiées jusqu’à maintenant sont des contraintes immédiates
(immediate) qui sont contrôlées après chaque instruction
...
Pour l’heure, MySQL avec InnoDB ne propose pas ce mode
de programmation
...
3
...
sql qui contient les instructions nécessaires pour ajouter les colonnes
suivantes (avec ALTER TABLE)
...
Tableau 3-5 Données de la table Installer
Table
Nom, type et signification des nouvelles colonnes
Segment
nbSalle TINYINT(2) : nombre de salles par défaut = 0
...
Logiciel
nbInstall TINYINT(2) : nombre d’installations par défaut = 0
...
Vérifier la structure et le contenu de chaque table avec DESCRIBE et SELECT
...
2
Modification de colonnes
Dans ce même script, rajouter les instructions nécessaires pour :
•
augmenter la taille dans la table Salle de la colonne nomSalle (passer à VARCHAR(30)) ;
•
diminuer la taille dans la table Segment de la colonne nomSegment à VARCHAR(15) ;
•
tenter de diminuer la taille dans la table Segment de la colonne nomSegment à VARCHAR(14)
...
3
...
Ajouter les contraintes de clés étrangères pour assurer l’intégrité référentielle (avec ALTER TABLE…
ADD CONSTRAINT…) entre les tables suivantes
...
Si l’ajout d’une contrainte référentielle renvoie une erreur, vérifier les enregistrements des tables
« pères » et « fils » (notamment au niveau de la casse des chaînes de caractères, 'Tx' est différent de
'TX' par exemple)
...
sql) en fonction des nouvelles contraintes
...
3
...
Figure 3-11 Contraintes référentielles à créer
Segment
indIP
nomSegment
Salle
nSalle
Poste
nPoste
nomSalle
nomPoste
Logiciel
nLog
Installer
nPoste
Types
typeLP
© Éditions Eyrolles
etage
nbPoste indIP
indIP
nomLog
nLog
nbSalle nbPoste
ad
typePoste
nSalle
dateAch version typeLog prix
numIns
dateIns
nbLog
nbInstall
delai
nomType
81
Partie I
SQL de base
La mise en place de ces contraintes doit renvoyer une erreur car :
•
Il existe des salles ('s22' et 's23') ayant un numéro de segment inexistant dans la table Segment
...
Extraire les enregistrements qui posent problème (numéro des salles pour le premier cas, numéro de
logiciel pour le second)
...
Ajouter le type de logiciel ('BeOS', 'Système Be') dans la table Types
...
Vérifier que les instructions ne
renvoient plus d’erreur et que les deux requêtes d’extraction ne renvoient aucune donnée
...
Une requête permet de rechercher
des données dans une ou plusieurs tables ou vues, à partir de critères simples ou complexes
...
Généralités
L’instruction SELECT est une commande déclarative (elle décrit ce que l’on cherche sans expliquer le moyen d’opérer)
...
La figure suivante schématise les principales fonctionnalités de l’instruction SELECT
...
Figure 4-1 Possibilités de l’instruction SELECT
Pilote
Avion
Projection (SELECT )
Restriction (WHERE )
Compagnie
Air France
Jointure2
© Éditions Eyrolles
Jointure1 (WHERE )
83
Partie I
SQL de base
La restriction qui est programmée dans le WHERE de la requête permet de restreindre la
recherche à une ou plusieurs lignes
...
La projection qui est programmée dans le SELECT de la requête permet d’extraire une ou
q
plusieurs colonnes
...
La jointure qui est programmée dans le WHERE de la requête permet d’extraire des données
q
de différentes tables en les reliant deux à deux (le plus souvent à partir de contraintes référentielles)
...
La deuxième jointure répond à la question : « Quels sont les avions de la
compagnie de nom Air France ? »
...
Les questions trop complexes peuvent être programmées à l’aide des vues (chapitre 5) ou par traitement (programmes mélangeant requêtes et
instructions procédurales)
...
La syntaxe SQL simplifiée de l’instruction SELECT est la suivante :
SELECT [ { DISTINCT | DISTINCTROW } | ALL ] listeColonnes
FROM nomTable1 [,nomTable2]
...
Pseudotable
La pseudotable est une table qui n’a pas de nom et qui est utile pour évaluer une expression de
la manière suivante : « SELECT expression; »
...
84
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Tableau 4-1 Extraction d’expressions
Besoin
Requête et résultat
Aucun, utilisation probablement la plus superflue
...
14159265359/180),2) "Environ"
tat de 214, le carré du cosi- ,EXP(1);
nus de 3π sur 2 et e1
...
50000000000015 | 2
...
q
ALL prend en compte les duplicatas (option par défaut)
...
}
– * : extrait toutes les colonnes de la table
...
– alias : renomme l’expression (nom valable pendant la durée de la requête)
...
85
Partie I
SQL de base
clauseOrdonnancement : tri sur une ou plusieurs colonnes ou expressions
...
Interrogeons la table suivante en utilisant chaque option:
q
Figure 4-2 Table Pilote
Pilote
brevet
nom
PL-1
PL-2
PL-3
PL-4
PL-5
VARCHAR(6)
nbHVol
Gratien Viel
Didier Donsez
Richard Grin
Placide Fresnais
Daniel Vielle
VARCHAR(16)
450
0
1000
2450
compa
AF
AF
SING
CAST
AF
DECIMAL(7,2) CHAR(4)
Extraction de toutes les colonnes
L’extraction de toutes les colonnes d’une table requiert l’utilisation du symbole « * »
...
00 | AF
|
| PL-2
| Didier Donsez
|
0
...
00 | SING |
| PL-4
| Placide Fresnais | 2450
...
Tableau 4-3 Liste de colonnes
Web
Requête SQL
SELECT compa, brevet FROM Pilote;
86
Résultat
+-------+--------+
| compa | brevet |
+-------+--------+
| AF
| PL-1
|
| AF
| PL-2
|
| SING | PL-3
|
| CAST | PL-4
|
| AF
| PL-5
|
+-------+--------+
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Alias
Les alias permettent de renommer des colonnes à l’affichage ou des tables dans la requête
...
L’utilisation de la directive AS est facultative (pour se rendre conforme à SQL2)
...
Tableau 4-4 Alias (colonnes et tables)
Alias de colonnes
Web
Alias de table
SELECT compa AS c1,
SELECT aliasPilotes
...
nom
FROM Pilote;
FROM Pilote aliasPilotes;
+------+------------------+------+
| c1
| NometPrenom
| c3
|
+------+------------------+------+
| AF
| Gratien Viel
| PL-1 |
| AF
| Didier Donsez
| PL-2 |
| SING | Richard Grin
| PL-3 |
| CAST | Placide Fresnais | PL-4 |
| AF
| Daniel Vielle
| PL-5 |
+------+------------------+------+
+------+------------------+
| c1
| nom
|
+------+------------------+
| AF
| Gratien Viel
|
| AF
| Didier Donsez
|
| SING | Richard Grin
|
| CAST | Placide Fresnais |
| AF
| Daniel Vielle
|
+------+------------------+
Il semble préférable d’utiliser la directive AS afin qu’il n’y ait pas d’ambiguïté dans l’expression
(oubli d’une virgule) SELECT col1 col2 FROM nomTable où MySQL interprétera la seconde
colonne comme un alias de la première
...
Pour la
deuxième requête, les écritures « DISTINCT compa », « DISTINCTROW(compa) » et
« DISTINCTROW compa » sont équivalentes
...
© Éditions Eyrolles
87
Partie I
SQL de base
Tableau 4-5 Gestion des duplicatas
Avec duplicata
Sans duplicata
SELECT compa FROM Pilote;
SELECT DISTINCT(compa) FROM Pilote;
+-------+
| compa |
+-------+
| AF
|
| AF
|
| SING |
| CAST |
| AF
|
+-------+
Web
+-------+
| compa |
+-------+
| AF
|
| SING |
| CAST |
+-------+
Expressions et valeurs nulles
Il est possible d’évaluer et d’afficher simultanément des expressions dans la clause SELECT
(types numériques, DATE et DATETIME)
...
Le résultat d’une expression comportant une valeur NULL est évalué à NULL
...
Dans l’exemple
suivant, l’expression 10*nbHVol+5/2 est calculée en multipliant par 10 le nombre d’heures
de vol, puis en ajoutant le résulat de 5 divisé par 2
...
Tableau 4-6 Expressions numériques
Web
Requête
SELECT brevet, nbHVol,
nbHVol*nbHVol AS auCarre,
10*nbHVol+5/2
FROM Pilote;
SELECT SYSDATE()+0 ;
88
Résultat
+--------+---------+--------------+---------------+
| brevet | nbHVol | auCarre
| 10*nbHVol+5/2 |
+--------+---------+--------------+---------------+
| PL-1
| 450
...
0000 |
4502
...
00 |
0
...
5000 |
| PL-3
| 1000
...
0000 |
10002
...
00 | 6002500
...
5000 |
| PL-5
|
NULL |
NULL |
NULL |
+--------+---------+--------------+---------------+
+----------------+
| SYSDATE()+0
|
+----------------+
| 20051107145522 |
+----------------+
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Ordonnancement
Pour trier le résultat d’une requête, il faut spécifier la clause d’ordonnancement par ORDER
BY de la manière suivante :
ORDER BY
{ expression1 | position1 | alias1 } [ASC | DESC]
[,{expr2 | position2 | alias2} [ASC | DESC]
q
expression : nom de colonne, fonction SQL, constante, calcul
...
q
ASC ou DESC : tri ascendant ou descendant (par défaut ASC)
...
Tableau 4-7 Ordonnancement
Options par défaut
Ordre décroissant (et NULL)
mysql> SELECT brevet, nom
FROM Pilote ORDER BY nom;
mysql> SELECT brevet,nbHVol
FROM Pilote ORDER BY nbHvol DESC;
+--------+------------------+
| brevet | nom
|
+--------+------------------+
| PL-5
| Daniel Vielle
|
| PL-2
| Didier Donsez
|
| PL-1
| Gratien Viel
|
| PL-4
| Placide Fresnais |
| PL-3
| Richard Grin
|
+--------+------------------+
Web
+--------+---------+
| brevet | nbHVol |
+--------+---------+
| PL-4
| 2450
...
00 |
| PL-1
| 450
...
00 |
| PL-5
|
NULL |
+--------+---------+
Concaténation
L’opérateur de concaténation se programme à l’aide de la fonction CONCAT qui admet deux
chaînes de caractères en paramètre
...
La colonne résultante est considérée comme une chaîne de caractères
...
La concaténation concerne deux colonnes et la constante "vole pour"
...
Dans
l’exemple suivant, il s’agit d’insérer tous les pilotes de la table Pilote (en considérant le
nom, le nombre d’heures de vol et la compagnie) dans la table NomsetHVoldesPilotes :
Tableau 4-9 Insertion multiligne
Web
Création et insertion
Requête et résultat
CREATE TABLE
NomsetHVoldesPilotes
(nom VARCHAR(16),
nbHVol DECIMAL(7,2),
compa CHAR(4));
mysql> SELECT * FROM NomsetHVoldesPilotes;
+------------------+---------+-------+
| nom
| nbHVol | compa |
+------------------+---------+-------+
| Gratien Viel
| 450
...
00 | AF
|
| Richard Grin
| 1000
...
00 | CAST |
| Daniel Vielle
|
NULL | AF
|
+------------------+---------+-------+
INSERT INTO NomsetHVoldesPilotes
SELECT nom,nbHVol,compa
FROM Pilote;
Notez que les instructions (CREATE TABLE et INSERT
...
Le second entier indique le nombre maximum de lignes à extraire
...
Ainsi « LIMIT n » équivaut à « LIMIT 0,n »
...
+--------+---------------+---------+-------+
| brevet | nom
| nbHVol | compa |
+--------+---------------+---------+-------+
| PL-2
| Didier Donsez |
0
...
00 | SING |
+--------+---------------+---------+-------+
SELECT * FROM Pilote LIMIT 1,2;
Les deux pilotes les plus expérimentés
(par ordre du nombre d’heures de vol)
...
00 | CAST |
| PL-3
| Richard Grin
| 1000
...
Cette clause limite la recherche aux enregistrements qui respectent une condition
simple ou complexe
...
Interrogeons la table suivante en utilisant chaque catégorie d’opérateur :
© Éditions Eyrolles
91
Partie I
SQL de base
Figure 4-3 Table Pilote
Pilote
brevet
Web
PL-1
PL-2
PL-3
PL-4
PL-5
PL-6
nom
Gratien Viel
Didier Donsez
Richard Grin
Placide Fresnais
Daniel Vielle
Francoise Tort
nbHVol prime
450
500
0
1000
90
2450
500
400
600
0
compa
AF
AF
SING
CAST
SING
CAST
Opérateurs de comparaison
Le tableau suivant décrit des requêtes pour lesquelles la clause WHERE contient des opérateurs
de comparaison
...
Les écritures
« prime<>500 » et « NOT (prime=500) » sont équivalentes
...
Notez l’utilisation du simple guillemet pour comparer des chaînes de caractères
...
• Les opérateurs de comparaison (>, =, <, >=, <=, <>) sont prioritaires par rapport à NOT
...
La première requête de l’exemple suivant contient une condition composée de trois prédicats
qui sont évalués par ordre de priorité (d’abord AND puis OR)
...
La deuxième requête force la priorité avec les parenthèses (AND et OR sur le même pied
d’égalité)
...
Tableau 4-12 Opérateurs logiques
Requête
Résultat sous SQL*Plus
SELECT brevet, nom, compa
FROM Pilote WHERE
( compa = 'SING' OR
compa = 'AF' AND nbHVol < 500) ;
+--------+---------------+-------+
| brevet | nom
| compa |
+--------+---------------+-------+
| PL-1
| Gratien Viel | AF
|
| PL-2
| Didier Donsez | AF
|
| PL-3
| Richard Grin | SING |
| PL-5
| Daniel Vielle | SING |
+--------+---------------+-------+
SELECT brevet, nom, compa
FROM Pilote WHERE
(( compa = 'SING' OR compa = 'AF' )
AND nbHVol < 500);
Web
+--------+---------------+-------+
| brevet | nom
| compa |
+--------+---------------+-------+
| PL-1
| Gratien Viel | AF
|
| PL-2
| Didier Donsez | AF
|
| PL-5
| Daniel Vielle | SING |
+--------+---------------+-------+
Opérateurs intégrés
Les opérateurs intégrés sont BETWEEN, IN, LIKE et IS NULL
...
SELECT brevet, nom, nbHVol FROM Pilote
WHERE nbHVol BETWEEN 399 AND 1000 ;
+--------+---------------+---------+
| brevet | nom
| nbHVol |
+--------+---------------+---------+
| PL-1
| Gratien Viel | 450
...
00 |
| PL-5
| Daniel Vielle | 400
...
WHERE compa IN ('CAST', 'SING') ;
+--------+------------------+-------+
| brevet | nom
| compa |
+--------+------------------+-------+
| PL-3
| Richard Grin
| SING |
| PL-4
| Placide Fresnais | CAST |
| PL-5
| Daniel Vielle
| SING |
| PL-6
| Francoise Tort
| CAST |
+--------+------------------+-------+
LIKE (expression) compare de manière
générique des chaînes de caractères à une
expression
...
Le symbole _ remplace un caractère
...
Utilisez de préférence des colonnes
VARCHAR ou complétez si nécessaire par des
blancs jusqu’à la taille maximale pour des
CHAR
...
La négation s’écrit soit « expression IS NOT
NULL » soit « NOT (expression IS NULL) »
...
00 |
| Francoise Tort |
0 |
NULL |
+----------------+-------+--------+
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Alias
Il n’est pas permis d’utiliser un alias de colonne dans la clause WHERE
...
Ainsi, la requête suivante renvoie une erreur alors qu’elle ne contient pourtant pas d’expression litigieuse
...
compa »
...
compa AS c1, aliasDesPilotes
...
La syntaxe générale d’une fonction est la suivante :
nomFonction(colonne1 | expression1 [,colonne2 | expression2 …])
• Une fonction monoligne agit sur une ligne à la fois et ramène un résultat par ligne
...
Ces fonctions peuvent se combiner entre elles (exemple :
MAX(COS(ABS(n))) désigne le maximum des cosinus de la valeur absolue de la colonne n)
...
Caractères
Interrogeons la table suivante en utilisant des fonctions pour les caractères :
Figure 4-4 Table Pilote
Pilote
brevet
PL-1
PL-2
PL-3
PL-4
PL-5
PL-6
© Éditions Eyrolles
prenom
Gratien
Didier
richard
placide
Daniel
Francoise
nom
viel
donsez
Grin
Fresnais
vielle
tort
surnom
dba
smith
Faucon
cool
jones
NormaleSup
compa
AF
AF
SING
CAST
SING
CAST
95
Partie I
SQL de base
La plupart des fonctions pour les caractères acceptent une chaîne de caractères en paramètre
de nature CHAR ou VARCHAR
...
CHAR(n)
Retourne le carac- CHR (161) || CHR (162) donne íó
tère équivalent
dans le jeu de
caractères en
cours
...
SELECT CONCAT(
CONCAT(nom,' vole pour '), compa)
"Personnel" FROM Pilote;
+------------------------------+
| Personnel
|
+------------------------------+
| viel travaille pour AF
|
|
...
0 si
aucune égalité
n’est trouvée
...
INSTR(c1,c2)
96
Premier indice
d’une sous-chaîne
c1 dans une
chaîne c2
...
Exemple
SELECT INSERT('Compxxxie : Airbus ',5,
"Qui?";
3, 'agn')
+---------------------+
| Qui?
|
+---------------------+
| Compagnie : Airbus |
+---------------------+
SELECT INSTR('Infos-Air : AirBus pour
Air-France','Air') "Indice";
+--------+
| Indice |
+--------+
|
7 |
+--------+
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Tableau 4-14 Fonctions pour les caractères (suite)
Fonction
Exemple
LOWER(c)
Tout en minuscules
...
Exemple : indice
de 'Air' dans la
chaîne à partir du
9e caractère
...
SELECT LENGTH('Infos-Air : AirBus pour
Air-France') "Taille";
+-------+
| Taille |
+--------+
|
35 |
+--------+
LEFT(c,n)
Extrait les n premiers caractères à
c en partant de la
gauche
...
-') "sur 20";
de c2 dans c1 sur +----------------------+
n caractères
...
--Rien |
+----------------------+
REPLACE(c1,c2,c3)
© Éditions Eyrolles
Objectif
Recherche les c2 SELECT
présentes dans c1
REPLACE('Matra et Aerospatiale',
et les remplace
'Matra','EADS') "Changement";
par c3
...
"Miroir";
+----------------+
| Miroir
|
+----------------+
| A380 à Blagnac |
+----------------+
RIGHT(c,n)
Extrait les n derniers caractères à
c en partant de la
droite
...
SELECT RPAD('Rien',19,'-
...
- |
+---------------------+
SOUNDEX(c)
Extrait la phonéti- SELECT nom, surnom, compa FROM Pilote
que d’une expresWHERE SOUNDEX(surnom) IN
sion (in english
( SOUNDEX('SMYTHE') , SOUNDEX('John') );
only !)
...
SELECT
SUBSTR('Air France à Blagnac Con!',12,9)
"Où ça?";
+-----------+
| Où ça?
|
+-----------+
| à Blagnac |
+-----------+
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Tableau 4-14 Fonctions pour les caractères (suite)
Fonction
Objectif
Exemple
TRIM(c1 FROM c2)
Enlève les caractères c1 à la
chaîne c2 (options
LEADING et
TRAILING pour
préciser le sens
du découpage)
...
SELECT
TRIM('B' FROM 'BA380 à BlagnacBBBBB')
"Bye les Jumbo";
Tout en majuscules
...
Tableau 4-15 Fonctions numériques
Fonction
ABS(n)
Valeur absolue de n
...
ATAN(n)
Arc tangente (∀ n), retour exprimé en
radians ( de -pi/2 à pi/2)
...
CEIL(15
...
COS(n)
Cosinus de n exprimé en radians de 0 à 2
pi
...
5
...
COT(30*PI()/180) retourne
1
...
DEGREES(n)
© Éditions Eyrolles
Objectif
Exemple
Conversion de radians en degrés
...
99
Partie I
SQL de base
Tableau 4-15 Fonctions numériques (suite)
Fonction
Objectif
Exemple
EXP(n)
e (2
...
FLOOR(n)
Plus grand entier ≤ à n
...
LOG(n)(m,n)
Logarithme de n dans une base m
...
POW(m,n)
m puissance n
...
RADIANS(90) retourne
1
...
RAND()
Flottant aléatoire (à 14 décimales) entre 0
et 1
...
567,2) retourne 17,57
...
ROUND(17
...
SIGN(n)
Retourne le signe d’un nombre (-1, 0 ou 1)
...
SINH(n)
Sinus hyperbolique de n
...
TAN(n)
Tangente de n exprimée en radians de 0
à 2 pi
...
7) retourne 15
...
SIN(30*PI()/180) retourne 0
...
TRUNC(15
...
7
...
On peut en utiliser certains
en passant des paramètres en base 10, en binaire ou de type chaîne de caractères
...
b'0100' | b'1100' retourne 12
...
b'0100' & b'1100' retourne 4
...
b'0100' ^ b'1100' retourne 8
...
3 << 2 retourne 12
...
b'0100' >> 2 retourne 1
...
3+(~3+1) retourne 1 (ici on programme le complément à 2)
...
BIN(12) retourne '1100'
...
BIT_LENGTH('GTR') retourne 24
(3 octets)
...
HEX(254) retourne 'FE'
...
OCT(12)
OCTET_LENGTH(c)
Synonyme de LENGTH()
...
retourne 14
...
Dates
Le tableau suivant décrit les principales fonctions pour les dates :
Tableau 4-17 Fonctions pour les dates
Fonction
Retour
Ajoute n jours à une date (heure)
...
TIME ou
DATETIME
CURDATE(), CURRENT_DATE ou
CURRENT_DATE()
Date courante ('YYYY-MM-DD' ou YYYYMMDD)
...
INT ou DATE
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP()ou NOW()
Date et heure courantes ('YYYY-MM-DD
HH:MM:SS' ou YYYYMMDDHHMMS)
...
DATE
DATEDIFF(date1,date2)
Nombre entier de jours entre les 2 dates
...
expr désigne un intervalle
...
DATE ou
DATETIME
DATE_FORMAT(date,format)
Présente la date selon un format (voir
tableau suivant)
...
DATE ou
DATETIME
DAYNAME(date)
Nom du jour en anglais
...
INT
DAYOFYEAR(date)
© Éditions Eyrolles
Objectif
ADDDATE(date,n)
Numéro du jour dans l’année (0 à 366)
...
INT
FROM_DAYS(n)
Retourne une date à partir d’un nombre de
jours (le calendrier année 0 débute à
n=365)
...
Utilisation possible d’un format
...
INT
LAST_DAY(date)
Dernier jour du mois d’une date (heure)
...
MAKEDATE(annee,njour)
Construit une date à partir d’une année et
d’un nombre de jours (>0, si njour>365,
l’année s’incrémente automatiquement)
...
TIME
MICROSECOND(date)
Extrait les microsecondes d’une dateheure
...
INT
MONTH(date), MONTHNAME(date)
Retourne respectivement le numéro et le
nom du mois d’une date-heure
...
ou INT
PERIOD_DIFF(int1,int2)
Nombre de mois séparant les deux dates
au format YYMM or YYYYMM
...
INT
SEC_TO_TIME(secondes)
Construit une heure au format 'HH:MM:SS'
ou HHMMSS
...
C’est l’inverse de DATE_FORMAT()
...
DATE ou
DATETIME
SUBTIME(date1,date2)
Retranche date2 (TIME) à date1 (TIME ou
DATETIME)
...
DATETIME
ou INT
TIME(datetime)
102
Objectif
Extrait le temps d’une date-heure
...
TIME
TIMESTAMP(date)
Construit une estampille à partir d’une date
(heure)
...
TIMESTAMP
TIMESTAMPDIF(intervalle,int,date)
Retranche à la date (heure) un intervalle
du type (idem précédent)
...
INT
TO_DAYS(date)
Retourne un nombre de jours à partir d’une
date ('YYYY-MM-DD' ou YYYYMMDD)
...
INT
UNIX_TIMESTAMP(date)
Retourne le nombre de secondes depuis le
1/1/1970 jusqu’à la date (heure) passée en
paramètre (ou entier au format YYMMDD
YYYYMMDD)
...
INT
UTC_DATE(), UTC_TIME(), UTC_TIMESTAMP()
Retournent respectivement la date, l’heure
et l’estampille au méridien de Greenwich
...
6 :
dimanche) d’une date (heure)
...
INT
103
Partie I
SQL de base
Tableau 4-18 Paramètres d’intervalles pour les fonctions DATE_ADD et DATE_SUB
Paramètre type
Paramètre expr
MICROSECOND
SECOND
MINUTE
HOUR
DAY
WEEK
MONTH
YEAR
SECOND_MICROSECOND
MINUTE_MICROSECOND
MINUTE_SECOND
HOUR_MICROSECOND
HOUR_SECOND
HOUR_MINUTE
DAY_MICROSECOND
DAY_SECOND
DAY_MINUTE
DAY_HOUR
YEAR_MONTH
n
n
n
nn
nn
n
nn
nnnn
'ss
...
microsec'
'mi:ssS'
'hh
...
microsec'
'dd hh:mi:ss'
'dd hh:mi'
'dd hh'
'yyyy-mm'
Tableau 4-19 Principaux formats pour les fonctions DATE_FORMAT et STR_TO_DATE
Format
%a
Nom du jour en anglais abrévié (Sun
...
Dec)
%c
Mois (0
...
31)
%f
Microsecondes (000000
...
23)
%i
Minutes (00
...
366)
%M
Nom du mois en anglais (January
...
59)
%T
Time sur 24 heures (hh:mm:ss)
%u
Numéro de semaine (00
...
Saturday)
%w
Jour de la semaine (0=Sunday
...
SELECT ADDDATE('2005-11-9', 31) ;
+--------------------------+
| ADDDATE('2005-11-9', 31) |
+--------------------------+
| 2005-12-10
|
+--------------------------+
1 jour et 1 microseconde après le 9/11/2005,
11 heures, 1 microseconde
...
999999','1 0:0:0
...
000000 |
+----------------------------+
Rendez-vous dans 4 mois
...
SELECT DATE_ADD(CURRENT_TIMESTAMP,
INTERVAL '7 01:30:00' DAY_SECOND) "RDV
1sem 1h30";
+---------------------+
| RDV 1sem 1h30
|
+---------------------+
| 2005-11-16 18:53:03 |
+---------------------+
Aujourd’hui en anglais
...
SELECT EXTRACT(DAY_MINUTE FROM '2005-11-09
01:02:03') "DAY_MINUTE";
Web
+------------+
| DAY_MINUTE |
+------------+
|
90102 |
+------------+
Conversions
MySQL autorise des conversions de types implicites ou explicites
...
), une donnée de type numérique (ou date-heure) à une donnée de type VARCHAR
(ou CHAR)
...
On parle ainsi de conversions implicites
...
45', '20060116', 3, 5);
Explicites
Une conversion est dite « explicite » quand on utilise une fonction à cet effet
...
Les fonctions de conversion sont décrites dans le tableau suivant :
Tableau 4-21 Fonctions de conversion
Fonction
Conversion
Exemple
BINARY(expr)
L’expression en bits
...
CAST(expression
AS typeMySQL )
L’expression dans le type en paramètre (BINARY, CHAR, DATE,
DATETIME, DECIMAL, SIGNED,
TIME, UNSIGNED)
...
CONVERT(c, jeucar)
La chaîne c dans le jeu de caractères passé en paramètre
...
Comparaisons
MySQL compare deux variables entre elles en suivant les règles suivantes :
• Si l’une des deux valeurs est NULL, la comparaison retourne NULL (sauf pour l’opérateur
<=> qui renvoie vrai si les deux valeurs sont NULL)
...
• Si les deux valeurs sont des numériques, elles sont comparées en tant que telles
...
• Si l’une des valeurs est TIMESTAMP ou DATETIME et si l’autre est une constante, cette dernière est convertie en TIMESTAMP
...
106
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Énumérations
Nous avons vu au chapitre 2 comment manipuler les deux types d’énumérations que MySQL
propose (ENUM et SET)
...
Type ENUM
Chaque valeur de l’énumération est associée à un indice commençant à 1
...
Tableau 4-22 Exemples d’extraction d’indices d’une énumération ENUM
Table et données
Web
Extraction
Figure 4-5 Table et données colonne ENUM
UnCursus
num
nom
{diplome }
E1
E2
F
...
Degrelle
BTS
Licence
ENUM
mysql> SELECT nom, diplome, diplome+0
FROM UnCursus ;
+-------------+---------+-----------+
| nom
| diplome | diplome+0 |
+-------------+---------+-----------+
| F
...
Degrelle | Licence |
3 |
+-------------+---------+-----------+
BTS, DUT, Licence INSA
L’indice d’une valeur vide (colonne valuée à ('') ou '' dans l’INSERT) est 0, celui d’une
valeur NULL est NULL
...
L’exemple suivant (décrit
au chapitre 2) illustre deux possibilités d’extraction
...
Brouard
F
...
Peyrard
BTS, Licence
Licence, INSA , DUT
INSA, DUT
SET
BTS, DUT, Licence INSA
SELECT nom, diplomes FROM Cursus
WHERE
FIND_IN_SET('Licence',diplomes)>0 ;
+-------------+------------------+
| nom
| diplomes
|
+-------------+------------------+
| F
...
Degrelle | DUT,Licence,INSA |
+-------------+------------------+
SELECT nom, diplomes FROM Cursus
WHERE diplomes = 'BTS,Licence' ;
+------------+-------------+
| nom
| diplomes
|
+------------+-------------+
| F
...
Cela n’est cependant pas
recommandé, car le mot 'Licence' peut être présent dans l’ensemble non pas en tant qu’élément, mais en tant que sous-chaîne d’un élément
...
FORMAT(numerique,nb)
Formate un nombre arrondi à
nb décimales de la manière
suivante :'#,###,###
...
8901, 1) retourne
'1,234,567
...
GREATEST(expression[, expression]
...
GREATEST('Raffarin','Chirac','
X-Men') retourne 'X-Men'
...
)
Retourne la plus petite des
expressions
...
NULLIF(expr1,expr2)
Si expr1 = expr2 retourne
NULL, sinon retourne expr1
...
IFNULL(expr1,expr2)
Convertit expr1 susceptible
d’être nul en une valeur réelle
(expr2)
...
Regroupements
Cette section traite à la fois des regroupements de lignes (agrégats) et des fonctions de groupe
(ou multilignes)
...
q
clauseRegroupement : GROUP BY (expression1[,expression2]
...
q
q
HAVING condition : pour inclure ou exclure des lignes aux groupes (la condition ne
peut faire intervenir que des expressions du GROUP BY)
...
Interrogeons la table suivante en composant des regroupements et en appliquant des fonctions
de groupe :
Figure 4-7 Table Pilote
Pilote
Web
© Éditions Eyrolles
brevet
nom
nbHVol prime
embauche
typeAvion
compa
PL-1
PL-2
PL-3
PL-4
PL-5
PL-6
Gratien Viel
Didier Donsez
Richard Grin
Placide Fresnais
Daniel Vielle
Francoise Tort
450
0
1000
2450
400
1965 -02-05
1995 -05-13
2001 -09-11
2001 -09-21
1965 -01-16
2000 -12-24
A320
A320
A320
A330
A340
A340
AF
AF
SING
SING
AF
CAST
500
500
600
0
109
Partie I
SQL de base
Fonctions de groupe
Nous étudions dans cette section les fonctions usuelles
...
Le tableau suivant présente les principales fonctions
...
À l’exception de COUNT, toutes les fonctions ignorent les
valeurs NULL (il faudra utiliser IFNULL pour contrer cet effet)
...
COUNT({* | [DISTINCT ] expr})
Nombre de lignes (* toutes les lignes, expr pour les
colonnes non nulles)
...
MAX([DISTINCT] expr)
Maximum de expr (nombre, date, chaîne)
...
STDDEV(expr)
Écart type de expr (nombre)
...
VARIANCE(expr)
Variance de expr (nombre)
...
SELECT AVG(nbHVol) , AVG(prime) FROM Pilote WHERE compa = 'AF';
+-------------+------------+
| AVG(nbHVol) | AVG(prime) |
+-------------+------------+
| 283
...
0000 |
+-------------+------------+
COUNT
Web
Nombre de pilotes, d’heures de vol et de primes (toutes et distinctes) recensées dans la
table
...
SELECT compa, GROUP_CONCAT(nom) FROM Pilote GROUP BY compa;
+-------+------------------------------------------+
| compa | GROUP_CONCAT(nom)
|
+-------+------------------------------------------+
| AF
| Gratien Viel,Didier Donsez,Daniel Vielle |
| CAST | Francoise Tort
|
| SING | Richard Grin,Placide Fresnais
|
+-------+------------------------------------------+
MAX –
MIN
Nombre d’heures de vol le plus élevé, date d’embauche la plus récente
...
SELECT MAX(nbHVol), MAX(embauche) "Date+", MIN(prime) ,
MIN(embauche) "Date-" FROM Pilote;
+-------------+------------+------------+------------+
| MAX(nbHVol) | Date+
| MIN(prime) | Date|
+-------------+------------+------------+------------+
|
2450
...
VARIANCE SELECT STDDEV(prime) , SUM(nbHVol) , VARIANCE(prime) FROM Pilote
WHERE compa = 'AF';
+---------------+-------------+-----------------+
| STDDEV(prime) | SUM(nbHVol) | VARIANCE(prime) |
+---------------+-------------+-----------------+
|
50
...
00 |
2500
...
Étude du GROUP
BY et HAVING
Le groupement de lignes dans une requête se programme au niveau surligné de l’instruction
SQL suivante :
SELECT col1[, col2…], fonction1Groupe(…)[,fonction2Groupe(…)…]
FROM nomTable [ WHERE condition ]
GROUP BY {col1 | expr1 | position1} [,{col2
...
}] ];
© Éditions Eyrolles
111
Partie I
SQL de base
q
La clause WHERE de la requête permet d’exclure des lignes pour chaque groupement, ou de
rejeter des groupements entiers
...
q
La clause GROUP BY liste les colonnes du groupement
...
q
La clause ORDER BY permet de trier le résultat (déjà étudiée)
...
Seules des
fonctions ou expressions peuvent exister en plus dans le SELECT
...
Dans l’exemple suivant, en groupant sur la colonne compa, trois ensembles de lignes (groupements) sont composés
...
Figure 4-8 Groupement sur la colonne compa
Pilote
brevet
nom
nbHVol prime
embauche
typeAvion
compa
PL-1
Gratien Viel
450
1965 -02-05
A320
AF
PL-2
Didier Donsez
0
1995 -05-13
A320
AF
PL-5
Daniel Vielle
400
600
1965 -01-16
A340
AF
PL-6
Francoise Tort
0
2000-12-24
A340
CAST
PL-3
Richard Grin
1000
2001 -09-11
A320
SING
PL-4
Placide Fresnais
2450
2001-09-21
A330
SING
500
500
Il est aussi possible de grouper sur plusieurs colonnes (par exemple ici sur les colonnes compa
et typeAvion pour classifier les pilotes selon ces deux critères)
...
SELECT compa, AVG(nbHVol), AVG(prime) FROM Pilote
GROUP BY(compa) ;
+-------+-------------+------------+
| compa | AVG(nbHVol) | AVG(prime) |
+-------+-------------+------------+
| AF
| 283
...
0000 |
| CAST |
NULL |
0
...
000000 |
500
...
SELECT compa, COUNT(*), COUNT(nbHVol) FROM Pilote
GROUP BY(compa) ;
+-------+----------+---------------+
| compa | COUNT(*) | COUNT(nbHVol) |
+-------+----------+---------------+
| AF
|
3 |
3 |
| CAST |
1 |
0 |
| SING |
2 |
2 |
+-------+----------+---------------+
MAX
Nombre d’heures de vol le plus élevé, date d’embauche la plus récente pour chaque compagnie
...
00 | 1995-05-13 |
| CAST |
NULL | 2000-12-24 |
| SING |
2450
...
SELECT compa, STDDEV(prime), SUM(nbHVol) FROM Pilote
WHERE typeAvion = 'A320' GROUP BY(compa) ;
+-------+---------------+-------------+
| compa | STDDEV(prime) | SUM(nbHVol) |
+-------+---------------+-------------+
| AF
|
0
...
00 |
| SING |
NULL |
1000
...
dans le GROUP BY SELECT compa,typeAvion, COUNT(brevet) FROM Pilote
GROUP BY compa,typeAvion ;
+-------+-----------+---------------+
| compa | typeAvion | COUNT(brevet) |
+-------+-----------+---------------+
| AF
| A320
|
2 |
| AF
| A340
|
1 |
| CAST | A340
|
1 |
| SING | A320
|
1 |
| SING | A330
|
1 |
+-------+-----------+---------------+
© Éditions Eyrolles
113
Partie I
SQL de base
Tableau 4-27 Exemples de fonctions de groupe avec GROUP BY (suite)
Fonction
Exemples
GROUP BY et
HAVING
Compagnies (et nombre de leurs pilotes) ayant plus d’un pilote
...
Le langage SQL devrait programmer les opérations binaires
(entre deux tables) suivantes :
q
intersection qui extrait des données présentes simultanément dans les deux tables ;
q
union par les opérateurs UNION et UNION ALL qui fusionnent des données des deux
tables ;
q
différence qui extrait des données présentes dans une table sans être présentes dans la
deuxième table ;
q
produit cartésien par le fait de disposer de deux tables dans la clause FROM, ce qui permet
de composer des combinaisons à partir des données des deux tables
...
) doivent être
comparées avec des opérateurs ensemblistes
...
La différence se
programme à l’aide de DISTINCT et NOT IN, l’intersection à l’aide de DISTINCT et IN
...
Le nom des colonnes n’a pas d’importance
...
114
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Exemple
Étudions à présent chaque opérateur à partir de l’exemple composé des deux tables suivantes :
q
q
AvionsdeAF(immat CHAR(6), typeAvion CHAR(10), nbHVol DECIMAL(10,2))
AvionsdeSING(immatriculation CHAR(6), typeAv CHAR(10), prixAchat
DECIMAL(14,2))
Il est vraisemblable que seules les deux premières colonnes doivent être comparées
...
Figure 4-9 Tables pour les opérateurs ensemblistes
AviondeSING
AviondeAF
immat
typeAvion
nbHVol
immatriculation
typeAv
PrixAchat
F-WTSS
F-GLFS
F-GTMP
Web
Concorde
A320
A340
6570
3500
S-ANSI
S-AVEZ
S-SMILE
F-GTMP
A320
A320
A330
A340
104 500
156 000
198 000
204 500
Intersection
L’intersection entre deux ensembles homogènes se programme à l’aide d’une requête du type
SELECT DISTINCT ensemble1 FROM Table1 WHERE ensemble1 IN (SELECT ensemble2
FROM Table2)
...
Notez qu’à l’affichage le nom des colonnes est donné par la première requête
...
Tableau 4-28 Exemples d’intersections
Web
© Éditions Eyrolles
Besoin
Requête
Quels sont les types d’avions que les SELECT DISTINCT typeAvion FROM AvionsdeAF
deux compagnies exploitent en comWHERE typeAvion IN
mun ?
(SELECT typeAv FROM AvionsdeSING);
+-----------+
| typeAvion |
+-----------+
| A320
|
| A340
|
+-----------+
115
Partie I
SQL de base
Tableau 4-28 Exemples d’intersections (suite)
Besoin
Requête
Quels sont les avions qui sont exploi- SELECT DISTINCT immatriculation ,typeAv
tés par les deux compagnies en comFROM AvionsdeSING
mun ?
WHERE immatriculation IN
(SELECT immat FROM AvionsdeAF)
AND typeAv IN
(SELECT typeAvion FROM AvionsdeAF);
+-----------------+--------+
| immatriculation | typeAv |
+-----------------+--------+
| F-GTMP
| A340
|
+-----------------+--------+
Si vous voulez continuer ce raisonnement en vous basant sur trois compagnies, il suffit d’ajouter une clause WHERE dans les requêtes imbriquées qui interrogera la troisième compagnie
...
Opérateurs UNION et UNION
ALL
Les opérateurs UNION et UNION ALL sont commutatifs
...
UNION ALL ne les élimine pas
...
On extrait SELECT typeAvion FROM AvionsdeAF
les types de la compagnie 'AF', suivis des types UNION ALL
de la compagnie 'SING'
...
Différence
La différence entre deux ensembles homogènes se programme à l’aide d’une requête du type
SELECT DISTINCT ensemble1 FROM Table1 WHERE ensemble1 NOT IN (SELECT ensemble2
FROM Table2)
...
Tableau 4-30 Exemples de différences
Web
Besoin
Requête
Quels sont les types d’avions exploités par la SELECT DISTINCT typeAvion FROM AvionsdeAF
compagnie 'AF', mais pas par 'SING' ?
WHERE typeAvion NOT IN
(SELECT typeAv FROM AvionsdeSING);
+-----------+
| typeAvion |
+-----------+
| Concorde |
+-----------+
Quels sont les types d’avions exploités par la SELECT DISTINCT typeAv FROM AvionsdeSING
compagnie 'SING,' mais pas par 'AF' ?
WHERE typeAv NOT IN
(SELECT typeAvion FROM AvionsdeAF);
+--------+
| typeAv |
+--------+
| A330
|
+--------+
© Éditions Eyrolles
117
Partie I
SQL de base
Ce principe se généralise à la différence entre n ensembles par imbrication de n requêtes (dans
le bon ordre)
...
Ordonner les résultats
Le résultat d’une requête contenant des opérateurs ensemblistes est trié, par défaut, par ordre
croissant, sauf avec l’opérateur UNION ALL
...
Cette clause accepte le nom des colonnes de la première requête ou la position
de ces colonnes
...
Le besoin est de connaître tous les types d’avions que les deux
compagnies exploitent (classement par ordre décroissant)
...
Ce mécanisme permet de construire dynamiquement la table à interroger
...
SELECT typeAvion FROM AvionsdeAF
UNION
SELECT typeAv FROM AvionsdeSING
ORDER BY typeAvion DESC ;
Position de la colonne
...
SELECT T
...
typeAvion DESC;
+-----------+
| typeAvion |
+-----------+
| Concorde |
| A340
|
| A330
|
| A320
|
+-----------+
118
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Il faut affecter des alias aux expressions de la première requête pour pouvoir les utiliser dans
le ORDER BY final
...
Le problème
est que la table AvionsdeAF ne possède pas une telle colonne
...
Tableau 4-32 Alias pour ORDER BY
Requête
Résultat
SELECT immatriculation,
1
...
000 |
| S-MILE
| 237600
...
000 |
| S-ANSI
| 125400
...
000 |
| F-GTMP
|
0
...
000 |
+-----------------+------------+
Produit cartésien
En mathématiques, le produit cartésien de deux ensembles E et F est l’ensemble des couples
(x, y) où x ∈ E et y ∈ F
...
Le produit cartésien total entre deux tables T1 et T2 se programme sous SQL en positionnant
les deux tables dans la clause FROM, sans ajouter de conditions dans la clause WHERE
...
Si les conditions sont de la forme c1 opérateur valeur1 ou c2 opérateur valeur2,
on parlera de produit cartésien restreint
...
© Éditions Eyrolles
119
Partie I
SQL de base
Figure 4-10 Produit cartésien d’enregistrements de tables
Pilote
brevet
PL-1
PL-2
PL-3
PL-4
AviondeAF
nom
Gratien Viel
Richard Grin
Placide Fresnais
Daniel Vielle
nbHVol
450
1000
2450
5000
compa
AF
SING
CAST
AF
immat
F-WTSS
F-GLFS
F-GTMP
typeAvion
Concorde
A320
A340
nbHVol
6570
3500
Le nombre d’enregistrements résultant d’un produit cartésien est égal au produit du nombre
d’enregistrements des deux tables mises en relation
...
Le tableau suivant décrit la requête SQL permettant
de construire le produit cartésien restreint de notre exemple
...
Tableau 4-33 Produit cartésien
Web
Besoin
Requête
Quels sont les couples possibles (avion, pilote) SELECT p
...
immat
en considérant les avions et les pilotes de la
FROM Pilote p, AvionsdeAF avAF
compagnie 'AF' ?
WHERE p
...
Il est possible d’ajouter des expressions (constantes ou
calculs) à une requête pour rendre homogènes les deux requêtes, et permettre ainsi l’utilisation
d’un opérateur ensembliste
...
120
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Jointures
Les jointures permettent d’extraire des données issues de plusieurs tables
...
Ainsi, la majorité des requêtes utilisent des
jointures nécessaires pour pouvoir extraire des données de tables distinctes
...
Généralement, cette comparaison fait intervenir une clé étrangère d’une table avec
une clé primaire d’une autre table (car le modèle relationnel est fondamentalement basé sur
les valeurs)
...
Ces jointures
permettront d’afficher des données d’une table (ou des deux tables) tout en posant des conditions sur une table (ou les deux)
...
Figure 4-11 Deux tables à mettre en jointure
Compagnie
comp
AF
SING
CAST
nrue rue
124
Port Royal
7
Camparols
1
G
...
© Éditions Eyrolles
121
Partie I
SQL de base
Nous allons principalement étudier les deux premières écritures qui sont les plus utilisées
...
Jointure relationnelle
La forme la plus courante de la jointure est la jointure dite « relationnelle » (aussi appelée
SQL89), caractérisée par une seule clause FROM contenant les tables et alias à mettre en jointure deux à deux
...
]col1, [alias2
...
]nomTable1 [alias1], [nomBase
...
Un autre avantage de ce type
de jointure est qu’elle laisse le soin au SGBD d’établir la meilleure stratégie d’accès (choix du
premier index à utiliser, puis du deuxième, etc
...
Afin d’éviter les ambiguïtés concernant le nom des colonnes, on utilise en général des alias de
tables pour suffixer les tables dans la clause FROM et préfixer les colonnes dans les clauses
SELECT et WHERE
...
]nomTable1 [{ INNER | { LEFT | RIGHT } [OUTER] }]
JOIN [nomBase
...
)}
| { CROSS JOIN | NATURAL [{ LEFT | RIGHT } [OUTER] ]
JOIN [nomBase
...
Bien que plus concise pour des
jointures à deux tables, elle se complique pour des jointures plus complexes
...
La jointure naturelle est conditionnée en plus par le nom des colonnes
...
– L’autojointure (self join) est un cas particulier de l’équijointure, qui met en œuvre deux
fois la même table (des alias de tables permettront de distinguer les enregistrements
entre eux)
...
Les lignes de la table dominante sont retournées même si elles ne satisfont pas aux conditions de jointure
...
chefPil = alias2
...
Pour n tables, il faut n-1 clauses de jointures
...
Étudions à présent chaque type de jointure avec les syntaxes « relationnelle » et « SQL2 »
...
En considérant les tables suivantes, les équijointures se programment soit sur les colonnes
comp et compa soit sur les colonnes brevet et chefPil
...
La jointure qui résoudra la première requête est illustrée dans la figure par les données grisées,
tandis que la deuxième jointure est représentée par les données en gras
...
Brassens
ville
Paris
Singapour
Blagnac
nomComp
Air France
Singapore AL
Castanet AL
Pilote
brevet
PL-1
PL-2
PL-3
PL-4
nom
Pierre Lamothe
Didier Linxe
Christian Soutou
Henri Alquié
nbHVol compa
450
AF
900
AF
1000
SING
3400
AF
chefPil
PL-4
PL-4
Écriture « relationnelle »
• MySQL recommande d’utiliser des alias de tables pour améliorer les performances
...
Écriture « SQL2 »
• La clause JOIN … ON condition permet de programmer une équijointure
...
Le tableau suivant détaille ces requêtes avec les deux syntaxes
...
124
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Tableau 4-35 Exemples d’équijointures
Requête
Jointure relationnelle
Jointure SQL2
R1
Web
SELECT
FROM
WHERE
AND
AND
SELECT
FROM
JOIN
WHERE
AND
brevet,
Pilote,
comp
nomComp
nbHVol
nom
Compagnie
= compa
= 'Air France'
> 500;
brevet, nom
Compagnie
Pilote ON comp = compa
nomComp = 'Air France'
nbHVol > 500;
+--------+--------------+
| brevet | nom
|
+--------+--------------+
| PL-2
| Didier Linxe |
| PL-4
| Henri Alquié |
+--------+--------------+
R2
SELECT cpg
...
nrue,
SELECT nomComp, nrue, rue, ville
cpg
...
ville
FROM Compagnie
FROM Pilote pil, Compagnie cpg
INNER JOIN Pilote ON comp = compa
WHERE nbHVol < 500;
WHERE cpg
...
compa
AND
pil
...
Extrayons par exemple :
q
l’identité des pilotes placés sous la responsabilité des pilotes de nom 'Alquié'
(requête R3) ;
q
la somme des heures de vol des pilotes placés sous la responsabilité des chefs pilotes de la
compagnie de nom 'Air France' (requête R4)
...
Les autojointures sont réalisées entre les colonnes brevet et chefPil
...
© Éditions Eyrolles
125
Partie I
SQL de base
Figure 4-13 Autojointures
Compagnie
comp
AF
SING
CAST
nrue rue
124
Port Royal
7
Camparols
1
G
...
Dans les
deux syntaxes, il est impératif d’utiliser un alias de table
...
Tableau 4-36 Exemples d’autojointures
Web
Requête
Jointure relationnelle
Jointure SQL2
R3
SELECT
FROM
WHERE
AND
SELECT p1
...
nom
FROM
Pilote p1
JOIN Pilote p2
ON
p1
...
brevet
WHERE p2
...
brevet, p1
...
chefPil = p2
...
nom LIKE '%Alquié%';
+--------+----------------+
| brevet | nom
|
+--------+----------------+
| PL-1
| Pierre Lamothe |
| PL-2
| Didier Linxe
|
+--------+----------------+
R4
SELECT SUM(p1
...
nbHVol)
FROM Pilote p1, Pilote p2,
FROM Pilote p1
Compagnie cpg
JOIN Pilote p2
WHERE p1
...
brevet
ON p1
...
brevet
AND
cpg
...
compa
JOIN Compagnie
AND cpg
...
compa
WHERE nomComp = 'Air France';
+----------------+
| SUM(p1
...
00 |
+----------------+
126
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Inéquijointure
Les requêtes d’inéquijointures font intervenir tout type d’opérateur (<>, >, <, >=, <=, BETWEEN,
LIKE, IN)
...
En considérant les tables suivantes, extrayons par exemple :
q
les pilotes ayant plus d’expérience que le pilote de numéro de brevet 'PL-2' (requête R5)
...
Dans notre exemple, il
s’agit par exemple de retrouver le fait que le premier pilote est débutant
...
Figure 4-14 Inéquijointures
Pilote
brevet
PL-1
PL-2
PL-3
PL-4
nom
Pierre Lamothe
Didier Linxe
Christian Soutou
Henri Alquié
nbHVol compa
450
AF
900
AF
1000
SING
3400
AF
chefPil
PL-4
PL-4
HeuresVol
titre
Débutant
Initié
Expert
basnbHVol hautnbHVol
500
0
501
1000
1001
20000
Le tableau suivant détaille ces requêtes, les clauses d’inéquijointures sont surlignées :
Tableau 4-37 Exemples d’inéquijointures
Web
Requête
Jointure relationnelle
R5
SELECT p1
...
nom,
SELECT p1
...
nom,
p1
...
nbHVol "Référence"
p1
...
nbHVol "Référence"
FROM Pilote p1, Pilote p2
FROM Pilote p1 JOIN
WHERE p1
...
nbHVol
Pilote p2 ON p1
...
nbHVol
AND p2
...
brevet = 'PL-2';
Jointure SQL2
+--------+------------------+---------+-----------+
| brevet | nom
| nbHVol | Référence |
+--------+------------------+---------+-----------+
| PL-3
| Christian Soutou | 1000
...
00 |
| PL-4
| Henri Alquié
| 3400
...
00 |
+--------+------------------+---------+-----------+
© Éditions Eyrolles
127
Partie I
SQL de base
Tableau 4-37 Exemples d’inéquijointures (suite)
Requête
Jointure relationnelle
Jointure SQL2
R6
SELECT pil
...
nom,
SELECT brevet, nom, nbHVol, titre
pil
...
titre
FROM Pilote
FROM Pilote pil, HeuresVol hv
JOIN HeuresVol ON nbHVol
WHERE pil
...
basnbHVol AND hv
...
00 | Débutant |
| PL-2
| Didier Linxe
| 900
...
00 | Initié
|
| PL-4
| Henri Alquié
| 3400
...
Lorsque deux tables sont en jointure externe, une table est « dominante » par
rapport à l’autre (qui est dite « subordonnée »)
...
Comme les jointures internes, les jointures externes sont généralement basées sur les clés
primaires et étrangères
...
Jointures unilatérales
En considérant les tables suivantes, une jointure externe unilatérale permet d’extraire :
q
la liste des compagnies et leurs pilotes, même les compagnies n’ayant pas de pilote
(requête R7)
...
La figure illustre les tables dominantes et subordonnées :
q
128
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Figure 4-15 Jointures externes unilatérales
Qualifs
brevet typeAv
Compagnie
comp
nrue rue
Pilote
2005 -06-24
2005 -06-24
2006 -04-04
2006 -05-13
A320
A340
A320
A330
subordonnée
ville
AF
124
Port Royal
SING
7
Camparols
CAST
1
G
...
Le tableau suivant détaille les requêtes de notre exemple, les clauses de jointures externes
unilatérales sont grisées
...
Tableau 4-38 Écritures équivalentes de jointures externes unilatérales
Web
Requête
Jointures relationnelles
Jointures SQL2
R7
Sans objet
...
SELECT qua
...
brevet, pil
...
brevet = qua
...
typeAv, pil
...
nom
FROM Pilote pil
LEFT OUTER JOIN Qualifs qua
ON pil
...
brevet ;
+--------+--------+------------------+
| typeAv | brevet | nom
|
+--------+--------+------------------+
| NULL
|
| PL-1
| Pierre Lamothe
| A320
| PL-2
| Didier Linxe
|
| A330
| PL-3
| Christian Soutou |
| A320
| PL-4
| Henri Alquié
|
| A340
| PL-4
| Henri Alquié
|
+--------+--------+------------------+
Jointures bilatérales
Les deux tables jouent un rôle symétrique, il n’y a pas de table dominante
...
En considérant les tables suivantes, une jointure externe bilatérale permet d’extraire, par
exemple :
q
la liste des compagnies et leurs pilotes, incluant les compagnies n’ayant pas de pilote et les
pilotes rattachés à aucune compagnie (requête R9) ;
q
la liste des pilotes et leurs qualifications, incluant les pilotes n’ayant pas encore d’expérience et les qualifications associées à des pilotes inconnus (requête R10)
...
Brassens
Pilote
brevet
nom
nbHVol compa
PL-1
PL-2
PL-3
PL-4
PL-5
Pierre Lamothe
Didier Linxe
Christian Soutou
Henri Alquié
Michel Castaings
450
900
1000
3400
AF
AF
SING
AF
Écriture « SQL2 »
La directive FULL OUTER JOIN permet d’ignorer l’ordre (et donc le sens de la jointure) des
tables dans la requête
...
0, la directive FULL OUTER JOIN
...
Les enregistrements qui ne respectent pas la condition de jointure
sont surlignés
...
R10
Web
Sans objet
...
typeAv, pil
...
nom
FROM Pilote pil
FULL OUTER JOIN Qualifs qua
ON pil
...
brevet;
--équivalent à
SELECT qua
...
brevet, pil
...
brevet = qua
...
Chaque clause FROM ne contient qu’une seule table
...
]nomTable1
WHERE colonne(s) | expression(s) { IN | = | opérateur }
(SELECT colonne(s)delaTable2 FROM [nomBase
...
Elle est plus complexe à écrire, car l’ordre d’apparition des tables dans les clauses
FROM a son importance
...
La sous-interrogation doit être placée entre parenthèses
...
Le résultat d’une sous-interrogation est utilisé par la requête de niveau supérieur
...
Une sous-interrogation peut ramener une ou plusieurs lignes
...
Sous-interrogations monolignes
Le tableau suivant détaille quelques sous-interrogations monolignes
...
Tableau 4-40 Sous-interrogations monolignes
Opérateur
Besoin
Requête
= pour les équijointures ou autojointures (= teste
une ligne)
R1 (Pilotes de la compagnie
de nom 'Air France' ayant
plus de 500 heures de vol
...
)
Web
SELECT brevet, nom FROM Pilote
WHERE chefPil =
(SELECT brevet FROM Pilote
WHERE nom LIKE '%Alquié%') ;
R5 (Pilotes ayant plus
d’expérience que le pilote
de brevet 'PL-2'
...
Cet opérateur est utilisé pour les équijointures et les autojointures (et les intersections)
...
• ANY compare l’élément à chaque donnée ramenée par la sous-interrogation
...
L’opérateur «
...
• ALL compare l’élément à tous ceux ramenés par la sous-interrogation
...
Le tableau suivant détaille quelques sous-interrogations multilignes
...
Tableau 4-41 Sous-interrogations multilignes
Opérateur
Besoin
Requête
IN
R2
...
SELECT nomComp, nrue, rue, ville
FROM Compagnie
WHERE comp IN
( SELECT compa FROM Pilote
WHERE nbHVol < 500) ;
= et IN
R4
...
(SELECT comp FROM Compagnie
WHERE nomComp = 'Air France')
);
NOT IN
Web
Compagnies n’ayant pas de pilote
...
134
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
Afin d’illustrer les opérateurs ANY et ALL, considérons la table suivante
...
Figure 4-17 Table Avion
Avions
immat
typeAv
A1
A2
A3
A4
A5
A6
A320
A330
A320
A340
A340
A330
nbHVol
1000
1500
550
1800
200
100
compa
AF
AF
SING
SING
AF
AF
Le tableau suivant détaille quelques jointures procédurales utilisant les opérateurs ALL et
ANY :
Tableau 4-42 Opérateurs ALL et ANY
Opérateur
Requête et résultat
R11
...
SELECT immat, typeAv, nbHVol
FROM Avion
WHERE nbHVol < ANY
(SELECT nbHVol FROM Avion
WHERE typeAv='A320') ;
+-------+--------+--------+
| immat | typeAv | nbHVol |
+-------+--------+--------+
| A3
| A320
| 550
...
00 |
| A6
| A330
| 100
...
Compagnies et leurs
avions dont le nombre
d’heures de vol est supérieur à celui de n’importe
quel avion de la compagnie
de code 'SING'
...
00 | AF
|
| A2
| A330
| 1500
...
00 | SING |
+-------+--------+---------+-------+
135
Partie I
SQL de base
Tableau 4-42 Opérateurs ALL et ANY (suite)
Opérateur
Besoin
Requête et résultat
ALL
R13
...
SELECT immat, typeAv, nbHVol
FROM Avion
WHERE nbHVol < ALL
(SELECT nbHVol FROM Avion
WHERE typeAv='A320') ;
+-------+--------+--------+
| immat | typeAv | nbHVol |
+-------+--------+--------+
| A5
| A340
| 200
...
00 |
+-------+--------+--------+
R14
...
SELECT immat, typeAv, nbHVol, compa
FROM Avion
WHERE nbHVol > ALL
(SELECT nbHVol FROM Avion
WHERE compa = 'AF') ;
+-------+--------+---------+-------+
| immat | typeAv | nbHVol | compa |
+-------+--------+---------+-------+
| A4
| A340
| 1800
...
Jointure relationnelle procédurale
La jointure mixte suivante combine une clause de jointure relationnelle (en gras) avec une
jointure procédurale (en surligné) pour programmer la requête R4 :
SELECT SUM(p1
...
chefPil = p2
...
compa = (SELECT comp FROM Compagnie WHERE nomComp =
'Air France') ;
Ce type d’écriture peut être intéressant s’il n’est pas nécessaire d’afficher des colonnes des
tables présentes dans les sous-interrogations, ou si l’on désire appliquer des fonctions à des
regroupements
...
SELECT listeColonnes
FROM table1 aliasTable1, (SELECT… FROM table2 WHERE…) aliasTable2
[ WHERE (conditionsTable1etTable2) ];
Considérons la table suivante
...
Dans notre exemple, il y a 5 pilotes dont 3 dépendent de 'AF'
...
Figure 4-18 Table Pilote
Pilote
brevet
nom
Pierre Lamothe
Didier Linxe
Christian Soutou
Henri Alquié
Michel Castaings
PL-1
PL-2
PL-3
PL-4
PL-5
nbHVol compa
450
AF
900
AF
1000
SING
3400
AF
La requête suivante construit dynamiquement deux tables (alias a et b) dans la clause FROM
pour répondre à cette question :
Tableau 4-43 SELECT dans un FROM
Requête et tables évaluées dans le FROM
Résultat
SELECT a
...
nbpil/b
...
0000 |
| AF
| 60
...
0000 |
+------+---------+
Sous-interrogations synchronisées
Une sous-interrogation est synchronisée si elle manipule des colonnes d’une table du niveau
supérieur
...
Cette technique peut être aussi utilisée dans les
ordres UPDATE et DELETE
...
Les alias des tables sont utiles pour pouvoir manipuler des colonnes de tables de
différents niveaux
...
c
FROM nomTable1 alias1
WHERE colonne(s) opérateur (SELECT alias2
...
x opérateur alias2
...
Différents opérateurs peuvent être employés (=, >, <, >=, <=, EXISTS)
...
Avions dont le nombre d’heures de
vol est supérieur au nombre d’heures de
vol moyen des avions de leur compagnie
(ici 700 heures pour 'AF' et 1115 heures
pour 'SING')
...
* FROM Avion avi1
WHERE avi1
...
nbHVol) FROM Avion avi2
WHERE avi2
...
compa) ;
+-------+--------+---------+-------+
| immat | typeAv | nbHVol | compa |
+-------+--------+---------+-------+
| A1
| A320
| 1000
...
00 | AF
|
| A4
| A340
| 1800
...
La valeur FALSE est retournée si aucun enregistrement n’est extrait par la sous-interrogation
...
Pilotes ayant au moins un pilote sous
leur responsabilité
...
brevet, pil1
...
compa
FROM Pilote pil1 WHERE EXISTS
(SELECT pil2
...
chefPil = pil1
...
Cet opérateur peut être utilisé pour écrire des jointures externes
...
SELECT cpg
...
comp);
+------+------+-------------+---------+-------------+
| comp | nrue | rue
| ville
| nomComp
|
+------+------+-------------+---------+-------------+
| CAST |
1 | G
...
Considérons le schéma suivant (des colonnes portent le même nom)
...
Figure 4-20 Deux tables à mettre en jointure naturelle
VolsControle
brevet typeAv
validite
PL-1
PL-2
PL-2
PL-3
PL-3
2005-06-24
2006-04-04
2006-05-13
2007-07-20
2005-03-12
A320
A320
A330
A380
A320
Navigant
brevet
nom
nbHVol typeAv
PL-1
PL-2
PL-3
Pierre Lamothe
Didier Linxe
Henri Alquié
450
900
3400
A320
A380
Opérateur NATURAL JOIN
La jointure naturelle est programmée par la clause NATURAL JOIN
...
Les concepteurs devraient ainsi penser à nommer d’une manière semblable clés primaires et
clés étrangères ! Ce principe n’est pas souvent appliqué aux bases volumineuses
...
La clause de jointure est basée sur les colonnes (brevet, typeAv)
...
Tableau 4-47 Jointures naturelles
Besoin
140
Jointures SQL2 et résultat
Navigants qualifiés sur un type d’appareil et
instructeurs sur ce même type
...
Il ne faut pas utiliser d’alias de tables dans la liste des
colonnes
...
Si on les positionnait (brevet, typeAv) dans la directive USING, cela reviendrait
à construire un NATURAL JOIN
...
Web
SELECT nom, v
...
validite FROM Naviguant
JOIN VolsControle v USING(brevet) ;
SELECT nom, v
...
validite FROM VolsControle v
JOIN Naviguant USING(brevet) ;
+----------------+--------+------------+
| nom
| typeAv | validite
|
+----------------+--------+------------+
| Pierre Lamothe | A320
| 2005-06-24 |
| Didier Linxe
| A320
| 2006-04-04 |
| Didier Linxe
| A330
| 2006-05-13 |
| Henri Alquié
| A380
| 2007-07-20 |
| Henri Alquié
| A320
| 2005-03-12 |
+----------------+--------+------------+
Opérateur CROSS JOIN
La directive CROSS JOIN programme un produit cartésien qu’on peut restreindre dans la
clause WHERE
...
SELECT * FROM Naviguant CROSS JOIN VolsControle ;
-- équivalent à
SELECT * FROM VolsControle CROSS JOIN Naviguant;
+--------+----------------+---------+--------+--------+--------+------------+
| brevet | nom
| nbHVol | typeAv | brevet | typeAv | validite
|
+--------+----------------+---------+--------+--------+--------+------------+
| PL-1
| Pierre Lamothe | 450
...
00 | A320
| PL-1
| A320
| 2005-06-24 |
| PL-3
| Henri Alquié
| 3400
...
00 | NULL
| PL-2
| A320
| 2006-04-04 |
...
Cet opérateur est semblable sur le
principe à l’opération qu’on apprend au CM2 (oubliée plus tard en terminale à cause des
calculettes)
...
Il est possible d’opérer une division à
partir d’une seule table, en ce cas on divise deux parties de cette table (analogue aux autojointures)
...
Il n’existe donc malheureusement pas d’instruction DIVIDE
...
On peut aussi dire que lorsque vous voulez comparer un ensemble avec un groupe de référence, il faut programmer une division
...
142
© Éditions Eyrolles
chapitre n° 4
Interrogation des données
La figure suivante illustre l’opérateur de division dans sa plus simple expression (je ne parle
pas du contenu des tables, bien sûr…)
...
Figure 4-21 Division
T1
Jospin
Juppé
Juppé
Baudis
Baudis
Baudis
Chirac
Chirac
Chirac
T2
Quotient
Quels sont les enregistrements de T1 qui sont
associés à « tous les » enregistrements de T2 ?
Réponse : Chirac
Quotient=(T1–Reste)/T2
(ici Reste n’est pas nul)
Chirac
Définition
La division de la table T1[a1,
...
,bn] par la table T2[b1,
...
,an] qui contient les enregistrements ti
vérifiant ti ∈ T3 (de structure [a1,
...
,bn]) et ti,tj ∈ T1 (ti,tj de
structure [a1,
...
,bn])
...
Il s’agit de répondre à la
question : « Quels sont les avions affrétés par toutes les compagnies françaises ? »
...
L’ensemble à comparer (B) est formé des codes des compagnies pour chaque avion
...
La question à programmer serait : « Quels sont les avions affrétés par toutes les
compagnies françaises ? », sans préciser si les avions ne doivent pas être aussi affrétés par
des compagnies étrangères
...
q
Division exacte (le reste est nul) : les deux ensembles sont égaux (B=A)
...
L’avion ('A3', 'Mercure') répondrait à cette question
si la dernière ligne de la table Affretements était inexistante
...
© Éditions Eyrolles
143
Partie I
SQL de base
Figure 4-22 Divisions à programmer
Affretements
Web
Compagnie
immat
typeAv
compa
dateAff
comp
nomComp
pays
A1
A2
A3
A4
A3
A3
A320
A340
Mercure
A330
Mercure
Mercure
SING
AF
AF
ALIB
ALIB
SING
1965 -05-13
1968 -06-22
1965 -02-05
1965 -01-16
1942 -03-05
1987 -03-01
AF
ALIB
SING
Air France
Air Lib
Singapore AL
F
F
SG
Résultat
immat
typeAv
A3
Mercure
L’opérateur de différence (programmé avec NOT IN) combiné à la fonction EXISTS permet
de programmer ces deux comparaisons (un ensemble inclus dans un autre et une égalité
d’ensembles)
...
Écrivons à présent ces deux divisions à l’aide de requêtes SQL
...
La différence se programme à l’aide de
l’opérateur NOT IN, l’inexistence d’élément se programme à l’aide de la fonction NOT
EXISTS comme le montre la requête suivante :
Parcours de tous les avions
SELECT DISTINCT immat, typeAv FROM Affretements aliasAff
WHERE NOT EXISTS
Ensemble
A de référence
(SELECT DISTINCT comp FROM Compagnie WHERE pays = 'F'
AND comp NOT IN
( SELECT compa FROM Affr etements WHERE immat = aliasAff
...
La traduction mathématique est la suivante : A=B⇔(A-B=∅ et B-A=∅)
...
Le « et » se programme avec un AND
...
immat ))
AND NOT EXISTS
(SELECT compa FROM Affretements WHERE immat = aliasAff
...
Cela peut être intéressant si vous voulez rapidement publier des pages (qui seront statiques bien sûr) ou composer des fichiers destinés à
l’échange de données provenant de votre base
...
Concernant XML, la balise de plus haut niveau contient un attribut décrivant
la requête
...
immat)) AND NOT EXISTS (SELECT
compa FROM Affretements WHERE immat =
aliasAff
...
Une telle requête écrit dans un fichier dans un
répertoire du serveur
...
Le fichier cible doit être inexistant avant
d’exécuter son chargement
...
[ WHERE condition ]
INTO OUTFILE 'cheminEtNomFichier'
[FIELDS [TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char' ] ]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string'] ] ;
q
q
FIELDS décrit comment seront formatées dans le fichier les colonnes extraites de(s)
table(s)
...
– FIELDS TERMINATED BY décrit le caractère qui sépare deux valeurs de colonnes
...
– FIELDS ESCAPED BY permet de contrôler les caractères spéciaux
...
En
l’absence de cette clause, TERMINATED BY vaut '\n' et STARTING BY vaut ''
...
txt » situé dans le répertoire « D:\dev », en exportant la totalité des enregistrements de la table Pilote (SELECT *) décrite au début du chapitre
...
Notez l’utilisation du double « \ » pour désigner une arborescence Windows
...
Figure 4-23 Création d’un fichier
SELECT * INTO OUTFILE 'D: \\dev\\pilotes
...
4
...
sql permettant de créer les tables Softs et PCSeuls suivantes (en utilisant la directive AS SELECT de la commande CREATE TABLE)
...
Penser à modifier le nom des colonnes
...
La table PCSeuls doit seulement contenir les enregistrements de la table Poste, qui sont de type 'PCWS' ou 'PCNT'
...
2
Requêtes monotables
Écrire le script requêtes
...
3
Noms, adresses IP, numéros de salle des postes de type 'UNIX' ou 'PCWS'
...
120
...
5
Numéros des logiciels installés sur le poste 'p6'
...
7
© Éditions Eyrolles
Type du poste 'p8'
...
120
...
01') des postes de type 'TX' (utiliser la fonction
de concaténation)
...
3
Fonctions et groupements
8
Pour chaque poste, le nombre de logiciels installés (en utilisant la table Installer)
...
10 Pour chaque logiciel, le nombre d’installations sur des postes différents
...
12 Plus récente date d’achat d’un logiciel
...
14 Nombre de postes hébergeant 2 logiciels (utiliser la requête précédente en faisant un SELECT
dans la clause FROM)
...
4
Requêtes multitables
Opérateurs ensemblistes
15 Types de postes non recensés dans le parc informatique (utiliser la table Types)
...
17 Types de postes de travail n’étant pas des types de logiciels
...
19 Adresses IP complètes des postes qui hébergent le logiciel de nom 'Oracle 8'
...
21 Noms des salles ou l’on peut trouver au moins un poste hébergeant le logiciel 'Oracle 6'
...
Jointures relationnelles
Écrire les requêtes 18, 19, 20, 21 avec des jointures de la forme relationnelle
...
27 Installations (nom segment, nom salle, adresse IP complète, nom logiciel, date d’installation) triées
par segment, salle et adresse IP
...
Numéroter ces nouvelles requêtes de 28 à 31
...
5
Modifications synchronisées
Écrire le script modifSynchronisées
...
p2
p8
p10
nLog
...
séquence
...
SYSDATE()
SYSDATE ()
SYSDATE ()
delai
...
colonneA = alias1
...
) ;
Pour mettre à jour automatiquement les colonnes rajoutées :
•
nbSalle dans la table Segment (nombre de salles traversées par le segment) ;
•
nbPoste dans la table Segment (nombre de postes du segment) ;
•
nbInstall dans la table Logiciel (nombre d’installations du logiciel) ;
•
nbLog dans la table Poste (nombre de logiciels installés par poste)
...
4
...
sql, les instructions SELECT pour extraire les données suivantes :
Sous-interrogation synchronisée
32 Noms des postes ayant au moins un logiciel commun au poste 'p6' (on doit trouver les postes p2,
p8 et p10)
...
On doit trouver les postes 'p2' et 'p8' (division inexacte)
...
© Éditions Eyrolles
149
Chapitre 5
Contrôle des données
Comme dans tout système multi-utilisateur, l’usager d’un SGBD doit être identifié avant de
pouvoir utiliser des ressources
...
La figure suivante illustre un groupe d’utilisateurs dans lequel existe une classification entre ceux qui peuvent consulter, mettre à jour,
supprimer des enregistrements, voire les tables
...
Nous étudierons :
q
la gestion des utilisateurs qui manipuleront des bases de données dans lequelles se trouvent
des objets tels que des tables, index, séquences (pour l’instant implémentées par des colonnes AUTO_INCREMENT), vues, procédures, etc
...
Le chapitre 9 détaille l’outil graphique MySQL Administrator qui permet de s’affranchir
d’écrire des instructions SQL
...
Cela fait, il
pourra accéder à différents objets (tables, vues, séquences, index, procédures, etc
...
Classification
Les types d’utilisateurs, leurs fonctions et leur nombre peuvent varier d’une base à une autre
...
Il en existe au moins un
...
Une base importante peut en regrouper plusieurs qui se partagent les tâches suivantes :
– installation et mises à jour de la base et des outils éventuels ;
– gestion de l’espace disque et des espaces pour les données ;
– gestion des utilisateurs et de leurs objets (s’ils ne les gèrent pas eux-mêmes) ;
– optimisation des performances ;
– sauvegardes, restaurations et archivages ;
– contact avec le support technique
...
Les développeurs qui conçoivent et mettent à jour la base
...
Ils transmettent au
DBA leurs demandes spécifiques (stockage, optimisation, sécurité)
...
Pour les petites et les moyennes bases, le DBA joue ce rôle
...
Tous seront des utilisateurs (au sens MySQL) avec des privilèges différents
...
user qui stockera l’existence de ce
nouvel arrivant)
...
];
q
IDENTIFIED BY motdePasse permet d’affecter un mot de passe (16 caractères maximum,
sensibles à la casse) à un utilisateur (16 caractères maximum, sensibles aussi à la casse)
...
Par défaut, les utilisateurs, une fois créés, n’ont aucun droit sur aucune base de données (à part
en lecture écriture sur la base test et en lecture seule sur la base information_schema)
...
Un utilisateur bien connu
Lors de l’installation, vous avez dû noter la présence de l’utilisateur root (mot de passe saisi
à l’installation)
...
Il vous permettra d’effectuer vos tâches administratives en ligne de commande ou par une console graphique (créer des
utilisateurs par exemple)
...
user)
...
Si
root n’avait pas sélectionné la base mysql, la commande à exécuter aurait été « SELECT
User,Host FROM mysql
...
(root@localhost) [mysql] mysql> SELECT User,Host FROM user;
+--------+-----------+
| User
| Host
|
+--------+-----------+
|
| %
|
|
| localhost |
| root
| localhost |
| soutou | localhost |
+--------+-----------+
© Éditions Eyrolles
153
Partie I
SQL de base
Vous devez posséder une table similaire
...
L’utilisateur vide
' ' correspond à une connexion anonyme
...
La machine désignée par « localhost » spécifie que
la connexion est autorisée en local
...
db) est permis en local et à partir de tout site, et que soutou comme root ne
peuvent se connecter qu’en local
...
Nous verrons plus
tard qu’il est possible de restreindre le nombre de requêtes (SELECT), de modifications
(UPDATE), de connexions par heure et de connexions simultanées à un serveur
...
L’instruction suivante modifie le mot de passe de l’utilisateur soutou pour l’accès en local
...
Il est plus prudent d’utiliser ensuite FLUSH PRIVILEGES qui recharge les tables système de manière à rendre la manipulation effective sur
l’instant (un peu comme un COMMIT sur des données)
...
user
SET Password = PASSWORD('eyrolles')
WHERE User = 'soutou'
AND
Host = 'localhost';
FLUSH PRIVILEGES;
Une fois cette modification réalisée, si soutou tente une connexion avec son ancien mot de
passe, il vient l’erreur classique : « ERROR 1045 (28000): Access denied for user
'soutou'@'localhost' (using password: xx) » (xx valant YES si soutou se
connecte avec son ancien mot de passe, NO s’il n’en donne pas)
...
Mais attention ! Le fait de lui donner ce droit (nous verrons plus loin comment le
faire) implique également qu’il puisse aussi modifier les mots de passe de ses copains, ainsi
que celui du root !
Renommer un utilisateur (RENAME
USER)
Pour pouvoir renommer un utilisateur, vous devez posséder le privilège CREATE USER (ou le
privilège UPDATE sur la base de données mysql)
...
Les privilèges et le mot de
passe ne changent pas
...
Tableau 5-2 Renommer un utilisateur
Instruction SQL
Commentaire
RENAME USER soutou @localhost
TO christiansoutou @localhost;
L’accès soutou en local est renommé
christiansoutou en local
...
53
...
12 ;
L’accès christiansoutou en local est renommé
christiansoutou en accès distant
...
53
...
12
TO soutou@localhost ;
L’accès est renommé complètement
...
La syntaxe SQL est la suivante :
DROP USER utilisateur [,utilisateur2
...
Tous les privilèges relatifs à cet accès
sont détruits
...
Aucune donnée d’aucune table que l’utilisateur aura mis à jour durant toutes ses connexions
ne sera supprimée
...
) à un utilisateur
...
Pour supprimer le compte soutou en local, la commande à lancer est :
DROP USER soutou@localhost;
Gestion des bases de données
Abordée brièvement à l’introduction, une base de données (database) regroupe essentiellement des tables sur lesquelles l’administrateur affectera des autorisations à des utilisateurs
...
D’ailleurs dans l’instruction de création les deux mots peuvent être utilisés
...
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] nomBase
[ [DEFAULT] CHARACTER SET nomJeu ]
[ [DEFAULT] COLLATE nomCollation ];
q
IF NOT EXISTS évite une erreur dans le cas où la base de données existe déjà (auquel
cas elle ne sera pas remplacée)
...
Les caractères « / », « \ », ou «
...
q
CHARACTER SET indique le jeu de caractères associé aux données qui résideront dans les
tables de la base
...
La collation, dans le jargon
informatique, permet de définir la position des caractères dans le jeu
...
Le but étant de
s’adapter aux différentes règles et langues de notre petite planète
...
n\data\nouvelleBase dans le cas de Windows)
...
Si vous concevez manuellement un répertoire (mkdir rep1
par exemple) dans le répertoire de data de MySQL, rep1 sera considéré comme une base de
données avec le jeu de caractères par défaut (visible avec « SHOW DATABASES; »)
...
opt qui stocke les caractéristiques de la base
...
Souhaitons que ce ne soit pas
gb2312 associé par défaut à la collation gb2312_chinese_ci qui vous ferait dire que je
vous parle chinois ! C’est pourtant quelquefois ce que je ressens quand mes étudiants me
regardent avec des yeux de poisson en utilisant le langage des carpes…
Le tableau suivant décrit la création de deux bases de données :
Tableau 5-3 Création de bases
Instruction SQL
Résultat
CREATE DATABASE bdnouvelle
DEFAULT CHARACTER SET ascii
COLLATE ascii_general_ci;
La base bdnouvelle est créée, le jeu de caractères
par défaut est ASCII
...
1
...
Petit Larousse
...
ini à l’aide de la variable defaultcharacter-set
...
Le jeu de caractères d’une base définit celui des
tables qui seront constituées dedans, à moins que la table ne soit combinée à un autre jeu (créé
avec la directive [DEFAULT] CHARACTER SET jeu [COLLATE nomCollation])
...
L’exemple suivant construit la table testChap5 dans la base bdnouvelle2 (par
défaut chinoise) en spécifiant que la colonne col1 sera associée au jeu cp850 : DOS West
European, tandis que le reste de la table (pour l’instant de portée col2) sera appliqué au jeu
latin1 : cp1252 West European
...
CREATE TABLE bdnouvelle2
...
testChap5 VALUES ('GTR','IUT');
Sélection d’une base de données (USE)
Ceux qui ont travaillé sous Dbase se souviennent de l’instruction USE qui désignait la table
courante dans un programme
...
USE nomBase;
Si vous désirez travailler simultanément dans différentes bases de données, faites toujours
préfixer le nom des tables par celui de la base par la notation pointée (nomBase
...
L’exemple suivant exécute une jointure sur deux tables situées dans deux bases distinctes :
Tableau 5-4 Sélection de bases
Instruction SQL
Création d’une table dans la base
...
SELECT col , bdnouvelle
...
col3
FROM testChap5, bdnouvelle
...
testUSE
...
testUSE
(col3 CHAR(5), col4 CHAR(4))
CHARACTER SET latin1;
INSERT INTO bdnouvelle
...
Insertion d’une ligne
...
Pour pouvoir changer ainsi une base, vous devez avoir le privilège ALTER sur la base
de données en question
...
ALTER DATABASE bdnouvelle2 DEFAULT CHARACTER SET cp850 ;
Suppression d’une base (DROP
DATABASE)
Pour pouvoir supprimer une base de données, vous devez posséder le privilège DROP sur la
base (ou au niveau global pour effacer toute base)
...
) et le répertoire contenus dans la base
...
Cette instruction retourne le nombre de tables qui on été supprimées (fichiers à l’extension
«
...
Disons à présent adios à la base « chinoise » :
q
DROP DATABASE bdnouvelle2;
Privilèges
Depuis le début du livre, nous avons parlé de privilèges
...
Un privilège (sous-entendu utilisateur) est un droit d’exécuter une
certaine instruction SQL (on parle de privilège système), ou un droit relatif aux données des
tables situées dans différentes bases (on parle de privilège objet)
...
Les privilèges système diffèrent sensiblement d’un SGBD à un autre
...
En revanche, on retrouvera les mêmes privilèges objet (exemple : autorisation de modifier la colonne
nomComp de la table Compagnie) qui sont attribués ou retirés par les instructions GRANT et
REVOKE
...
Ces privilèges sont
stockés dans la table mysql
...
q
Database level : privilèges s’appliquant à tous les objets d’une base de données en particulier
...
db et mysql
...
q
Table level : privilèges s’appliquant à la globalité d’une table d’une base de données en
particulier
...
tables_priv (exemple
d’attribution d’un privilège table : GRANT INSERT ON bdpaul
...
q
Column level : privilèges s’appliquant à une des colonnes d’une table d’une base de
données en particulier
...
columns_priv
(exemple d’attribution d’un privilège column : GRANT
UPDATE( nomComp )ON
bdpaul
...
q
Routine level : privilèges globaux ou au niveau d’une base (CREATE ROUTINE, ALTER
ROUTINE, EXECUTE, et GRANT) s’appliquant aux procédures cataloguées (étudiées au
chapitre 7)
...
procs_priv de la base
mysql (exemple d’attribution d’un privilège routine : GRANT EXECUTE ON PROCEDURE
bdpaul
...
Tables de la base mysql
Cinq tables de la base de données mysql suffisent à MySQL pour stocker les privilèges
(système et objet) de tous les utilisateurs
...
© Éditions Eyrolles
159
Partie I
SQL de base
Figure 5-3 Stockage des prérogatives
root possède tous les privilèges
sur une base / table / objet
root
Table user / db / host / tables_priv / columns_priv / procs _priv
+----------- +------ +------------- +-------- +-------- +------------- +----- | Host
| User | …
| droit1 | droit2 | familledroit1 |
…
+----------- +------ +----------- --+-------- +-------- +---------- -----+---| localhost | root |
|
Y
| Y
| Y
| …
| …
|
|
|
|
|
|
| …
|
|
|
|
|
|
| localhost | Paul |
|
N
| Y
| N
| …
+----------- +------ +------------- +-------- +-------- +------------ ---+----
Paul possède le privilège droit2
sur une base / table / objet
Paul
La colonne Db est en plus dans les tables host, tables_priv et columns_priv, car elle est
nécessaire pour désigner la base de données sur laquelle portera le droit ou la famille de droits
...
CREATE DATABASE bdpaul;
CREATE USER Paul@localhost IDENTIFIED BY 'iut';
Table mysql
...
Cette table est composée de 37 colonnes qui décrivent
les privilèges au niveau global du serveur
...
Privilèges objet (LMD) sur toutes les bases de données
La requête suivante extrait les prérogatives de Paul (et des autres)
...
SELECT Host, User, Select_priv, Insert_priv, Update_priv, Delete_priv
FROM mysql
...
Privilèges objet (LDD) sur toutes les bases de données
La requête suivante extrait les prérogatives à propos des instructions LDD
...
SELECT Host, User, Create_priv, Drop_priv,Index_priv, Alter_priv
FROM mysql
...
Pour l’instant, le
caractère 'N' étant dans toutes les colonnes, Paul ne peut ni créer un utilisateur (Create_
user_priv), ni transmettre des droits qu’il aura lui-même reçus (Grant_priv), ni lister les
bases de données existantes (Show_db_priv), et ce quelle que soit la base de données
...
user;
+-----------+------+------------------+------------+--------------+
| Host
| User | Create_user_priv | Grant_priv | Show_db_priv |
+-----------+------+------------------+------------+--------------+
| localhost | root | Y
| Y
| Y
|
| localhost |
| N
| Y
| Y
|
| %
|
| N
| N
| N
|
| N
| N
| localhost | Paul | N
|
+-----------+------+------------------+------------+--------------+
Privilèges à propos des vues sur toutes les bases de données
La requête suivante extrait les prérogatives à propos des instructions relatives aux vues (views
détaillées dans la section suivante)
...
© Éditions Eyrolles
161
Partie I
SQL de base
SELECT Host,User, Create_view_priv, Show_view_priv FROM mysql
...
Pour l’instant, le caractère 'N' étant dans toutes les colonnes, Paul ne
peut ni créer une procédure (Create_routine_priv), ni en modifier (Alter_routine_
priv), ni en exécuter (Execute_priv), et ce quelle que soit la base de données
...
user;
+-----------+------+---------------------+--------------------+--------------+
| Host
| User | Create_routine_priv | Alter_routine_priv | Execute_priv |
+-----------+------+---------------------+--------------------+--------------+
| localhost | root | Y
| Y
| Y
|
| localhost |
| N
| N
| Y
|
| %
|
| N
| N
| N
|
| localhost | Paul | N
| N
| N
|
+-----------+------+---------------------+--------------------+--------------+
Privilèges à propos des restrictions d’utilisateur
La requête suivante extrait les prérogatives à propos des restrictions qu’on peut définir par
accès
...
SELECT Host, User, max_questions "Requetes", max_updates
"Modifs" ,
max_connections "Connexions", max_user_connections "Cx simult
...
user;
+-----------+------+----------+--------+------------+------------+
| Host
| User | Requetes | Modifs | Connexions | Cx simult
...
user sont intéressantes, mais sortent un peu du cadre
de ce livre
...
Nul doute que vous saurez vous servir de ces privilèges en temps voulu, par analogie avec
ceux que nous allons étudier
...
Il permettrait de bénéficier de
l’intégrité référentielle entre deux tables appartenant à deux bases distinctes (par exemple la
table Avion dans bd1 ferait référence par clé étrangère à la table Compagnie dans bd2)
...
Attribution de privilèges (GRANT)
La figure suivante illustre le contexte qui va servir d’exemple à l’attibution de prérogatives
...
L’utilisateur qui exécute cette commande doit avoir reçu luimême le droit de transmettre ces privilèges (reçu avec la directive GRANT OPTION)
...
© Éditions Eyrolles
163
Partie I
SQL de base
GRANT privilège [ (col1 [, col2
...
]
ON [ {TABLE | FUNCTION | PROCEDURE} ]
{nomTable | * | *
...
*}
TO utilisateur [IDENTIFIED BY [PASSWORD] 'password']
[,utilisateur2
...
), voir le tableau suivant
...
GRANT OPTION : permet de donner le droit de retransmettre les privilèges reçus à une
tierce personne
...
q
Tableau 5-5 Privilèges principaux pour GRANT et REVOKE
privilege
Tous les privilèges
...
ALTER ROUTINE
Modification de procédure
...
CREATE ROUTINE
Création de procédure
...
CREATE VIEW
Création de vue
...
DROP
Suppression de base/table
...
INDEX
Création/Suppression d’index
...
SELECT
Extraction de données de table
...
SHOW VIEW
Lister les vues d’une base
...
UPDATE
Modification de données de table
...
© Éditions Eyrolles
chapitre n° 5
Contrôle des données
Exemples
Le tableau suivant décrit l’affectation de quelques privilèges en donnant les explications associées
...
*
TO 'Paul'@'localhost' ;
Privilège système database level :
Paul (en accès local) peut créer ou
supprimer des tables dans la base bdpaul
...
Livre
Paul peut insérer, extraire, supprimer et
TO 'Paul'@'localhost' ;
modifier la colonne ISBN de la table Livre
contenue dans la base bdpaul
...
Livre
TO 'Paul'@'localhost' ;
Privilège système table level :
Paul peut modifier la structure ou les
contraintes de la table Livre contenue
dans la base bdpaul
...
Livre
TO 'Jules'@'localhost'
WITH GRANT OPTION;
Privilège objet column level :
Jules peut extraire seulement la colonne
titre de la table Livre contenue dans la
base bdpaul
...
GRANT CREATE ON *
...
GRANT USAGE ON bdpaul
...
Tout ce que vous avez le droit de faire doit être explicitement autorisé par la commande GRANT
...
Par exemple, Jules peut créer des bases, mais
pas en détuire, Paul peut modifier le numéro ISBN d’un livre mais pas son titre, etc
...
C’est bien utile quand vous avez attribué un certain nombre
de privilèges à un utilisateur sans avoir pensé à les consigner dans un fichier de commande
...
J’avoue avoir un peu retravaillé l’état de sortie (sans en modifier une
ligne quand même)
...
* TO 'Jules'@'localhost' IDENTIFIED BY PASSWORD
'*6AE163FB9EE8BB011EB2E87316AA5BE563A6CDB7' WITH MAX_QUERIES_PER_HOUR 50
MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 6 MAX_USER_CONNECTIONS 3 |
| GRANT SELECT (titre) ON `bdpaul`
...
Par là même, on se rend compte que les prérogatives de
connexion sont au niveau global, bien qu’on les ait spécifiées au niveau database
...
* TO 'Paul'@'localhost' IDENTIFIED BY PASSWORD
'*6AE163FB9EE8BB011EB2E87316AA5BE563A6CDB7'
|
| GRANT CREATE, DROP ON `bdpaul`
...
`Livre`
TO 'Paul'@'localhost'
|
+---------------------------------------------------------------------------+
On remarque que MySQL a regroupé tous les privilèges sur la table Livre en une instruction
GRANT
...
SHOW GRANTS FOR 'root'@'localhost';
+---------------------------------------------------------------------------+
| Grants for root@localhost
|
+---------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *
...
*), avec en prime la clause GRANT OPTION qui
permet de retransmettre n’importe quoi à n’importe qui, ou de tout révoquer
...
Le droit de création en local de Jules apparaît sur toutes les bases
...
user;
+-----------+-------+-------------+-----------+------------+------------+
| Host
| User | Create_priv | Drop_priv | Index_priv | Alter_priv |
+-----------+-------+-------------+-----------+------------+------------+
| …
| localhost | Paul | N
| N
| N
| N
|
| localhost | Jules | Y
| N
| N
| N
|
+-----------+-------+-------------+-----------+------------+------------+
Les colonnes suivantes permettent de stocker les restrictions sur les connexions
...
"
FROM mysql
...
|
+-----------+-------+----------+--------+------------+------------+
| …
| localhost | Paul |
0 |
0 |
0 |
0 |
50 |
20 |
6 |
3 |
| localhost | Jules |
+-----------+-------+----------+--------+------------+------------+
Analysons les autres tables de la base mysql pour découvrir les prérogatives des autres
niveaux (database, table, column et routine)
...
db
La table mysql
...
Ainsi la colonne Db indique la
base de données
...
db;
+-----------+------+---------+-------------+-----------+------------+
| Host
| User | Db
| Create_priv | Drop_priv | Alter_priv |
+-----------+------+---------+-------------+-----------+------------+
| %
|
| test\_% | Y
| Y
| Y
|
| %
|
| test
| Y
| Y
| Y
|
| Y
| N
| localhost | Paul | bdpaul | Y
|
+-----------+------+---------+-------------+-----------+------------+
Notez la possibilité de Paul, avec l’accès local, de créér et de supprimer des tables dans la
base bdpaul
...
Table mysql
...
© Éditions Eyrolles
167
Partie I
SQL de base
Table mysql
...
tables_priv décrit les prérogatives objet au niveau table
...
La colonne Table_priv est un SET contenant la liste des droits de
l’utilisateur sur la table
...
',Table_name) "Objet", Grantor, Table_priv
FROM mysql
...
Livre | root@localhost | Grant
|
| Paul@localhost | bdpaul
...
Cette table possède aussi une colonne de nom Timestamp stockant l’instant au cours duquel
s’est déroulée l’attribution (ou la révocation)
...
columns_priv
La table mysql
...
Ainsi la
colonne Table_name indique la table concernée, la colonne Column_name précise la
colonne concernée par le droit
...
SELECT CONCAT(User,'@',Host) "Compte", CONCAT(Db,'
...
columns_priv;
+-----------------+--------------+-------------+-------------+
| Compte
| Objet
| Column_name | Column_priv |
+-----------------+--------------+-------------+-------------+
| Jules@localhost | bdpaul
...
Livre | ISBN
| Update
|
+-----------------+--------------+-------------+-------------+
On retrouve le privilège de Paul et celui de Jules (portant ici sur la même table)
...
procs_priv
La table mysql
...
168
© Éditions Eyrolles
chapitre n° 5
Contrôle des données
Les privilèges CREATE ROUTINE, ALTER ROUTINE, EXECUTE, et GRANT s’appliquent sur
les sous-programmes catalogués et peuvent être attribués au niveau global et database
...
En supposant que la base bdpaul contient la procédure cataloguée sp1() et la fonction
sp2(), toutes deux écrites par root, le tableau suivant exprime l’affectation de quelques
privilèges en donnant les explications associées
...
*
TO 'Paul'@'localhost';
Privilège système database level :
Paul (en accès local) peut créer ou supprimer
des sous-programmes catalogués dans la base
bdpaul
...
sp1
TO 'Paul'@'localhost';
GRANT EXECUTE ON PROCEDURE bdpaul
...
Privilèges système routine level :
Jules peut exécuter la procédure sp1 et la
fonction sp2 contenues dans la base bdpaul
...
sp2
TO 'Jules'@'localhost';
La colonne Routine_name de la table mysql
...
La colonne Routine_type précise le type du sous-programme catalogué (fonction ou procédure)
...
La colonne Proc_priv est un SET contenant la liste des droits de l’utilisateur sur le sous-programme de la base
...
SELECT CONCAT(User,'@',Host) "Compte", Db,
Create_routine_priv "create routine", Alter_routine_priv "alter routine",
Execute_priv "exec
...
db;
+----------------+---------+----------------+---------------+---------------+
| Compte
| Db
| create routine | alter routine | exec
...
Extrayons enfin les privilèges relatifs aux sous-programmes
au niveau routine
...
',Routine_name,':',Routine_type) "Objet",
Grantor, Proc_priv FROM mysql
...
sp1:PROCEDURE | root@localhost | Execute
|
| Jules@localhost | bdpaul
...
sp1:PROCEDURE | root@localhost | Alter Routine |
+-----------------+----------------------+----------------+---------------+
On retrouve le privilège en modification de sp1 pour Paul, et les deux privilèges d’exécution
de Jules
...
Pour
pouvoir révoquer un privilège, vous devez détenir (avoir reçu) au préalable ce même privilège
avec l’option WITH GRANT OPTION
...
REVOKE privilège [ (col1 [, col2
...
]
ON [ {TABLE | FUNCTION | PROCEDURE} ]
{nomTable | * | *
...
*}
FROM utilisateur [,utilisateur2
...
Tableau 5-8 Révocation de privilèges
Instruction faite par root
REVOKE CREATE
ON bdpaul
...
REVOKE ALTER,INSERT,UPDATE(ISBN)
ON bdpaul
...
GRANT USAGE ON bdpaul
...
Ici c’est un GRANT qu’il
faut faire, car il s’agit plus d’une restriction de connexion
que d’une instruction SQL
...
Les colonnes SET des tables mysql
...
columns_priv et mysql
...
Ainsi,
l’extraction du profil actuel de Paul au niveau table fait apparaître les deux seuls droits qu’il
lui reste
...
',Table_name)
"Objet",
Grantor, Table_priv FROM mysql
...
Livre | root@localhost | Select,Delete |
+----------------+--------------+----------------+---------------+
L’extraction du profil actuel de Jules au niveau database fait apparaître que les deux limitations de connexion sur les SELECT et UPDATE ont disparu
...
"
FROM mysql
...
|
+-----------+-------+----------+--------+------------+------------+
0 |
0 |
| localhost | Jules |
6 |
3 |
+-----------+-------+----------+--------+------------+------------+
Tout en une fois !
Il existe une instruction qui révoque tous les droits en une fois
...
Pensez
quand même à sauvegarder au préalable le profil de Jules (SHOW GRANT FOR) pour
pouvoir le faire travailler de nouveau quand vous serez calmé
...
Et les privilèges routine, me direz-vous ?
Ils ont dû l’oublier dans la documentation, mais ils sont aussi effacés, ne vous inquiétez pas, je
l’ai testé
...
] ;
Pour pouvoir annihiler ainsi un utilisateur, il faut détenir le privilège CREATE USER au niveau
global ou le privilège UPDATE au niveau database sur la base mysql
...
Par
analogie, les politiciens qui se voient retirer le droit de vote ne sont pas encore guillotinés (que
je sache)
...
Ici mon billet d’humeur conteste la possibilité qui est donnée de modifier les
cinq tables de la base mysql pour affecter tantôt un 'N' par-ci, tantôt un 'Y' par-là, ou encore
pour mettre à jour un SET contenant SELECT par exemple, etc
...
Vous pouvez vousmême empêcher toute connexion (même celle du root)
...
C’est heureux
...
Ensuite
parce si vous voulez « bidouiller », allez consulter des sites Web ou d’autres ouvrages qui
recopient la documentation sans quelquefois changer ni tester les exemples, vous m’en direz
des nouvelles
...
• Les deux instructions sont dans la norme SQL
...
La seule utilisation acceptable, parce qu’on n’a pas le choix de faire autrement, concerne la
mise à jour de la table mysql
...
À configuration avancée, programmeur averti
...
Un client est en 192
...
4
...
Un
serveur est en 192
...
4
...
Sur le serveur, root crée
172
© Éditions Eyrolles
chapitre n° 5
Contrôle des données
un accès à Paul, en précisant l’adresse de la machine client, et lui attribue un droit d’extraction de la table Livre sur la base bdPaul
...
168
...
173 IDENTIFIED BY 'pauldistant';
GRANT SELECT ON bdpaul
...
168
...
173';
Figure 5-5 Accès distant par l’interface de commande MySQL
TCP-IP
192
...
4
...
168
...
173
root@localhost
root
Paul@localhost
Paul@192
...
4
...
Livre
mysql
...
Pensez à enlever les
pare-feu Windows sur le client et le serveur (bloquant le port 3306)
...
168
...
118 -u Paul -p
Paul peut, à présent seulement, interroger la table distante, comme le montre la copie d’écran
suivante :
Figure 5-6 Interrogation distante par l’interface de commande MySQL
Table mysql
...
host est utilisée conjointement avec mysql
...
Cette table n’est employée que pour les prérogatives au niveau
© Éditions Eyrolles
173
Partie I
SQL de base
database, indépendamment des utilisateurs
...
db,
à l’exception de la colonne User qui n’est pas présente
...
Tableau 5-9 Tables pour les accès distants
Signification pour mysql
...
host
colonne Host
colonne Db
colonne Host
colonne Db
%
toute machine
toute base
toute machine
toute base
' ' (chaîne
vide)
consultez la table
mysql
...
Pour les opérations relatives aux
bases (INSERT, UPDATE, etc
...
Si l’accès n’y est pas décrit,
la recherche se poursuit dans les tables db et host
...
Si la colonne Host de la table db n’est pas renseignée (' '), cela signifie que la table host
énumère les machines qui sont autorisées à accéder à une base de données en particulier
...
Dans le cas contraire, les privilèges sont
valués à 'Y' à partir d’une intersection (et pas d’une union) entre les tables db et host sur le
couple (Host, Db)
...
host n’est mise à jour ni par GRANT, ni par REVOKE
...
Elle n’est pas utilisée par la plupart des serveur MySQL, car elle est dédiée à des usages très
spécifiques (pour gérer un ensemble de machines à accès sécurisé, par exemple)
...
En supposant que vous déclariez une machine à accès non sécurisé : camparols
...
fr
...
Ceci en
ajoutant des enregistrements par INSERT dans la table mysql
...
+------------------+----+----------------------------| camparols
...
fr | % | (tous les privilèges à 'N')
| %
...
fr
| % | (tous les privilèges à 'Y')
+------------------+----+-----------------------------
Vous déclareriez l’inverse des conditions initiales en remplaçant les 'N' par des 'Y', et réciproquement
...
174
© Éditions Eyrolles
chapitre n° 5
Contrôle des données
Vues
Outre le contrôle de l’accès aux données (privilèges), la confidentialité des informations est un
aspect important qu’un SGBD relationnel doit prendre en compte
...
Cette section décrit les différents types de vues qu’on peut rencontrer
...
Seules les tables contiennent des données et, pourtant, pour l’utilisateur, une vue apparaît
comme une table
...
Ces dernières masquant la structure des tables interrogées
...
La figure suivante illustre ce qui a été dit en présentant trois utilisateurs
...
Figure 5-7 Les vues
Jules
Paul
Vue2
Vue1
Louise
Vue3
schéma1
schéma2
Niveau externe
Niveau physique
Table2
Table1
Vue1
Vue2
Vue3
Une vue est considérée comme une table virtuelle car elle n’a pas d’existence propre
...
Ses données seront extraites de la mémoire à partir
des tables source, à la demande
...
Cette
requête interroge une (ou plusieurs) table(s) ou vue(s)
...
Outre le fait d’assurer la confidentialité des informations, une vue est capable de réaliser des
contrôles de contraintes d’intégrité et de simplifier la formulation de requêtes complexes
...
Attribuées comme des privilèges (GRANT), les vues améliorent la sécurité des informations stockées
...
La
syntaxe SQL de création d’une vue est la suivante :
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW [nomBase
...
Vous devez avoir le privilège DELETE sur la base
pour bénéficier de cette directive
...
q
ALGORITHM=TEMPTABLE : les résultats sont extraits dans une table temporaire (TEMPORARY) qui est utilisée par la suite
...
q
Aucune option ou ALGORITHM=UNDEFINED : MySQL choisit la politique à adopter,
souvent en faveur de MERGE, la seule qui convient aux vues modifiables
...
En l’absence de ce
paramètre, la vue est créée dans la base en cours d’utilisation
...
• La requête de définition ne peut interroger une table temporaire, ni contenir de paramètres
ou de variables de session
...
Il faudra recréer la vue pour prendre en compte
l’évolution structurelle de l’objet source
...
q
176
Les paramètres LOCAL et CASCADED (par défaut) determinent la portée de la vérification
quand une vue est définie à partir d’une autre vue
...
CASCADED permet d’étendre éventuellement les vérifications aux
autres vues source de la vue qui vient d’être définie
...
Le tableau suivant résume ce que nous allons détailler au cours de cette section :
Tableau 5-10 Classification des vues
Requête de définition
Vue simple
Vue complexe
Nombre de tables
1
1 ou plusieurs
Fonction
non
oui
Regroupement
non
oui
Mises à jour possibles ?
oui
pas toujours
Une vue monotable est définie par une requête SELECT ne comportant qu’une seule table dans
sa clause FROM
...
Considérons les deux vues illustrées par la figure suivante et dérivées de
la table Pilote
...
La vue Etat_civil est constituée par une projection de certaines
colonnes (éléments du SELECT)
...
Le tableau
suivant présente une interrogation des deux vues :
© Éditions Eyrolles
177
Partie I
SQL de base
Tableau 5-11 Interrogation d’une vue
Web
Besoin et requête
Somme des heures de vol des pilotes d'Air France
...
SELECT COUNT(*) FROM Etat_civil;
Résultat
+-------------+
| SUM(nbHVol) |
+-------------+
|
1700
...
Alias
Les alias, s’ils sont utilisés, désignent le nom de chaque colonne de la vue
...
Quand un alias n’est pas présent, la colonne
prend le nom de l’expression renvoyée par la requête de définition
...
Les vues suivantes sont créées avec des alias qui masquent le nom des colonnes de la table
source
...
Tableau 5-12 Vue avec alias
Web
Écriture 1
Écriture 2
CREATE OR REPLACE VIEW
CREATE OR REPLACE VIEW
PilotesPasAF
PilotesPasAF
( codepil,nomPil,heuresPil,
AS SELECT brevet codepil, nom nomPil ,
nbHVol heuresPil , adresse adressePil,
adressePil, societe )
AS SELECT *
compa societe
FROM Pilote
FROM Pilote
WHERE NOT (compa = 'AF');
WHERE NOT (compa = 'AF');
Contenu de la vue : +---------+---------+-----------+------------+---------+
| codepil | nomPil | heuresPil | adressePil | societe |
+---------+---------+-----------+------------+---------+
| PL-1
| Soutou |
890
...
00 | Montauban | CAST
|
| PL-5
| Bidal
|
120
...
00 | Pau
| ASO
|
| PL-7
| Tauzin |
100
...
La vue
suivante est définie à partir de la vue PilotesPasAF précédemment créée
...
178
© Éditions Eyrolles
chapitre n° 5
Contrôle des données
Tableau 5-13 Vue d’une vue
Création
Web
CREATE OR REPLACE VIEW
EtatCivilPilotesPasAF
AS SELECT nomPil,heuresPil,adressePil
FROM PilotesPasAF ;
Contenu de la vue
+---------+-----------+------------+
| nomPil | heuresPil | adressePil |
+---------+-----------+------------+
| Soutou |
890
...
00 | Montauban |
| Bidal
|
120
...
00 | Pau
|
| Tauzin |
100
...
Redéfinissons une vue des pilotes n’étant pas d’Air France à l’aide de cette option
...
Tableau 5-14 Vue en lecture seule
Création
Web
CREATE OR REPLACE
ALGORITHM=TEMPTABLE
VIEW
PilotesPasAFRO
AS
SELECT *
FROM Pilote
WHERE NOT (compa = 'AF');
Opérations impossibles
INSERT INTO PilotesPasAFRO
VALUES ('PL-8','Ferry',5,'Paris','ASO');
ERROR 1288 (HY000): The target table
PilotesPasAFRO of the INSERT is not updatable
UPDATE PilotesPasAFRO SET nbHvol=nbHvol+2;
ERROR 1288 (HY000): The target table
PilotesPasAFRO of the UPDATE is not updatable
DELETE FROM PilotesPasAFRO;
ERROR 1288 (HY000): The target table
PilotesPasAFRO of the DELETE is not updatable
Vues modifiables
Lorsqu’il est possible d’exécuter des instructions INSERT, UPDATE ou DELETE sur une vue,
cette dernière est dite « modifiable » (updatable view)
...
Pour mettre à jour une vue, il doit exister une correspondance biunivoque entre les lignes de la
vue et celles de l’objet source
...
Si une vue n’est pas modifiable en soi, il n’est pas encore possible de programmer un déclencheur de type instead of qui prenne le pas sur l’instruction de modification de la vue, en spécifiant un bloc d’instructions à effectuer à la place
...
Notons que ce type de
déclencheur n’est arrivé qu’assez tardivement sous Oracle, DB2 et SQL Server
...
Dans notre exemple, nous constatons qu’il sera quand même possible d’ajouter un pilote à la vue
Etat_civil, bien que la clé primaire de la table source ne soit pas renseignée
...
Cette opération ne pourra donc se faire
qu’une seule fois, après, cela sera contradictoire avec la condition de correspondance biunivoque
...
On pourra aussi ajouter,
modifier (sous réserve de respecter les éventuelles contraintes issues des colonnes de la table
source), ou supprimer des pilotes en passant par la vue PilotesAF
...
La directive WITH CHECK
OPTION permet d’éviter ces effets de bord indésirables pour l’intégrité de la base
...
('PL-8','Ferry',5, 'Paris','AF');
Modification
UPDATE PilotesAF SET nbHVol = nbHVol*2;
Suppression
DELETE FROM PilotesAF WHERE nom='Ferry';
Ajout d’un pilote qui n’est pas de 'AF' !
INSERT INTO PilotesAF VALUES
('PL-9','Caboche', 600,'Rennes','ASO');
180
© Éditions Eyrolles
chapitre n° 5
Contrôle des données
Directive CHECK OPTION
La directive WITH CHECK OPTION empêche un ajout ou une modification non conformes à la
définition de la vue
...
Il est nécessaire de
redéfinir la vue PilotesAF
...
Les messages sont très clairs
...
PilotesAF'
Nouveau pilote
INSERT INTO PilotesAF VALUES
('PL-11','Teste',900,'Revel','AF');
Query OK, 1 row affected (0
...
PilotesAF'
Vues complexes
Une vue complexe est caractérisée par le fait qu’elle contient, dans sa définition, plusieurs
tables (jointures) et une fonction appliquée à des regroupements ou à des expressions
...
Pour pouvoir modifier une vue complexe, les restrictions sont les suivantes :
• La requête de définition ne doit pas contenir de sous-interrogation (jointure procédurale)
...
La figure suivante présente deux vues complexes qui ne sont pas modifiables
...
La vue Moyenne_Heures_Pil est créée à partir d’un regroupement de la table
Pilote
...
brevet, p
...
nbHVol, c
...
nomComp
FROM Pilote p, Compagnie c
WHERE p
...
comp AND p
...
Les messages d’erreur générés par MySQL
sont différents suivant la nature de la vue (monotable ou multitable)
...
Tableau 5-17 Tentatives d’insertions dans des vues complexes
Web
Vue monotable
Vue multitable
INSERT INTO Moyenne_Heures_Pil
VALUES ('TAT',50);
ERROR 1288 (HY000): The target
table Moyenne_Heures_Pil of the
INSERT is not updatable
INSERT INTO Pilotes_multi_AF VALUES
('PL-4','Test',400,'Castanet','Castanet AL');
ERROR 1394 (HY000): Can not insert into join
view 'bdsoutou
...
Ce n’est pas le cas
...
Nous verrons dans le prochain paragraphe la signification de cette notion
...
Ici, nbHVol peut être mise à jour car elle appartient à la table protégée ;
ville qui n’appartient pas à une table protégée peut aussi être modifée !
Les suppressions ne se répercutent pas sur les enregistrements de la table protégée par clé
(Pilote)
...
Tableau 5-18 Mise à jour d’une vue multitable
Web
Mise à jour
Résultats
-- Multiplie par 2 le nombre d’heures
UPDATE Pilotes_multi_AF
SET nbHVol = nbHVol * 2;
SELECT brevet,nom,nbHVol
FROM Pilotes_multi_AF;
+--------+-------------+---------+
| brevet | nom
| nbHVol |
+--------+-------------+---------+
| PL-1
| Louise Ente | 900
...
00 |
+--------+-------------+---------+
Query OK, 2 rows affected
Rows matched: 2 Changed: 2 Warnings: 0
-- Modif de la ville de la compagnie
UPDATE Pilotes_multi_AF
SET ville = 'Orly';
SELECT brevet,nom,ville
FROM Pilotes_multi_AF;
+--------+-------------+-------+
| brevet | nom
| ville |
+--------+-------------+-------+
| PL-1
| Louise Ente | Orly |
| PL-2
| Paul Ente
| Orly |
+--------+-------------+-------+
SELECT comp,ville,nomComp
FROM Compagnie;
+------+-----------+--------------+
| comp | ville
| nomComp
|
+------+-----------+--------------+
| AF
| Orly
| Air France
|
| SING | Singapour | Singapore AL |
+------+-----------+--------------+
--Pas possible :
DELETE FROM Pilotes_multi_AF ;
© Éditions Eyrolles
ERROR 1395 (HY000): Can not delete
from join view 'bdsoutou
...
En considérant les données initiales pour la vue multitable Vue_Multi_Comp_Pil, la table
préservée est la table Pilote, car la colonne brevet identifie chaque enregistrement extrait
de la vue, alors que la colonne comp ne le fait pas
...
comp,
c
...
brevet , p
...
nbHVol
FROM Pilote p,
Compagnie c
WHERE p
...
comp;
+------+--------------+--------+-------------+---------+
| comp | nomComp
| brevet | nom
| nbHVol |
+------+--------------+--------+-------------+---------+
| AF
| Air France
| PL-1
| Louise Ente | 450
...
00 |
| SING | Singapore AL | PL-3
| Paul Soutou | 1000
...
Étudions à présent les conditions qui régissent ces limitations
...
Aucune suppression n’est possible
...
Attention aux effets de bord quand vous modifiez une colonne provenant d’une table non protégée par clé
...
Modifions de différentes manières la vue multitable Vue_Multi_Comp_Pil
...
Les deux dernières instructions insèrent dans
chacune des deux tables
...
Vue_Multi_Comp_Pil'
UPDATE Vue_Multi_Comp_Pil
SET nbHVol = nbHVol * 3;
Query OK, 3 rows affected (0
...
00 |
| PL-2
| 2700
...
00 |
+--------+---------+
(SELECT comp,ville,nomComp
UPDATE Vue_Multi_Comp_Pil
FROM Compagnie;
SET nomComp = 'Dupond';
+------+-----------+---------+
Query OK, 2 rows affected (0
...
00 |
| PL-2
| Paul Ente
| 2700
...
00 |
| PL-5
| Jean
| 2500
...
© Éditions Eyrolles
185
Partie I
SQL de base
Simplifier les noms
Une vue permet de simplifier la manipulation d’une table ayant un nom long ou des colonnes
portant des noms compliqués
...
Nous étudierons dans la prochaine
section les différentes tables de cette base système
...
Créons la vue CollationsLatines qui simplifie l’accès à cette table au niveau du nom,
mais aussi au niveau des colonnes
...
Tableau 5-21 Vue pour simplifier les noms
Web
Création
CREATE VIEW CollationsLatines
(collation,jeu)
AS SELECT * FROM INFORMATION_SCHEMA
...
Aucun french dans la base, donc
...
Il est possible de programmer ce type de contraintes par des vues
...
Les règles conseillées pour manipuler les enregistrements d’une vue v1 décrivant des contraintes de vérification sur une table t1 sont les suivantes :
• modification et insertion par la vue v1 ;
• suppression et lecture par la table t1
...
VueGradePilotes'
INSERT INTO VueGradePilotes
(brevet,nom,nbHVol,grade) VALUES
('PL-1','Daniel Vielle', 1000,'CDB' );
INSERT INTO VueGradePilotes
(brevet,nom,nbHVol,grade) VALUES
('PL-2','Benoit Treihlou', 450,'COPI' );
INSERT INTO VueGradePilotes
(brevet,nom,nbHVol,grade) VALUES
('PL-3','Pierre Filoux', 9000,'INST'
);
INSERT INTO VueGradePilotes
(brevet,nom,nbHVol,grade) VALUES
('PL-4','Philippe Minier', 1000,'COPI');
INSERT INTO VueGradePilotes
(brevet,nom,nbHVol,grade)VALUES
('PL-5','Trop jeune', 100,'CDB' );
INSERT INTO VueGradePilotes
(brevet,nom,nbHVol,grade) VALUES
('PL-6',
'Inexperimente', 2999,'INST');
UPDATE VueGradePilotes
SET grade ='CDB'
WHERE brevet = 'PL-4';
Web
UPDATE VueGradePilotes
SET nbHVol= 50
WHERE brevet = 'PL-3';
UPDATE VueGradePilotes
SET grade ='INST'
WHERE brevet = 'PL-2';
Confidentialité
La confidentialité est une des vocations premières des vues
...
Les vues suivantes limitent temporellement les accès en lecture et en écriture à des tables
...
© Éditions Eyrolles
187
Partie I
SQL de base
Tableau 5-23 Vues pour restreindre l’accès à des moments précis
Web
Définition de la vue
Accès
CREATE VIEW VueDesCompagniesJoursFeries Restriction en lecture de la table Compagnie, les
AS SELECT * FROM Compagnie
samedis et dimanches
...
IN ('Sunday','Saturday');
CREATE VIEW VueDesPilotesJoursOuvrables Restriction, en lecture et en écriture (à cause de
AS SELECT * FROM Pilote
WITH CHECK OPTION), de la table Pilote les
WHERE CURTIME()+0
jours ouvrables de 8h30 à 17h30
...
Ainsi, si un utilisateur désire transmettre des droits sur une partie
d’une de ses tables, il utilisera une vue
...
Les privilèges objet qu’il est possible d’attribuer sur une vue sont les mêmes que ceux applicables sur les tables (SELECT, INSERT, UPDATE sur une ou plusieurs colonnes, DELETE)
...
GRANT INSERT ON VueDesPilotesJoursOuvrables
TO 'Jules'@'localhost';
Accès en local de l’utilisateur Jules en
écriture sur la vue
VueDesCompagniesJoursFériés
...
La syntaxe SQL est la suivante :
ALTER [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW [nomBase
...
Voir la section Création d’une vue
...
]nomVue;
En arrangeant l’état de sortie, vous pouvez découvrir comment MySQL stocke la définition de
la vue précédemment créée :
SHOW CREATE VIEW VueDesCompagniesJoursFeries;
+-----------------------------+-----------------------------------------------+
| View
| Create View
|
+-----------------------------+-----------------------------------------------+
| VueDesCompagniesJoursFeries | CREATE ALGORITHM=UNDEFINED
|
|
| DEFINER=`root`@`localhost` SQL SECURITY
|
|
| DEFINER VIEW `VueDesCompagniesJoursFeries` AS |
|
| select sql_no_cache `Compagnie`
...
`nrue` AS
|
|
| `nrue`,`Compagnie`
...
`ville` AS
|
|
| `ville`,`Compagnie`
...
La suppression d’une vue n’entraîne pas la destruction des données qui résident toujours dans
les tables
...
]nomVue [,nomBase2
...
[RESTRICT | CASCADE];
q
IF EXISTS évite une erreur dans le cas où la vue n’existe pas
...
© Éditions Eyrolles
189
Partie I
SQL de base
Dictionnaire des données
Le dictionnaire des données (metadata ou data dictionary) est une partie majeure d’une base
de données MySQL qu’on peut assimiler à une structure centralisée
...
Ces vues, qui sont appelées
tables par abus de langage (dans la documentation officielle, dans les livres et sur les forums1)
et qui sont situées dans la base INFORMATION_SCHEMA, suffisent à stocker toutes les
informations décrivant tous les objets contenus dans toutes les bases de données
...
Les
noms des vues sont similaires et se rapprochent de la spécification ANSI/ISO SQL:2003
standard Part 11 Schemata
...
Toutes les tables du dictionnaire des données ne sont accessibles qu’en lecture seulement
...
L’interrogation du dictionnaire des données est permise à tout utilisateur (qui ne verra que les objets qui lui sont toutefois accessibles avec ses propres privilèges) et peut se faire au travers de requêtes SELECT ou
par le biais de la commande SHOW
...
Le dictionnaire des données est mis automatiquement à jour après chaque instruction SQL du
LMD (INSERT, UPDATE, DELETE, LOCK TABLE)
...
Je conserve le vocable de « vue » pour être plus près de la réalité
...
190
© Éditions Eyrolles
chapitre n° 5
Contrôle des données
q
Conforme aux règles d’E
...
Codd (le père du modèle relationnel) ; toutes les manipulations sont réalisées à l’aide des opérateurs relationnels sur des tables
...
La migration vers un autre SGBD est ainsi facilitée
...
q
Vous avez tellement souffert au chapitre 4, que vous avez ici l’occasion de mettre à
l’épreuve vos connaissances dans un contexte plus « système »
...
com, décrit la structure des vues du dictionnaire des données
...
Recherche du nom d’une vue
Il n’y a pas de moyen automatique de trouver le nom de la vue pertinente
...
Choisir les colonnes
Le choix des colonnes d’une vue du dictionnaire des données s’effectue après avoir listé la
structure de cette vue (par DESCRIBE)
...
Dans notre exemple, la vue contient huit colonnes
...
La colonne CHECK_OPTION
doit indiquer en principe le fait que la vue est déclarée avec une contrainte de vérification
...
VIEWS;
+-----------------+--------------+------+-----+---------+-------+
| Field
| Type
| Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+-------+
| TABLE_CATALOG
| varchar(512) | YES |
| NULL
|
|
| TABLE_SCHEMA
| varchar(64) | NO
|
|
|
|
| TABLE_NAME
| varchar(64) | NO
|
|
|
|
| VIEW_DEFINITION | longtext
| NO
|
|
|
|
| CHECK_OPTION
| varchar(8)
| NO
|
|
|
|
| IS_UPDATABLE
| varchar(3)
| NO
|
|
|
|
| DEFINER
| varchar(77) | NO
|
|
|
|
| SECURITY_TYPE
| varchar(7)
| NO
|
|
|
|
+-----------------+--------------+------+-----+---------+-------+
Interroger la vue
L’interrogation de la vue sur les colonnes choisies est l’étape finale de la recherche de données
dans le dictionnaire
...
Ces données sont en fait contenues dans des tables
système qui ne sont pas accessibles pour des raisons sécuritaires
...
VIEWS;
+--------------+-----------------------------+--------------+
| TABLE_SCHEMA | TABLE_NAME
| CHECK_OPTION |
+--------------+-----------------------------+--------------+
| bdnouvelle
| VueDesSocietes
| NONE
|
| bdsoutou
| VueDesPilotesJoursOuvrables | CASCADED
|
+--------------+-----------------------------+--------------+
Si j’avais voulu connaître les vues contenues seulement dans la base bdsoutou, il suffisait
d’ajouter la condition (WHERE TABLE_SCHEMA='bdsoutou')
...
q
La colonne TABLE_NAME pour stocker le nom de chaque vue des différents schémas
...
q
La colonne CHECK_OPTION pour indiquer le caractère restreint de chaque vue (la
première n’est pas restreinte, la seconde l’est)
...
Notez qu’aucune redondance ni
de synonyme n’existent (si vous voulez réaliser une extraction pour découvrir quelque chose,
il n’y aura pas beaucoup de requêtes différentes possibles)
...
CHARACTER_SETS : informations sur les colonnes pour lesquelles l’utilisateur a reçu une autorisation
...
Privilèges
SCHEMA_PRIVILEGES : liste des prérogatives au niveau database
...
USER_PRIVILEGES : liste des prérogatives au niveau user
...
Tables et séquences
TABLES : caractéristiques des tables (et séquences) dans les bases
...
Index
STATISTICS : description des index
...
KEY_COLUMN_USAGE : composition des contraintes (colonnes)
...
Sous-programmes
ROUTINES : description des sous-programmes stockés
...
Interrogeons à présent quelques-unes de ces vues dans le cadre d’exemples concrets
...
SELECT SCHEMA_NAME AS 'Base de donnees',
DEFAULT_CHARACTER_SET_NAME AS 'Jeu caracteres',
DEFAULT_COLLATION_NAME AS 'Collation'
FROM INFORMATION_SCHEMA
...
Le dictionnaire est lui-même codé en utf8
...
Les colonnes CATALOG_NAME et SQL_PATH ne sont pas encore renseignées
...
La première est relative au concept de
schéma (qu’on peut assimiler à une collection de bases), et la seconde concerne un nom symbolique qu’on pourrait associer à une routine (sous-programme)
...
SELECT TABLE_SCHEMA,TABLE_NAME, TABLE_TYPE,DATE(CREATE_TIME)
FROM INFORMATION_SCHEMA
...
q
la colonne CREATE_TIME pour désigner la date de création de l’objet
...
La requête suivante extrait des
informations intéressantes
...
TABLES
WHERE TABLE_SCHEMA = 'bdsoutou' AND TABLE_NAME='Installer';
+--------+----------------+------------+----------------+-------------+
| ENGINE | AUTO_INCREMENT | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH |
+--------+----------------+------------+----------------+-------------+
| InnoDB |
15 |
14 |
1170 |
16384 |
+--------+----------------+------------+----------------+-------------+
Notez que MySQL utilise :
q
la colonne ENGINE pour désigner le type de moteur de stockage de la table en question
...
q
la colonne TABLE_ROWS pour donner le nombre d’enregistrements de la table (ici c’est
bien cohérent avec la séquence qui fait office de clé primaire)
...
q
la colonne DATA_LENGTH pour désigner la taille de la table en octets
...
q
TABLE_COMMENT qui renseigne notamment à propos des références entre tables par les
clés étrangères
...
Structure au premier niveau
La requête suivante décrit en partie la table Installer
...
SELECT COLUMN_NAME,DATA_TYPE,ORDINAL_POSITION,COLUMN_DEFAULT,COLUMN_KEY
FROM INFORMATION_SCHEMA
...
q
DATA_TYPE pour donner le typeMySQL
...
q
COLUMN_DEFAULT pour préciser la valeur par défaut de chaque colonne
...
Extraction des colonnes caractères
La requête suivante décrit en détail les colonnes chaînes de caractères de la table Installer
...
COLUMNS
WHERE TABLE_SCHEMA = 'bdsoutou' AND TABLE_NAME='Installer'
AND NUMERIC_PRECISION IS NULL
AND DATA_TYPE NOT IN ('timestamp','time','date');
+-------------+-----------+------------+-------------+
| COLUMN_NAME | DATA_TYPE | Taille max | IS_NULLABLE |
+-------------+-----------+------------+-------------+
| nPoste
| varchar
|
7 | YES
|
| nLog
| varchar
|
5 | YES
|
+-------------+-----------+------------+-------------+
Vous pouvez noter que MySQL utilise :
q
q
IS_NULLABLE pour renseigner le fait qu’une colonne puisse être nulle
...
Extraction des colonnes numériques
La requête suivante détaille les colonnes numériques de la table Installer
...
COLUMNS
WHERE TABLE_SCHEMA = 'bdsoutou' AND TABLE_NAME='Installer'
AND CHARACTER_MAXIMUM_LENGTH IS NULL
AND DATA_TYPE NOT IN ('timestamp','time','date');
+-------------+-----------+------------+-----------+
| COLUMN_NAME | DATA_TYPE | Taille max | Précision |
+-------------+-----------+------------+-----------+
| numIns
| int
|
10 |
0 |
+-------------+-----------+------------+-----------+
© Éditions Eyrolles
197
Partie I
SQL de base
Vous pouvez notez que MySQL utilise :
q
NUMERIC_PRECISION pour renseigner la taille des numériques pour chaque colonne
...
Extraction des colonnes date-heure
La requête suivante extrait toutes les colonnes de type date-heure de la table Installer
...
COLUMNS
WHERE TABLE_SCHEMA = 'bdsoutou' AND TABLE_NAME='Installer'
AND CHARACTER_MAXIMUM_LENGTH IS NULL
AND DATA_TYPE IN ('timestamp','time','date' );
+-------------+-----------+-------------------+
| COLUMN_NAME | DATA_TYPE | COLUMN_DEFAULT
|
+-------------+-----------+-------------------+
| dateIns
| timestamp | CURRENT_TIMESTAMP |
| delai
| time
| NULL
|
+-------------+-----------+-------------------+
Citons, pour en terminer avec cette vue, les colonnes :
q
CHARACTER_SET_NAME et COLLATION_NAME qui renseignent sur le jeu de caractères
pour chaque colonne de la table
...
Recherche des contraintes d’une table
La vue TABLE_CONSTRAINTS décrit la nature des contraintes
...
SELECT CONSTRAINT_SCHEMA,CONSTRAINT_NAME,CONSTRAINT_TYPE
FROM INFORMATION_SCHEMA
...
© Éditions Eyrolles
chapitre n° 5
Contrôle des données
q
CONSTRAINT_NAME pour renseigner le nom de la contrainte
...
q
CONSTRAINT_TYPE pour renseigner le type de chaque contrainte
...
Vous
pouvez toutefois créer des tables avec des contraintes CHECK ; rien ne se passera si vous
insérez des données non valides et le dictionnaire restera cohérent en n’extrayant pas ces
informations
...
Positions
La requête suivante permet d’extraire la composition des contraintes de la table Installer
dans la base bdsoutou, et en particulier celle de l’unicité du couple (nPoste,nLog)
...
KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = 'bdsoutou' AND TABLE_NAME='Installer';
+----------------------------+-------------+----------+----------------+
| CONSTRAINT_NAME
| COLUMN_NAME | Position | Position index |
+----------------------------+-------------+----------+----------------+
| PRIMARY
| numIns
|
1 |
NULL |
| un_installation
| nPoste
|
1 |
NULL |
| un_installation
| nLog
|
2 |
NULL |
| fk_Installer_nLog_Logiciel | nLog
|
1 |
1 |
| fk_Installer_nPoste_Poste | nPoste
|
1 |
1 |
+----------------------------+-------------+----------+----------------+
MySQL utilise :
q
ORDINAL_POSITION qui indique la position de la colonne dans la contrainte (débutant
à 1)
...
Pour les clés étrangères composites, elle indique la position de la colonne dans
la contrainte
...
© Éditions Eyrolles
199
Partie I
SQL de base
SELECT CONSTRAINT_NAME, COLUMN_NAME AS 'Cle',
REFERENCED_TABLE_SCHEMA AS 'Base cible',
REFERENCED_TABLE_NAME AS 'Table pere',
REFERENCED_COLUMN_NAME AS 'Col pere'
FROM INFORMATION_SCHEMA
...
Ici la base données contient les tables « fils » et « pères », mais il se peut que ces
tables soient dans deux bases distinctes
...
q
REFERENCED_COLUMN_NAME qui indique le nom de la colonne référencée dans la table
« père »
...
Recherche du code source d’un sous-programme
La vue ROUTINES décrit la composition des sous-programmes (procédures, et fonctions cataloguées)
...
SELECT ROUTINE_NAME,ROUTINE_TYPE,ROUTINE_DEFINITION
FROM INFORMATION_SCHEMA
...
q
ROUTINE_NAME qui indique le nom du sous-programme
...
q
ROUTINE_DEFINITION qui liste le code MySQL du sous-programme
...
q
CREATED et LAST_ALTERED pour stocker la date de création du sous-programme et
l’instant de la dernière compilation
...
q
ROUTINE_COMMENT qui stocke un éventuel commentaire relatif au sous-programme
(initialisé lors de la compilation)
...
Au niveau global
La vue USER_PRIVILEGES liste les privilèges des accès utilisateurs au niveau global (les
données viennent de la table mysql
...
La requête suivante extrait les privilèges de
Paul et de Jules (en accès distant ou en local)
...
SELECT GRANTEE,PRIVILEGE_TYPE,IS_GRANTABLE
FROM INFORMATION_SCHEMA
...
168
...
173' | SELECT
| NO
|
| 'Paul'@'192
...
4
...
q
PRIVILEGE_TYPE qui indique le type du privilège
...
Au niveau database
La vue SCHEMA_PRIVILEGES possède la même structure que la précédente, en ajoutant la
colonne TABLE_SCHEMA
...
user)
...
SELECT TABLE_SCHEMA ,GRANTEE,PRIVILEGE_TYPE,IS_GRANTABLE
FROM INFORMATION_SCHEMA
...
168
...
173' | SELECT
| NO
|
| bdpaul
| 'Paul'@'localhost'
| DROP
| NO
|
| bdpaul
| 'Paul'@'localhost'
| CREATE ROUTINE | NO
|
+--------------+------------------------+----------------+--------------+
Au niveau table
La vue TABLE_PRIVILEGES possède la même structure que la précédente, en ajoutant la
colonne TABLE_NAME
...
tables_priv)
...
SELECT CONCAT(TABLE_SCHEMA,'
...
Table',
GRANTEE,PRIVILEGE_TYPE AS 'Privilege'
FROM INFORMATION_SCHEMA
...
Table
| GRANTEE
| Privilege |
+--------------------------------------+------------------------+-----------+
| bdsoutou
...
Livre
| 'Paul'@'192
...
4
...
Livre
| 'Paul'@'localhost'
| SELECT
|
| bdpaul
...
Celle-ci précise le nom de la colonne concernée par les privilèges
des accès utilisateurs (les données viennent de la table mysql columns_priv)
...
SELECT CONCAT(TABLE_NAME,'
...
colonne',
GRANTEE,PRIVILEGE_TYPE AS 'Privilege'
FROM INFORMATION_SCHEMA
...
colonne | GRANTEE
| Privilege |
+---------------+--------------------+-----------+
| Livre
...
Commande SHOW
La commande SHOW permet d’extraire facilement des informations provenant du dictionnaire
des données
...
La copie d’écran suivante illustre la commande SHOW TABLES qui restitue une réponse à la
question : « Quelles sont les tables et les vues présentes dans la base de données en cours
d’utilisation ? »
...
Tableau 5-26 Exemples de SHOW
Commande
SHOW COLUMNS FROM Installer
FROM bdsoutou LIKE 'n%';
Liste des colonnes dont le nom commence par
'n' dans la table Installer de la base
bdsoutou
...
SHOW CREATE TABLE bdsoutou
...
SHOW DATABASES;
Liste des bases présentes sur le serveur
...
SHOW ERRORS;
Libellé de l’erreur SQL courante
...
SHOW INDEX FROM Installer FROM bdsoutou;
Description des index de la table Installer
de la base bdsoutou
...
SHOW TABLE STATUS FROM bdsoutou LIKE
'S%';
Caractéristiques physiques des tables dont le
nom commence par 'S' dans la base bdsoutou
...
SHOW TRIGGERS;
204
Résultat
Caractéristiques des déclencheurs présents
sur le serveur
...
5
...
sql, permettant de créer :
•
La vue LogicielsUnix qui contient tous les logiciels de type 'UNIX' (toutes les colonnes sont
conservées)
...
•
La vue Poste_0 de structure (nPos0, nomPoste0, nSalle0, TypePoste0, indIP, ad0) qui
contient tous les postes du rez-de-chaussée ( etage=0 au niveau de la table Segment)
...
Vérifier la structure et le contenu de la vue
...
Vérifier le contenu de la vue et celui de la table
...
Résoudre une requête complexe
Créer la vue SallePrix de structure (nSalle, nomSalle, nbPoste, prixLocation) qui
contient les salles et leur prix de location pour une journée (en fonction du nombre de postes)
...
Servez-vous de l’expression 100*nbPoste dans la requête de définition
...
Ajouter la colonne tarif de type SMALLINT(4) à la table Types
...
Il s’agit de grouper par salle, type et tarif (tout en faisant une jointure avec la table
Types pour les tarifs), et de compter le nombre de postes pour avoir le résultat suivant :
+--------+-----------+--------+-------+
| nSalle | typePoste | nombre | tarif |
+--------+-----------+--------+-------+
| s01
| TX
|
2 |
50 |
| s01
| UNIX
|
2 |
200 |
| s02
| PCWS
|
2 |
100 |
| s03
| TX
|
1 |
50 |
|
...
Vérifier le contenu de cette vue
...
Vues avec contraintes
Remplacer la vue Poste0 en rajoutant l’option de contrôle (CHECK OPTION)
...
Créer la vue Installer0 de structure (nPoste, nLog, dateIns) ne permettant de travailler
qu’avec les postes du rez-de-chaussée, tout en interdisant l’installation d’un logiciel de type 'PCNT'
...
Insérer l’enregistrement 'p6', 'log2' qui doit passer à travers
la vue
...
2
Vue multitable
Créer la vue SallePoste de structure (nomSalle, nomPoste, adrIP, nomTypePoste )
permettant d’extraire toutes les installations sous la forme suivante :
SELECT * FROM SallePoste;
+----------+----------+---------------+-------------------+
| nomSalle | nomPoste | adrIP
| nomTypePoste
|
+----------+----------+---------------+-------------------+
| Salle 1 | Poste 1 | 130
...
80
...
120
...
02 | Système Unix
|
| Salle 1 | Poste 3 | 130
...
80
...
|
206
© Éditions Eyrolles
Partie II
Programmation
procédurale
Chapitre 6
Bases du langage
de programmation
Ce chapitre décrit les caractéristiques générales du langage procédural de programmation de
MySQL :
q
structure d’un programme ;
q
déclaration et affectation de variables ;
q
structures de contrôle (si, tant que, répéter, pour) ;
q
mécanismes d’interaction avec la base ;
q
programmation de transactions
...
Elles apparaissent dans une sous-partie optionnelle de la norme
(ISO/IEC 9075-5:1996
...
MySQL les prend en compte
...
Environnement client-serveur
Dans un environnement client-serveur, chaque instruction SQL donne lieu à l’envoi d’un
message du client vers le serveur suivi de la réponse du serveur vers le client
...
En effet, un bloc donne
lieu à un seul échange sur le réseau entre le client et le serveur
...
© Éditions Eyrolles
209
Partie II
Programmation procédurale
Figure 6-1 Trafic sur le réseau d’instructions SQL
SELECT …;
UPDATE …
...
d’instructions
Client
CALL Bloc
Serveur
SGBD
Exécution globale
BEGIN
SELECT …;
UPDATE …
...
END;
Avantages
Les principaux avantages d’utiliser des sous-programmes (procédures ou fonctions cataloguées qui sont stockées côté serveur) sont :
q
La modularité : un sous-programme peut être composé d’autres blocs d’instructions
...
q
La portabilité : un sous-programme est indépendant du système d’exploitation qui héberge
le serveur MySQL
...
q
L’intégration avec les données des tables : on retrouvera avec ce langage procédural tous
les types de données et d’instructions disponibles sous MySQL, des mécanismes pour
parcourir des résultats de requêtes (curseurs), pour traiter des erreurs (handlers) et pour
programmer des transactions (COMMIT, ROLLBACK, SAVEPOINT)
...
Structure d’un bloc
Un bloc d’instructions est composé de :
q
BEGIN (section obligatoire) contient le code incluant ou non des directives SQL se termi-
nant par le symbole « ; » ;
q
DECLARE (directive optionnelle) déclare une variable, un curseur, une exception, etc
...
Un bloc peut être imbriqué dans un autre bloc
...
MySQL ne
prend pas encore en charge les procédures anonymes (sans nom)
...
…
…
END;
déclaration ]
-- code
…
END;
BEGIN
[DECLARE déclaration ]
...
Un objet déclaré dans un bloc est accessible dans les sous-blocs
...
Figure 6-3 Visibilité des objets
BEGIN
DECLARE v_brevet CHAR(6);
…
-- v_brevet accessible
…
END;
v_nom inaccessible
BEGIN
DECLARE v_nom VARCHAR (20);
-- v_brevet et v_nom
accessibles
…
END;
Casse et lisibilité
Comme SQL, les sous-programmes sont capables d’interpréter les caractères alphanumériques du jeu de caractères sélectionné
...
Ainsi numeroBrevet et NumeroBREVET désignent le même
identificateur (tout est traduit en minuscules au niveau du dictionnaire des données)
...
Tableau 6-1 Lisibilité du code
Peu lisible
IF x>y THEN SET max:=x;ELSE SET max:=y;END IF;
© Éditions Eyrolles
C’est mieux
IF x>y THEN
SET max:=x;
ELSE
SET max:=y;
END IF;
211
Partie II
Programmation procédurale
Identificateurs
Avant de parler des différents types de variables MySQL, décrivons comment il est possible
de nommer les objets des sous-programmes
...
Un identificateur n’est pas limité en nombre de caractères
...
Le tableau suivant décrit quelques exemples :
Tableau 6-3 Commentaires
Sur une ligne
-- Lecture de la table Pilote
SELECT nbHVol INTO v_nbHVol
FROM Pilote –- Extraction heures de vol
WHERE nom = 'Gratien Viel';
SET v_bonus := v_nbHVol*0
...
15;
Variables
Un sous-programme est capable de manipuler des variables qui sont déclarées (et éventuellement initialisées) par la directive DECLARE
...
Deux types de variables sont disponibles sous MySQL :
q
q
212
scalaires : recevant une seule valeur d’un type SQL (ex : colonne d’une table) ;
externes : définies dans la session et qui peuvent servir de paramètres d’entrée ou de sortie
...
] typeMSQL [DEFAULT expression];
q
DEFAULT permet d’initialiser la (ou les) variable(s) – pas forcément à l’aide d’une cons-
tante
...
Équivalent à SET v_dateNaissance
:= NULL;
DECLARE v_capacite SMALLINT(4) DEFAULT 999;
Initialise la variable à 999
...
DECLARE v_Dans2jours DATE
DEFAULT ADDDATE(SYSDATE(),2);
Initialise la variable à dans 2 jours
...
Vous pouvez aussi utiliser le symbole « = », mais il est plus prudent
de le réserver à la programmation de conditions ;
q
la directive DEFAULT ;
q
la directive INTO d’une requête (SELECT … INTO variable FROM …)
...
Cela peut être
pénalisant quand on désire travailler en interne avec des résultats d’extractions de taille
moyenne
...
Ici, la déclaration de la variable v_maxi est incorrecte :
DECLARE
v_maxi INT DEFAULT 2 * v_mini;
DECLARE
v_mini INT DEFAULT 15;
© Éditions Eyrolles
213
Partie II
Programmation procédurale
Comme la plupart des langages récents, les déclarations multiples sont permises
...
Dans l’exemple suivant, l’instruction DELETE supprime tous les pilotes de la table (et non pas
seulement le pilote de nom 'Placide Fresnais'), car MySQL considère les deux identificateurs
comme étant la même variable, et non pas comme colonne de la table et variable
...
Une
autre solution serait d’utiliser une étiquette de bloc (block label) pour lever d’éventuelles
ambiguïtés
...
Tableau 6-5 Éviter les ambiguïtés
Préfixer les variables
Étiquette de bloc (préfixe pas opérationnel)
DECLARE v_nom VARCHAR(16)
DEFAULT 'Placide Fresnais';
…
DELETE FROM Pilote WHERE nom = v_nom ;
--ou
DELETE FROM Pilote WHERE v_nom = nom ;
principal: BEGIN
DECLARE nom VARCHAR(16)
DEFAULT 'Placide Fresnais';
DELETE FROM Pilote
WHERE principal
...
Les règles de priorité sont les mêmes que dans le
cas de SQL
...
Toute expression
arithmétique contenant une valeur nulle est évaluée à NULL
...
SET v_compteur := v_compteur+1;
Incrémentation de v_compteur (opérateur +)
SET v_boolean := (v_compteur=v_nombre); v_boolean reçoit NULL, car la condition est
fausse
...
Variables de session
Il est possible de passer en paramètres d’entrée d’un bloc des variables externes
...
Elles n’existent que durant la session
...
SET @var1 = expression1
[, @var2 = expression2]
...
Son numéro de brevet et la durée du vol sont lus au clavier
...
00 |
+------------------+----------+
Conventions recommandées
Adoptez les conventions d’écriture suivantes pour que vos programmes MySQL soient plus
facilement lisibles et maintenables :
© Éditions Eyrolles
215
Partie II
Programmation procédurale
Tableau 6-8 Conventions
Objet
Convention
Exemple
Variable
v_nomVariable
v_compteur
Constante
c_nomConstante
c_pi
Variable de session (globale)
vs_nomVariable
vs_brevet
Test des exemples
Parce qu’il n’est pas encore possible d’exécuter des blocs anonymes (sous-programme sans
nom et qui n’est pas stocké dans la base), vous devez les inclure dans une procédure cataloguée que vous appellerez dans l’interface de commande
...
Pensez à redéfinir le délimiteur à « $ » (par exemple) pour pouvoir utiliser, dans le bloc, le
symbole « ; » pour terminer chaque instruction
...
DROP PROCEDURE sp1$
Suppression de la procédure
...
BEGIN
DECLARE v_nbHVol DECIMAL(7,2);
SELECT nbHVol INTO v_nbHVol
FROM Pilote WHERE nom = @vs_nom;
SELECT v_nbHVol;
END;
$
Bloc d’instructions
...
Trace du résultat
...
Allez-y tester vos exemples, maintenant
...
Pas de structure FOR pour l’instant
...
Structures conditionnelles
MySQL propose deux structures pour programmer des actions conditionnées : la structure IF
et la structure CASE
...
Le tableau suivant donne l’écriture des différentes structures conditionnelles IF
...
L’exemple affiche un message différent selon la nature du numéro de téléphone contenu dans la variable v_telephone
...
";
END IF;
END;
Conditions booléennes
Les tableaux suivants précisent le résultat d’opérateurs logiques qui mettent en jeu des variables booléennes pouvant prendre trois valeurs (TRUE, FALSE, NULL)
...
Il est à noter que la
négation de NULL (NOT NULL) renvoie une valeur nulle
...
La structure CASE est utile lorsqu’il faut évaluer une même
expression et proposer plusieurs traitements pour diverses conditions
...
8;
...
SET v_mention := 'R' ;
END IF;
...
Structure tant que
La structure tant que se programme à l’aide de la syntaxe suivante
...
Si elle est vraie, la séquence d’instructions est exécutée, puis la condition est réévaluée pour un éventuel nouveau passage dans la
© Éditions Eyrolles
219
Partie II
Programmation procédurale
boucle
...
Quand la condition n’est jamais fausse, on dit que le programme boucle…
[etiquette:] WHILE condition DO
instructions;
END WHILE [etiquette];
Le tableau suivant décrit la programmation de deux tant que
...
Le second recherche le premier numéro 4 dans une chaîne de caractères
...
Elle doit être utilisée
quand il est nécessaire de tester une condition avant d’exécuter les instructions contenues dans
la boucle
...
Enfin un répéter qui se programme comme il faut (à savoir « répéter… jusqu’à condition »)
...
Ouf, MySQL
(comme Oracle) a bien programmé la structure répéter en traduisant ce fameux jusqu’à par la
directive until, et non plus par ce fâcheux while
...
La condition n’est évaluée qu’en fin de boucle
...
Ce processus
continue jusqu’à ce que la condition soit vraie pour passer en séquence après le END REPEAT
...
Les variables sont les mêmes qu’au tableau précédent
...
Structure boucle sans fin
La syntaxe générale de cette structure est programmée par la directive LOOP
...
[etiquette:] LOOP
instructions;
END LOOP [etiquette];
Le tableau suivant donne l’écriture du calcul de la somme des 100 premiers entiers en utilisant
deux boucles sans fin (qui se terminent toutefois, car tout a une fin, mais celles-là je les
programme avec LEAVE)
...
© Éditions Eyrolles
221
Partie II
Programmation procédurale
Tableau 6-17 TStructures boucle sans fin
Web
Avec LEAVE
Avec ITERATE
boucle1: LOOP
boucle1: LOOP
SET v_somme := v_somme + v_entier;
SET v_somme := v_somme + v_entier;
SET v_entier := v_entier + 1;
SET v_entier := v_entier + 1;
IF v_entier > 100 THEN
IF v_entier <= 100 THEN
LEAVE boucle1 ;
ITERATE boucle1 ;
END IF;
END IF;
END LOOP boucle1 ;
LEAVE boucle1 ;
END LOOP boucle1 ;
Il est à noter que LEAVE peut être aussi utilisé pour sortir d’un bloc (s’il est étiqueté)
...
Redirection (GOTO)
Célèbre pour faire tendre un programme vers une configuration plutôt de feu d’artifice que de
cours d’eau tranquille, l’instruction GOTO est bien connue, mais souvent mal utilisée
...
Il n’est pas souhaitable
que vous utilisiez GOTO, à moins que vous écriviez vos algorithmes avec des organigrammes
...
mysql
...
html) Peter Gulutzan parle de « GOTO etiquette; » et de « LABEL etiquette; »
...
0 n’en était qu’à ses débuts
...
À suivre, donc
...
La syntaxe générale de cette structure est programmée dans
tous les langages par l’instruction for
...
Dans tous ces cas, il faudra définir un indice allant d’une valeur
initiale à une valeur finale, tout en incrémentant ce même indice en fin de boucle
...
222
© Éditions Eyrolles
chapitre n° 6
Bases du langage de programmation
Extraire des données
La principale instruction capable d’extraire des données contenues dans des tables est
SELECT
...
]INTO variable1 [,variable2
...
;
Cette instruction peut aussi être utilisée à l’extérieur d’un bloc pour charger une variable de
session, par exemple
...
C’est logique, puisque vous désirez ne charger qu’une valeur par variable
...
• Si vous n’en extrayez aucun (no data found), aucune erreur n’est soulevée et la variable est
inchangée (elle reste initialisée à la valeur présente avant la requête)
...
DECLARE v_comp VARCHAR(15);
Nécessité d’appeler par la suite cette procéSELECT compa INTO v_comp
dure (CALL)
...
END;
SET @vs_compa=''$
SELECT compa INTO @vs_compa FROM Pilote
WHERE brevet='PL-2'$
...
SET @vs_compa=''$
Chargement d’une variable de session dans un
CREATE PROCEDURE sp1()
sous-programme
...
END;
© Éditions Eyrolles
223
Partie II
Programmation procédurale
Pour traiter des requêtes renvoyant plusieurs enregistrements, il faudra utiliser des curseurs
(étudiés au chapitre suivant)
...
Deux exemples sont décrits dans le tableau suivant : le premier chargera la variable avec le nom du pilote de code 'PL-1' en majuscules (table décrite au début
du chapitre 4) ; le second affectera à la variable le maximum du nombre d’heures de vol,
tous pilotes confondus
...
00 |
+-----------------+
Manipuler des données
Les principales instructions disponibles pour manipuler, par un sous-programme, les
éléments d’une base de données sont les mêmes que celles proposées par SQL, à savoir
INSERT, UPDATE et DELETE
...
Insertions
Le tableau suivant décrit l’insertion de différents enregistrements sous plusieurs écritures (il
est aussi possible d’utiliser des variables de session) :
Comme sous SQL, il faut respecter les noms, types et domaines de valeurs des colonnes
...
Dans le cas inverse, une exception qui précise la nature du problème est levée et peut être
interceptée par la directive HANDLER (voir chapitre suivant)
...
Insertion d’un enregistrement en renseignant les colonnes par des constantes
...
dans le bloc qui contient l’instruction INSERT, la première exception fera s’interrompre le
programme
...
UPDATE nomTable
SET col1 = { variable1 | expression1 | autrecol | (requête) }
[,col2 =
...
];
Si aucun enregistrement n’est modifié, aucune erreur ne se produit et aucune exception n’est
levée
...
Le tableau suivant décrit la modification de différents enregistrements (il est aussi possible
d’employer des variables de session)
...
8;
UPDATE Pilote
SET nbHVol= nbHVol + v_dureeVol
WHERE brevet= 'PL-6';
Déclaration
...
Modification d’un enregistrement de la
table Pilote en utilisant une variable
...
DELETE FROM nomTable
[WHERE col1 = { variable1 | expression1 | autrecol | (requête) }
[,col2 =
...
Le tableau suivant décrit la suppression de différents enregistrements (il est aussi possible
d’utiliser des variables de session)
...
00;
DELETE FROM Pilote WHERE nbHVol < v_hVolMini ;
DELETE FROM Pilote WHERE brevet = 'PL-3' ;
DELETE FROM Pilote WHERE brevet = NULL ;
END;
226
Supprime les enregistrements de
la table Pilote dont le nombre
d’heures de vol est inférieur à
1 000
...
Ne supprime aucun pilote
...
Si un problème logiciel ou matériel survient au cours d’une
transaction, aucune des instructions contenues dans la transaction n’est effectuée, quel que
soit l’endroit de la transaction où est intervenue l’erreur
...
Les langages plus évolués permettent aussi de développer des transactions
à travers des API (par exemple la méthode commit est comprise dans le paquetage
java
...
L’exemple typique d’une transaction est celui du transfert d’un compte épargne vers un
compte courant
...
Le mécanisme transactionnel empêche un tel scénario en invalidant toutes les opérations faites depuis le début de la transaction, si une panne survient au cours de cette même
transaction
...
© Éditions Eyrolles
227
Partie II
Programmation procédurale
Début et fin d’une transaction
Deux instructions sont disponibles pour marquer le début d’une transaction : START TRANSACTION ou BEGIN
...
Le fait de commencer une transaction termine implicitement
celle qui précédait ladite transaction
...
Elle
se termine implicitement :
• à la première commande SQL du LDD ou du LCD rencontrée (CREATE, ALTER, DROP…) ;
• à la fin normale d’une session utilisateur avec déconnexion ;
• à la fin anormale d’une session utilisateur (sans déconnexion)
...
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
...
Le mode à utiliser
pour programmer des transactions est celui inverse (autocommit off) qui se déclare à l’aide du
paramètre 0 dans l’instruction suivante :
SET AUTOCOMMIT = {0 | 1}
Le tableau suivant précise la validité de la transaction en fonction des événements possibles :
Tableau 6-23 Validité d’une transaction
Événement
Validité
COMMIT
Transaction validée
...
Fin anormale d’une session
...
Votre première transaction
Vous pouvez tester rapidement une transaction en écrivant le bloc suivant qui insère une ligne
dans une de vos tables
...
);
END;
$
--appel de la transaction
CALL sp1()$
SELECT * FROM TableaVous$
Web
Exécutez ce bloc dans l’interface, puis déconnectez-vous soit en cassant la fenêtre (icône en
haut à droite), soit proprement avec exit
...
Même quand la fin du programme est normale, la transaction n’est pas validée (car il manque COMMIT)
...
Notez que l’enregistrement est présent désormais dans votre
table, même après une déconnexion douce ou dure
...
La figure suivante illustre une transaction découpée en trois parties
...
Ainsi ROLLBACK
TO
SAVEPOINT
Pointvalidation1 invalidera les UPDATE et le DELETE tout en laissant la possibilité de
confirmer l’instruction INSERT (en fonction des commandes se trouvant après ce ROLLBACK
restreint et de la manière dont la session se terminera)
...
Le programmeur
aura le choix entre les instructions ROLLBACK TO SAVEPOINT indiquées en commentaire
pour valider tout ou partie de la transaction
...
L’instruction SAVEPOINT déclare un point de validation
...
SET AUTOCOMMIT = 0;
INSERT INTO Compagnie VALUES
('C2',2, 'Place Brassens', 'Blagnac', 'Easy Jet');
SAVEPOINT P1 ;
UPDATE Compagnie SET nrue = 125
WHERE comp = 'AF';
UPDATE Compagnie SET ville = 'Castanet'
WHERE comp = 'C1';
Deuxième partie de la transaction
...
-- ROLLBACK TO SAVEPOINT P1 ;
Première partie à valider
...
-- ROLLBACK TO SAVEPOINT P3
Troisième partie à valider
...
Valide la ou les sous-parties
...
Il n’est pas possible d’invalider par ROLLBACK une commande SQL du LDD ou du LCD rencontrée (CREATE, ALTER, DROP…)
...
Vous utiliserez une procédure pour tester vos blocs, comme il
est indiqué dans la section Test des exemples
...
1
Extraction de données
Écrire le bloc MySQL qui affiche les détails de la dernière installation de logiciel sous la forme suivante
(les champs en gras sont à extraire) :
+------------------------------------------------+
| Resultat 1 exo 1
|
+------------------------------------------------+
| Derniere installation en salle : numérodeSalle |
+------------------------------------------------+
+--------------------------------------------------------------------+
| Resultat 2 exo 1
|
+--------------------------------------------------------------------+
| Poste : numéroPoste Logiciel : nomLogiciel en date du dateInstallation |
+--------------------------------------------------------------------+
Vous utiliserez SELECT … INTO pour extraire ces valeurs
...
6
...
Vous devez extraire 1 poste et 3 installations
...
6
...
La date d’achat doit être celle du jour
...
© Éditions Eyrolles
231
Partie II
Programmation procédurale
Il faut ensuite procéder à l’installation de ce logiciel sur le poste de code p7 (utiliser une variable pour
pouvoir plus facilement modifier ce paramètre)
...
Penser
à actualiser correctement la colonne delai qui mesure le délai (TIME) entre l’achat et l’installation
...
Utiliser la fonction TIMEDIFF pour
calculer ce délai
...
4, typePCWS coûtant 95 €
...
01 sec)
+----------------------------------+
| message2
|
+----------------------------------+
| Date achat : 2005-11-23 19:16:04 |
+----------------------------------+
Attente de 5 secondes à ce niveau
+----------+
| SLEEP(5) |
+----------+
|
0 |
+----------+
+-----------------------------------------+
| message3
|
+-----------------------------------------+
| Date installation : 2005-11-23 19:16:10 |
+-----------------------------------------+
+--------------------------------+
| message4
|
+--------------------------------+
| Logiciel installe sur le poste |
+--------------------------------+
Vérifiez l’état des tables mises à jour après la transaction
...
232
© Éditions Eyrolles
Chapitre 7
Programmation avancée
Ce chapitre est consacré à des caractéristiques avancées du langage procédural de MySQL :
q
écriture et appel de sous-programmes ;
q
programmation des curseurs ;
q
gestion des exceptions ;
q
mise en place de déclencheurs ;
q
utilisation du SQL dynamique
...
Dans le vocabulaire des bases de données, on appelle les sous-programmes stored
procedures ou stored routines
...
Comme dans tous les langages de
programmation, les fonctions retournent un unique résultat, alors que les procédures réalisent
des actions sans en donner (sauf éventuellement en paramètre de sortie)
...
L’autre SGBD se rapprochant le plus de la norme est DB2 d’IBM
...
Pour l’instant, seules les procédures sont capables d’inclure des paramètres en sortie
...
Généralités
Il est possible de retrouver le code d’un sous-programme au niveau du dictionnaire des
données (voir la fin du chapitre 5)
...
Les avantages d’utiliser des sous-programmes ont été soulignés au
chapitre 6 (modularité, portabilité, extensibilité, réutilisabilité, intégrité et confidentialité)
...
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, ou dans le corps
d’un déclencheur
...
Le cycle de vie d’un sous-programme est le suivant : création de la procédure ou de la fonction
(compilation et stockage dans la base), appel et éventuellement suppression du sousprogramme de la base
...
Le privilège CREATE
ROUTINE est requis sur la base de données (ou au niveau global) en question (ALTER
ROUTINE et EXECUTE sont affectés par la suite automatiquement)
...
]nomProcédure(
[ [ IN | OUT | INOUT ] param typeMySQL
[,[ IN | OUT | INOUT ] param2 typeMySQL ] ]
...
;]
bloc d’instructions SQL et MySQL
...
Si un
nom est spécifié (nomBase), la procédure appartiendra à cette base de données
...
LANGUAGE SQL (par défaut) détermine le langage de programmation de la procédure
...
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
q
q
q
q
DETERMINISTIC est simplement informationnel (l’optimiseur s’en servira dans des
versions ultérieures) et décrit le caractère déterministe de la procédure
...
CONTAINS SQL renseigne sur le fait que la procédure interagit avec la base
...
READS SQL DATA précise que les interactions sont en lecture seulement
...
SQL SECURITY détermine si la procédure s’exécute avec les privilèges du créateur
(option par défaut : definer-rights procedure) ou ceux de l’utilisateur qui appelle la procédure (invoker-rights procedure)
...
q
bloc d’instructions SQL et MySQL contient les déclarations et les instructions de
q
la procédure écrite dans le langage de MySQL (voir le chapitre précédent)
...
Fonctions cataloguées
La syntaxe de création d’une fonction cataloguée est CREATE FUNCTION
...
N’oubliez pas l’instruction « RETURN
variable; » qui termine la fonction et retourne le résultat (de même type que celui déclaré
dans la clause RETURNS
...
]nomFonction(
[ param typeMySQL
[,param2 typeMySQL ] ]
...
;]
bloc d’instructions SQL et MySQL
...
La figure suivante
illustre la structure d’une spécification et d’un corps d’un sous-programme MySQL
...
Figure 7-1 Structure d’un sous-programme
CREATE { PROCEDURE | FUNCTION }
nomSousProgramme [(
...
instructions MySQL;
BEGIN
[DECLARE déclaration ];
...
...
Nous allons écrire (dans la base bdsoutou) une fonction et
une procédure :
q
La fonction EffectifsHeure(comp,heures) devra renvoyer le nombre de pilotes
d’une compagnie donnée (premier paramètre) qui ont plus d’heures de vol que la valeur du
deuxième paramètre (si aucun pilote, retourne 0)
...
Les éventuelles erreurs ne
sont pas encore traitées (compagnie de code inexistant, par exemple)
...
Si plusieurs pilotes ont la même expérience, un message d’erreur est affiché
...
Remarquez que la fonction aurait pu être programmée par une procédure ayant un troisième
paramètre de sortie
...
sql)
...
CREATE FUNCTION bdsoutou
...
sql)
...
On peut assimiler le passage d’un paramètre par
référence à l’utilisation de la directive INOUT
...
PlusExperimente
Web
(INOUT pcomp VARCHAR(4), OUT pnomPil VARCHAR(20), OUT pheuresVol DECIMAL(7,2))
BEGIN
DECLARE p1 SMALLINT;
IF (pcomp IS NULL) THEN
SELECT COUNT(*) INTO p1 FROM Pilote
WHERE nbHVol=(SELECT MAX(nbHVol) FROM Pilote);
ELSE
SELECT COUNT(*) INTO p1 FROM Pilote
WHERE nbHVol=(SELECT MAX(nbHVol) FROM Pilote WHERE comp=pcomp)
AND comp = pcomp;
END IF;
IF (p1 = 0) THEN
SELECT ('Aucun pilote n''est le plus expérimenté') AS resultat;
ELSEIF p1 > 1 THEN
SELECT('Plusieurs pilotes sont les plus expérimentés') AS resultat;
ELSE
IF (pcomp IS NULL) THEN
SELECT nom, nbHVol, comp INTO pnomPil, pheuresVol, pcomp
FROM Pilote WHERE nbHVol=(SELECT MAX(nbHVol) FROM Pilote);
ELSE
SELECT nom, nbHVol INTO pnomPil, pheuresVol FROM Pilote
WHERE nbHVol=(SELECT MAX(nbHVol) FROM Pilote WHERE comp=pcomp)
AND comp = pcomp;
END IF;
END IF;
END;
Fonction n’interagissant pas avec la base
La fonction EcritureComplexe renvoie une chaîne de caractères désignant l’écriture d’un
nombre complexe sous la forme « a + bi » ou « a - bi » (EcritureComplexe
...
Web
CREATE FUNCTION bdsoutou
...
Le même résultat peut être obtenu par la commande SHOW ERRORS
...
Appel d’un sous-programme
Le créateur d’un sous-programme peut exécuter ce dernier à la demande et sans aucune condition préalable
...
AugmenteCapacite('F-GLFS'); »)
...
Le chapitre suivant détaillera un tel appel à
partir d’un programme externe (Java ou PHP)
...
La commande CALL permet d’appeler une procédure
...
Le tableau suivant décrit l’appel et le résultat des trois sous-programmes
...
© Éditions Eyrolles
239
Partie II
Programmation procédurale
Tableau 7-1 Appels dans l’interface de commande
Web
Appel d'un sous-programme
Résultat
delimiter ;
SELECT bdsoutou
...
EffectifsHeure('AF',300) |
+-----------------------------------+
|
2 |
+-----------------------------------+
delimiter ;
SET @vs_compa = 'AF';
SET @vs_nompil = '';
SET @vs_heures = '';
CALL bdsoutou
...
EcritureComplexe(2,-5);
CREATE TABLE test
...
Trace
SELECT bdsoutou
...
EcritureComplexe
(-2,-5);
INSERT INTO test
...
EcritureComplexe(3,-7));
SELECT @vs_compa,@vs_nompil,@vs_heures;
+-----------+----------------+------------+
| @vs_compa | @vs_nompil
| @vs_heures |
+-----------+----------------+------------+
| AF
| Gilles Laborde | 2450
...
EcritureComplexe(2,-5) |
+---------------------------------+
| Complexe : 2-5i
|
+---------------------------------+
SELECT * FROM test
...
Le même principe peut être adopté pour l’appel dans un déclencheur
...
240
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
Tableau 7-2 Appels dans un sous-programme
Codage
Web
CREATE PROCEDURE test
...
EffectifsHeure
(v_compa,v_heures);
SELECT v_nbpil;
END;
Appels
CALL test
...
sp2()
BEGIN
CALL bdsoutou
...
sp2()$
+---------------------------------+
| resultat
|
+---------------------------------+
| Plusieurs pilotes sont les plus
expérimentés
|
+---------------------------------+
-- Les variables de session sont
-- toutes à NULL
SET @vs_resultat = ''$
CREATE PROCEDURE test
...
EcritureComplexe(7,-2) ;
END;
CALL test
...
Comme dans tout programme récursif, il ne faudrait pas oublier la condition de terminaison !
L’exemple suivant décrit la programmation à l’aide d’une fonction récursive du calcul de la
factorielle d’un entier positif
...
© Éditions Eyrolles
241
Partie II
Programmation procédurale
Tableau 7-3 Récursivité
Web
Code MYSQL
Commentaires
delimiter $
CREATE FUNCTION factorielle(n INT)
RETURNS INT
BEGIN
IF n = 1 THEN
RETURN (1);
ELSE
RETURN (n * factorielle(n - 1));
END IF;
END;
$;
Condition de terminaison
...
SELECT factorielle(10) AS 'Factorielle de 10'$
ERROR 1424 (HY000): Recursive stored routines are not
allowed
...
Cela n’est valable que pour les blocs d’instructions qui peuvent éventuellement en inclure
d’autres (voir chapitre 6)
...
Ce sous-programme insérerait une ligne dans une table pour tracer
l’appel de la procédure en fonction de l’utilisateur et du moment de l’exécution
...
imbriquee
(INOUT p1 VARCHAR(2))
BEGIN
CREATE PROCEDURE bdsoutou
...
Trace VALUES
(CONCAT(USER(),' a lancé imbriquee
le ',SYSDATE()));
END;
SET p1 := 'OK';
CALL bdsoutou
...
Déclaration du sous-programme imbriqué
...
Appel du sous-programme imbriqué
...
Modification d’un sous-programme
La modification d’un sous-programme s’exécute par la commande ALTER
...
Plusieurs caractéristiques
peuvent être corrigées en une seule instruction (mais ni le code, ni les paramètres)
...
]nomSousProg
[ { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'commentaire'
...
ALTER PROCEDURE bdsoutou
...
La syntaxe de suppression
d’un sous-programme est la suivante :
DROP {PROCEDURE | FUNCTION} [IF EXISTS] [nomBase
...
Les instructions suivantes suppriment la procédure cataloguée Mouchard de la base bdsoutou
...
Mouchard;
© Éditions Eyrolles
243
Partie II
Programmation procédurale
Restrictions
Les restrictions que nous mentionnons ici s’appliquent également aux déclencheurs (étudiés
en fin de ce chapitre)
...
• Les instructions suivantes ne peuvent être présentes dans un sous-programme CHECK
TABLES, LOCK TABLES, UNLOCK TABLES, LOAD DATA, LOAD TABLE et OPTIMIZE TABLE
...
• Il n’y a pas encore d’outil de débogage pour les sous-programmes
...
• MySQL ne prend pas encore en charge la notion de paquetage (package) qui est un module
regroupant plusieurs objets (variables, exceptions, curseurs, fonctions ou procédures) fournissant un ensemble de services (un peu comme une classe dans l’approche objet)
...
Le concept, analogue au niveau de JDBC, est programmé à l’aide de la classe
Resultset, et, sous ASP de Microsoft, à l’aide de la classe RecordSet (appelée DataSet
avec
...
MySQL n’est compatible qu’avec des curseurs en lecture seulement, non navigables, non
modifiables et non dynamiques
...
Un sous-programme peut
travailler avec plusieurs curseurs en même temps
...
La figure suivante illustre la manipulation de base d’un curseur
...
Il est ouvert dans le code du programme ; il s’évalue alors et va se charger en
extrayant les données de la base
...
Le curseur est ensuite fermé
...
244
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
Figure 7-3 Principes d’un curseur
CREATE PROCEDURE
BEGIN
DECLARE v1
...
;
DECLARE v3
...
) ]
FOR SELECT brevet,nbhVol,
comp
FROM Pilote WHERE comp = ‘AF’
...
OPEN curs1 ;
F ETCH curs1 INTO
...
Instructions
Les instructions disponibles pour travailler avec des curseurs sont définies dans le tableau
suivant :
Tableau 7-5 Instructions pour les curseurs
Instructions
Déclaration du curseur
...
Pilote WHERE comp = 'AF';
OPEN nomCurseur;
Ouverture du curseur (chargement des lignes)
...
OPEN curs1;
FETCH nomCurseur INTO
listeVariables;
Positionnement sur la ligne suivante et chargement de l’enregistrement
courant dans une ou plusieurs variables
...
L’exception « ERROR 1326 (24000): Cursor is
not open » se déclenche si des accès au curseur sont opérés après
sa fermeture
...
Le tableau suivant
présente le parcours d’un curseur à l’aide de ces deux techniques
...
Notez l’utilisation obligatoire d’une exception (handler dans le vocable de MySQL) qui force
le programme à continuer si on arrive en fin du curseur (au-delà du dernier enregistrement),
tout en positionnant la variable curs1 à vrai (1)
...
Nous étudierons plus en détail les exceptions dans la prochaine section
...
Pilote WHERE comp = 'AF';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET fincurs1 := 1;
OPEN curs1;
REPEAT
FETCH curs1 INTO v_nbHv;
IF NOT fincurs1 THEN
SET v_tot := v_tot+v_nbHv;
END IF;
UNTIL fincurs1
END REPEAT;
FETCH curs1 INTO v_nbHv;
WHILE (NOT fincurs1) DO
SET v_tot := v_tot+v_nbHv;
FETCH curs1 INTO v_nbHv;
END WHILE;
CLOSE curs1;
SELECT v_tot AS 'Total heures pour les pilotes de ''AF''';
Personnellement, je préfère la programmation avec un tant que
...
00 |
+---------------------------------------+
246
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
Accès concurrents (FOR
UPDATE)
Si vous voulez verrouiller les lignes d’une table interrogée par un curseur dans le but de mettre
à jour la table, sans qu’un autre utilisateur ne la modifie en même temps, il faut utiliser la
clause FOR UPDATE
...
Les verrous sont libérés à la fin de la transaction
...
Il est conseillé d’utiliser un curseur
FOR UPDATE pour verrouiller les lignes à actualiser
...
Tableau 7-7 Curseur avec verrouillage explicite
Web
Code MySQL
fincurs BOOLEAN DEFAULT 0;
v_brevet VARCHAR(6);
v_nbHv
DECIMAL(7,2);
v_comp
VARCHAR(4);
curs CURSOR FOR
SELECT brevet,nbHVol,comp
FROM bdsoutou
...
Pilote
SET nbHVol = nbHVol + 100
WHERE brevet = v_brevet;
ELSEIF (v_comp='SING') THEN
UPDATE bdsoutou
...
Pilote
WHERE brevet = v_brevet;
END IF;
FETCH curs INTO v_brevet,v_nbHv,v_comp;
END WHILE;
CLOSE curs;
COMMIT;
© Éditions Eyrolles
Commentaires
BEGIN
DECLARE
DECLARE
DECLARE
DECLARE
DECLARE
Déclaration du curseur avec verrou
...
Mise à jour de la table Pilote par
l’intermédiaire du curseur
...
247
Partie II
Programmation procédurale
Restrictions
• Une validation (COMMIT) avant la fermeture d’un curseur FOR UPDATE aura des effets de
bord fâcheux
...
• Il n’existe pas encore de directive WHERE CURRENT OF pour modifier l’enregistrement courant d’un curseur avec verrou
...
Exceptions
Afin d’éviter qu’un programme ne s’arrête dès la première erreur suite à une instruction SQL
(SELECT ne retournant aucune ligne, INSERT ou UPDATE d’une valeur incorrecte, DELETE
d’un enregistrement « père » ayant des enregistrements « fils » associés, etc
...
Dans le langage des informaticiens, on dit qu’on garde la main pendant l’exécution du
programme
...
Les exceptions
peuvent se paramétrer dans un sous-programme (fonction ou procédure cataloguée) ou un
déclencheur
...
Une exception est détectée (aussi dite « levée ») si elle est prévue
dans un handler au cours de l’exécution d’un bloc (entre BEGIN et END)
...
La figure suivante illustre les deux mécanismes qui peuvent être mis en œuvre pour gérer une
exception (seuls CONTINUE et EXIT sont actuellement pris en charge par MySQL)
...
Supposons que l’insertion déclenche une erreur, on peut également
décider de sortir ou de poursuivre le traitement
...
DECLARE { CONTINUE | EXIT | UNDO }
HANDLER FOR
{ SQLSTATE
v | SQLEXCEPTION
| NOT FOUND
...
SELECT
...
FROM
...
...
CONTINUE
...
END ;
Si aucune erreur ne se produit, le traitement se termine ou retourne à son appelant, s’il s’agit
d’un sous-programme lancé d’un programme principal
...
Les exceptions doivent être déclarées de préférence après les variables et avant
les curseurs
...
]
q
q
La directive CONTINUE (appelée handler) force à poursuivre l’exécution de programme
lorsqu’il se passe un événement prévu dans la clause FOR
...
Le handler UNDO n’est pas encore reconnu
...
q
SQLSTATE permet de couvrir toutes les erreurs d’un état donné
...
q
SQLWARNING permet de couvrir toutes les erreurs d’état SQLSTATE débutant par 01
...
© Éditions Eyrolles
249
Partie II
Programmation procédurale
q
SQLEXCEPTION gère toutes les erreurs qui ne sont ni gérées par SQLWARNING ni par NOT
FOUND
...
Il est possible de grouper plusieurs déclarations d’exceptions, ainsi que de prévoir plusieurs
conditions pour une même exception
...
Par exemple, ERROR 1046 désigne la non sélection d’une base de
données (1046 devra être écrit en lieu et place de code_erreur_mysql)
...
L’exception serait ainsi manuellement déclenchée et pourrait être définie par le programmeur (par exemple, la condition PILOTE_TROP_JEUNE si l’âge d’un pilote est inférieur à
20 ans)
...
Étudions à présent les différents types d’exceptions en programmant des procédures simples
interrogeant la table Pilote illustrée à la figure 7-2
...
Gestion de NOT FOUND
Le tableau suivant décrit une procédure qui gère une erreur : aucun pilote n’est associé à la
compagnie de code passé en paramètre (NOT FOUND)
...
250
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
Tableau 7-8 Exception NOT FOUND traitée avec EXIT
Code MySQL
Commentaires
CREATE PROCEDURE bdsoutou
...
BEGIN
DECLARE EXIT HANDLER FOR NOT FOUND
SET flagNOTFOUND :=1 ;
SELECT nom INTO var1 FROM bdsoutou
...
Requête pouvant déclencher
l’exception prévue
...
Fin du bloc
...
Fin de la procédure
...
procException1('CAST')$
+--------------------------------------------------------+
| Resultat procException1
|
+--------------------------------------------------------+
| Le seul pilote de la compagnie CAST est Sonia Dietrich |
+--------------------------------------------------------+
Une autre exécution correcte de cette procédure (qui se déroute hors du bloc du fait de NOT
FOUND) est la suivante :
CALL bdsoutou
...
La procédure se termine
maintenant correctement si la requête retourne une seule ligne ou plusieurs (message personnalisé en sortie de bloc)
...
procException1
(IN p_comp VARCHAR(4))
BEGIN
DECLARE flagPlusDun BOOLEAN DEFAULT 0;
DECLARE flagNOTFOUND BOOLEAN DEFAULT 0;
DECLARE var1 VARCHAR(20);
Déclaration de la procédure et
des variables
...
Pilote
WHERE comp=p_comp;
SELECT CONCAT('Le seul pilote de la compagnie ',
p_comp,' est ',var1)
AS 'Resultat procException1';
END;
IF flagNOTFOUND THEN
SELECT CONCAT('Il n''y a pas de pilote pour la
compagnie ',p_comp)
AS 'Resultat procException1';
END IF;
IF flagPlusDun THEN
SELECT CONCAT('Il y a plusieurs pilotes pour la
compagnie ',p_comp)
AS 'Resultat procException1';
END IF;
END;
Bloc qui déclare les deux
exceptions
...
Affichage du résultat
...
Gestion des erreurs
...
La trace d’une exécution correcte de cette procédure (qui se déroute hors du bloc du fait de
plusieurs lignes retournées) est la suivante :
252
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
CALL bdsoutou
...
La procédure principale exécute le sous–programme, puis sort du bloc principal et se termine correctement
...
pasTrouve
(IN p_comp VARCHAR(4))
BEGIN
SELECT CONCAT('Il n''y a pas de pilote pour
la compagnie ',p_comp)
AS 'Resultat procpasTrouve';
END;
Codage du sous-programme
appelé lors de l’exception
...
procException1
(IN p_comp VARCHAR(4))
BEGIN
DECLARE var1 VARCHAR(20);
DECLARE EXIT HANDLER FOR NOT FOUND
CALL bdsoutou
...
Pilote
WHERE comp = p_comp;
Web
Procédure qui déclare
l’exception
...
Affichage du résultat
...
La trace d’une exécution correcte de cette procédure (qui se déroute vers le sous-programme
appelé du fait de NOT FOUND) est la suivante :
+-----------------------------------------------+
| Resultat procpasTrouve
|
+-----------------------------------------------+
| Il n'y a pas de pilote pour la compagnie RIEN |
+-----------------------------------------------+
Il est aisé de transposer ce raisonnement à plusieurs exceptions appelant différents sousprogrammes
...
Gestion de NOT FOUND
Le tableau suivant décrit la même procédure gérant l’erreur NOT FOUND
...
Tableau 7-11 Exception NOT FOUND traitée avec CONTINUE
Code MySQL
Commentaires
CREATE PROCEDURE bdsoutou
...
Pilote
WHERE comp=p_comp;
Déclaration de la procédure et
des variables
...
Bloc qui déclare l’exception
...
Affichage du résultat
...
Gestion d’une erreur particulière
Le tableau suivant décrit la même procédure qui gère en plus l’erreur Result consisted
of more than one row
...
254
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
Tableau 7-12 Exceptions 1172 et NOT FOUND traitées avec CONTINUE
Code MySQL
Commentaires
CREATE PROCEDURE bdsoutou
...
Pilote
WHERE comp=p_comp;
Web
Déclaration de la procédure et
des variables
...
Requête pouvant déclencher
l’exception prévue
...
SELECT CONCAT('Il n''y a pas de pilote pour la
compagnie ',p_comp)
AS 'Resultat procException1';
ELSEIF flagPlusDun THEN
SELECT CONCAT('Il y a plusieurs pilotes
pour la compagnie ',p_comp)
AS 'Resultat procException1';
ELSE
SELECT CONCAT('Le seul pilote de la compagnie Affichage du résultat
...
Gestion des autres erreurs (SQLEXCEPTION)
Si une erreur non prévue en tant qu’exception (dans les clauses DECLARE HANDLER) se
produisait, le programme se terminerait anormalement en renvoyant l’erreur en question
...
Dans notre exemple (sélection d’une colonne d’une table), seule une erreur « interne » pourrait éventuellement se produire (base de données ou table inexistante, colonne de la table
inexistante ou d’un type différent de VARCHAR(4) ou autre erreur système)
...
© Éditions Eyrolles
255
Partie II
Programmation procédurale
En d’autres termes, il faudra soit :
q
interrompre brusquement votre procédure avec différents cas d’erreurs, pour lister les
codes erreur générés en sortie ;
q
vous contenter de gérer globalement les autres exceptions, tout en ne sachant pas de quelles erreurs il s’agit
...
Tableau 7-13 Exceptions toutes traitées avec EXIT et SQLEXCEPTION
Web
Code MySQL
Commentaires
CREATE PROCEDURE bdsoutou
...
CREATE PROCEDURE bdsoutou
...
autreErreur()
BEGIN
SELECT 'Erreur mais laquelle?'
AS 'Resultat autreErreur';
END;
3 cas
CREATE PROCEDURE bdsoutou
...
tropdeLignes(p_comp);
DECLARE EXIT HANDLER FOR NOT FOUND
CALL bdsoutou
...
autreErreur();
SELECT nom INTO var1 FROM bdsoutou
...
Fin de la procédure
...
Affichage du résultat
...
procException1('AF')$
+-----------------------+
| Resultat autreErreur |
+-----------------------+
| Erreur mais laquelle? |
+-----------------------+
Même erreur sur différentes instructions
Plusieurs cas de figure sont possibles suivant qu’on désire maîtriser une exception ou terminer
toutes les exceptions avant la fin du sous-programme
...
La première requête extrait le nom du pilote de code passé en paramètre
...
Le sous-programme se termine correctement si les deux requêtes ne retournent
qu’un seul enregistrement
...
Le principe est d’utiliser une variable indiquant quelle est la requête qui a fait sortir du bloc
par l’exception levée
...
procException2('PL-1', 1000)$
+------------------------------------------------------+
| CONCAT('Le pilote de code ',p_brevet,' est ',v_nom) |
+------------------------------------------------------+
| Le pilote de code PL-1 est Gilles Laborde
|
+------------------------------------------------------+
+----------------------------------------------------------------+
| CONCAT('Le pilote ayant ',p_heures,' heures de vol est ',v_nom) |
+----------------------------------------------------------------+
| Le pilote ayant 1000 heures de vol est Florence Périssel
|
+----------------------------------------------------------------+
CALL bdsoutou
...
procException2
(IN p_brevet VARCHAR(6),IN p_heures DECIMAL(7,2))
BEGIN
DECLARE v_nom
VARCHAR(20);
DECLARE flagNOTFOUND BOOLEAN DEFAULT 0;
DECLARE v_requete
TINYINT;
BEGIN
DECLARE EXIT HANDLER FOR NOT FOUND SET flagNOTFOUND :=1 ;
SET v_requete := 1;
SELECT nom INTO v_nom FROM bdsoutou
...
Pilote
WHERE nbHVol = p_heures;
SELECT CONCAT('Le pilote ayant ',p_heures,
' heures de vol est ',v_nom);
END;
Bloc avec les requêtes
déclenchant potentiellement
une exception prévue
...
SELECT CONCAT('Pas de pilote de brevet : ',p_brevet);
ELSEIF v_requete = 2 THEN
SELECT CONCAT('Pas de pilote ayant ce nombre
d''heures de vol : ',p_heures);
END IF;
END IF;
END;
Dans cette procédure, une erreur sur la première requête interrompt le programme (après avoir
traité l’exception), et de ce fait la deuxième requête n’est pas évaluée
...
Gestion de plusieurs exceptions
Le tableau suivant décrit une procédure qui traite toutes les mêmes exceptions en séquence
...
Dans
cette procédure, les deux requêtes sont évaluées indépendamment du résultat retourné par
chacune d’elles
...
procException3
(IN p_brevet VARCHAR(6),IN p_heures DECIMAL(7,2))
BEGIN
DECLARE v_nom
VARCHAR(20);
DECLARE flagNOTFOUND BOOLEAN DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET flagNOTFOUND := 1 ;
SELECT nom INTO v_nom FROM bdsoutou
...
Pilote
WHERE nbHVol = p_heures;
IF flagNOTFOUND THEN
SELECT CONCAT('Pas de pilote ayant ce nombre d'
'heures de vol : ',p_heures);
ELSE
SELECT CONCAT('Le pilote ayant ',p_heures,
' heures de vol est ',v_nom);
END IF;
END;
Commentaires
Gestion de l’exception de
la première requête
...
L’exécution suivante de cette procédure déclenche les deux exceptions (ce qui n’était pas le
cas dans la procédure précédente)
...
procException3('PL-0', 500)$
+-----------------------------------------------+
| CONCAT('Pas de pilote de brevet : ',p_brevet) |
+-----------------------------------------------+
| Pas de pilote de brevet : PL-0
|
+-----------------------------------------------+
+-----------------------------------------------------------------+
| CONCAT('Pas de pilote ayant ce nombre d''heures de vol : ',p_heures) |
+-----------------------------------------------------------------+
| Pas de pilote ayant ce nombre d'heures de vol : 500
|
+-----------------------------------------------------------------+
Il resterait à programmer l’exception ERROR 1172 (Result consisted of more
than one row) pour gérer, au niveau de la seconde requête, l’extraction de plusieurs pilotes
© Éditions Eyrolles
259
Partie II
Programmation procédurale
ayant un même nombre d’heures de vol
...
Afin de déclarer d’autres exceptions, il faut consulter la liste des erreurs dans la documentation
officielle (Appendix B
...
Vous pouvez aussi écrire un bloc qui programme volontairement l’erreur pour voir, sous l’interface de commande, le numéro que MySQL renvoie
...
La syntaxe est la suivante :
Déclaration
DECLARE nomException CONDITION FOR
{SQLSTATE [VALUE] ‘valeur_sqlstate’ | code_erreur_mysql}
Il est ainsi possible de regrouper plusieurs types d’erreurs (avec SQLSTATE ou cibler une erreur
en particulier en indiquant le code erreur de MySQL)
...
Déclenchement
Considérons les deux tables suivantes
...
Programmons une procédure qui supprime une compagnie de
code passé en paramètre
...
Il s’agit de contrôler le programme si la compagnie à
détruire est encore rattachée à un enregistrement référencé dans la table Pilote
...
procExceptionNommee
(IN p_comp VARCHAR(4))
BEGIN
DECLARE flagerr BOOLEAN DEFAULT 0;
BEGIN
DECLARE erreur_ilResteUnPilote CONDITION
FOR SQLSTATE '23000' ;
DECLARE EXIT HANDLER
FOR erreur_ilResteUnPilote SET flagerr :=1;
SET AUTOCOMMIT=0;
DELETE FROM Compagnie WHERE comp = p_comp;
SELECT CONCAT('Compagnie ',p_comp, ' détruite')
AS 'Resultat procExceptionNommee';
END;
IF flagerr THEN
ROLLBACK;
SELECT CONCAT('Désolé, il reste encore un pilote à
la compagnie ',p_comp)
AS 'Resultat procExceptionNommee';
ELSE
COMMIT;
END IF;
END;
Commentaires
Déclaration de l’exception
nommée
...
Gestion de l’exception
...
Notez que si on appelle cette
procédure en passant en paramètre une compagnie inexistante, le sous-programme se termine
normalement sans passer dans la section d’erreur
...
procExceptionNommee('AF')$
+-----------------------------------------------------+
| Resultat procExceptionNommee
|
+-----------------------------------------------------+
| Désolé, il reste encore un pilote à la compagnie AF |
+-----------------------------------------------------+
CALL bdsoutou
...
Comme nous le
verrons, ils sont limitatifs en termes de fonctionnalités et relativement instables (P
...
0 Triggers : « Triggers are very
new
...
… Do not try triggers with a database that has important data in it… »)
...
Prudence donc avec vos données
...
Songez qu’avant la version 5
...
10, les
déclencheurs ne pouvaient même pas accéder à la base !
Généralités
D’un point de vue général et sans parler de MySQL, la plupart des déclencheurs (triggers)
peuvent être vus comme des sous-programmes résidents associés à un événement particulier
(insertion, modification d’une ou de plusieurs colonnes, suppression) sur une table (ou une
vue)
...
Pour certains
SGBD, il existe d’autres types de déclencheurs que ceux associés à une table (ou vue) afin de
répondre à des événements qui ne concernent pas les données (exemple : connexion d’un
utilisateur particulier, suppression d’une table, démarrage ou arrêt du serveur, déconnexion
d’un utilisateur, etc
...
On dit que le déclencheur « se déclenche » (l’anglais le
traduit mieux : fired trigger)
...
Par exemple, la condition : une compagnie ne fait voler
un pilote que s’il a totalisé plus de 60 heures de vol dans les 2 derniers mois, sur le type
d’appareil du vol en question, ne pourra pas être programmée par une contrainte et nécessitera l’utilisation d’un déclencheur
...
q
Renforcer des aspects de sécurité et d’audit
...
262
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
En théorie, les événements déclencheurs peuvent être :
q
une instruction INSERT, UPDATE, ou DELETE sur une table (ou vue)
...
On parle
de déclencheurs LDD ;
q
le démarrage ou l’arrêt de la base (startup ou shutdown), une erreur spécifique (not found,
duplicate key, etc
...
On parle de
déclencheurs d’instances
...
Mécanisme général
Auparavant considérés au niveau table, les déclencheurs sont désormais attachés, à plus juste
titre, au niveau database
...
En revanche, différentes bases peuvent héberger un déclencheur de
même nom
...
Il faut d’abord le coder (comme un sous-programme),
puis le compiler (il est pour l’instant stocké indépendamment de la table, mais il devrait y être
inclus dans les prochaines versions)
...
Figure 7-6 Mécanisme des déclencheurs
1
...
Événement e1
sur Tab1
...
Actions codées dans trig1
Syntaxe
Pour pouvoir créer un déclencheur, vous devez disposer du privilège SUPER (le privilège
CREATE TRIGGER est à venir)
...
La syntaxe
de création d’un déclencheur est la suivante :
© Éditions Eyrolles
263
Partie II
Programmation procédurale
CREATE TRIGGER nomDéclencheur
{ BEFORE | AFTER } { DELETE | INSERT | UPDATE }
ON nomTable
FOR EACH ROW
{ instruction; |
[etiquette:] BEGIN
instructions;
END [etiquette]; }
Les options de cette commande sont les suivantes :
q
BEFORE | AFTER précise la chronologie entre l’action à réaliser par le déclencheur LMD et
la réalisation de l’événement (BEFORE INSERT exécutera le déclencheur avant de réaliser
l’insertion)
...
– Pour DELETE, le déclencheur examine les événements DELETE et REPLACE
...
SELECT, LOAD DATA, et REPLACE
...
q
ON nomTable spécifie la table associée au déclencheur LMD
...
q
instruction ou instructions compose le corps du code du déclencheur
...
En revanche, il est possible d’avoir deux déclencheurs distincts sur la même action,
dans une table donnée (un déclencheur pour BEFORE UPDATE et un autre pour AFTER UPDATE
par exemple)
...
Étudions à présent plus précisément les caractéristiques du seul type de déclencheur qu’il est
actuellement possible de programmer
...
264
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
L’exécution est, pour l’heure, dépendante du nombre de lignes touchées par l’événement
...
Ils sont pratiques quand on désire utiliser autant de fois le déclencheur qu’il y
a de lignes concernées par une mise à jour
...
Pour ce faire, il faudrait ne pas indiquer la directive FOR EACH ROW, ou préciser FOR
EACH STATEMENT à la place (à confirmer avec une prochaine version incluant cette
extension)
...
Le
tableau suivant explique ce mécanisme :
Tableau 7-17 Exécution d’un déclencheur LMD
Nature de
l’événement
État (statement trigger)
sans FOR EACH ROW
Ligne (row trigger)
avec FOR EACH ROW
BEFORE
Exécution une fois avant la mise à jour
...
AFTER
Exécution une fois après la mise à jour
...
Seuls les déclencheurs de lignes peuvent accéder aux anciennes et aux nouvelles valeurs des
colonnes de la ligne affectée par la mise à jour prévue par l’événement
...
Ce sont des extensions de MySQL à la norme SQL
(MySQL suit ainsi Oracle dans ce domaine qui propose :OLD et :NEW)
...
Quand utiliser la directive OLD ?
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
...
Considérons l’exemple suivant, et programmons la règle de gestion tout pilote qui perd une
qualification doit voir son compteur automatiquement décrémenter
...
© Éditions Eyrolles
265
Partie II
Programmation procédurale
Figure 7-7 Principe du déclencheur TrigDelQualif
Pilote
BREVET
NOM
NBHVOL
------------------------PL-1
P
...
Lebur
X
...
On utilise un déclencheur FOR
EACH ROW, car s’il se produit une suppression de toute la table (DELETE FROM Qualifications;), on exécutera autant de fois le déclencheur qu’il y a de lignes détruites
...
L’accès aux colonnes de ce pseudo-enregistrement
dans le corps du déclencheur se fait par la notation pointée
...
brevet ;
END;
Déclaration de l’événement déclencheur
...
Mise à jour du pilote concerné par la
suppression
...
Par ailleurs, la table Qualifications ne contient plus que trois
enregistrements
...
Caboche | 450
...
Lebur
| 3400
...
Leclercq | 900
...
L’accès aux colonnes de ce pseudo-enregistrement dans le corps du déclencheur se fait par la notation pointée
...
Programmons le déclencheur
TrigInsQualif qui surveille les insertions sur la table Qualifications et augmente de
un la colonne nbQualif pour le pilote concerné
...
C aboche
G
...
Leclercq
NBHVOL
---------450
3400
900
TypeAvion
TYPA NOMTYPE
---- -------------------------A320 Biréacteur Airbus 320
A330 Biréacteur Airbus 330
A340 Quadriréacteur Airbus 340
A380 Big -Qua driréacteur 380
COMP
NBQUALIF
---- ---------AF
3
AF
1
SING
1
3
+1
Qualifications
BREVET TYPA EXPIRE
------ ---- -------PL-1
A340 22/06/05
PL-1
A330 05/02/05
PL-1
A320 16/01/04
PL-2
A320 18/01/04
PL-3
A330 22/01/06
Déclencheur
TrigInsQualif
1
2
INSERT
PL -2 A380
20/06/06
NEW
L’événement déclencheur est ici AFTER INSERT, car il faudra s’assurer, avant de faire
l’insertion, que le code du pilote et celui de l’avion sont corrects (existant dans les tables
« père »)
...
Le code minimal de ce déclencheur (on ne prend en compte aucune erreur potentielle) est
décrit dans le tableau suivant :
© Éditions Eyrolles
267
Partie II
Programmation procédurale
Tableau 7-20 Déclencheur après insertion
Déclencheur
Commentaires
CREATE TRIGGER TrigInsQualif
AFTER INSERT ON Qualifications
FOR EACH ROW
BEGIN
UPDATE Pilote SET nbQualif = nbQualif + 1
WHERE brevet = NEW
...
Corps du déclencheur
...
En considérant les données initiales des tables, le test de ce déclencheur (réalisé le
20 décembre 2005) sous l’interface de commande est le suivant :
Tableau 7-21 Test du déclencheur AFTER INSERT
Web
Événement déclencheur
INSERT INTO
Qualifications VALUES
('PL-2', 'A380',
SYSDATE());
Résultat
SELECT * FROM Qualifications $
+--------+------+------------+
| brevet | typa | expire
|
+--------+------+------------+
| PL-1
| A340 | 2005-06-22 |
| PL-1
| A330 | 2005-02-05 |
| PL-1
| A320 | 2004-01-16 |
| PL-2
| A320 | 2004-01-18 |
| PL-3
| A330 | 2006-01-22 |
| PL-2
| A380 | 2005-12-20 |
+--------+------+------------+
SELECT * FROM Pilote$
+--------+-------------+---------+-------+----------+
| brevet | nom
| nbHVol | compa | nbQualif |
+--------+-------------+---------+-------+----------+
| PL-1
| P
...
00 | AF
|
3 |
| PL-2
| G
...
00 | AF
|
2 |
| PL-3
| X
...
00 | SING |
1 |
+--------+-------------+---------+-------+----------+
Quand utiliser à la fois les directives NEW et OLD ?
Seuls les déclencheurs de type UPDATE FOR EACH ROW permettent de manipuler à la fois les
directives NEW et OLD
...
L’accès aux anciennes valeurs se fera par la
notation pointée du pseudo-enregistrement OLD
...
La figure suivante illustre ce mécanisme dans le cas de la modification de la colonne brevet du
dernier enregistrement de la table Qualifications
...
268
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
Figure 7-9 Principe du déclencheur TrigUpdQualif
Pilote
BREVET
-----PL-1
PL-2
PL-3
NOM
NBHVOL COMP
NBQUALIF
-------------------- ---------- ---- ---------P
...
Lebur
3400 AF
1
X
...
Le code minimal de ce déclencheur est décrit dans le tableau suivant :
Tableau 7-22 Déclencheur après modification
Déclencheur
Commentaires
CREATE TRIGGER TrigUpdQualif
AFTER UPDATE ON Qualifications
FOR EACH ROW
BEGIN
UPDATE Pilote
SET nbQualif = nbQualif + 1
WHERE brevet = NEW
...
brevet ;
END;
Web
Déclaration de l’événement déclencheur
...
Mise à jour des pilotes concernés par
la modification de la qualification
...
Caboche | 450
...
Lebur
| 3400
...
Leclercq | 900
...
Retenez que seuls les déclencheurs UPDATE peuvent
manipuler à bon escient les deux types de directives
...
colonne
NEW
...
Nouvelle valeur
...
Nouvelle valeur
...
Impossible
...
Une colonne préfixée de NEW ne peut être accessible qu’à l’aide du privilège SELECT associé
...
• Un déclencheur ne peut pas lancer une procédure cataloguée retournant des données au
client (traces avec SELECT) ou utilisant du SQL dynamique (étudié plus loin)
...
• Les procédures appelées ne peuvent constituer aucune transaction (oubliez donc de pouvoir faire START TRANSACTION, COMMIT, et ROLLBACK)
...
Le
sous-programme ajoute simplement une ligne dans la table Trace
...
procTrigg(IN param DATETIME)
BEGIN
INSERT INTO Trace VALUES
(CONCAT('Insertion pilote, appel de bdsoutou
...
espionAjoutPilote
BEFORE INSERT ON Pilote
FOR EACH ROW
BEGIN
CALL bdsoutou
...
La trace d’exécution en considérant les données initiales des tables est la suivante :
mysql> (INSERT INTO Pilote VALUES ('PL-4', 'C
...
04 sec)
mysql> SELECT * FROM Pilote$
+--------+-------------+---------+-------+----------+
| brevet | nom
| nbHVol | compa | nbQualif |
+--------+-------------+---------+-------+----------+
| PL-1
| P
...
00 | AF
|
3 |
| PL-2
| G
...
00 | AF
|
1 |
| PL-3
| X
...
00 | SING |
1 |
| PL-4
| C
...
00 | AF
|
0 |
+--------+-------------+---------+-------+----------+
© Éditions Eyrolles
271
Partie II
Programmation procédurale
mysql> SELECT * FROM Trace$
+-----------------------------------------------------------------+
| col
|
+-----------------------------------------------------------------+
| Insertion pilote, appel de bdsoutou
...
Ils
sont désormais reconnus à juste titre au niveau database
...
La requête suivante interroge cette vue et permet de retrouver les noms et les caractéristiques
relatives aux événements déclencheurs des trois triggers de la base de données bdsoutou
...
TRIGGERS
WHERE TRIGGER_SCHEMA='bdsoutou';
+---------------+----------------+-----------+---------------+----------+
| TRIGGER_NAME | Table
| Evenement | ACTION_TIMING | Base
|
+---------------+----------------+-----------+---------------+----------+
| TrigInsQualif | Qualifications | INSERT
| AFTER
| bdsoutou |
| TrigUpdQualif | Qualifications | UPDATE
| AFTER
| bdsoutou |
| TriDelQualif | Qualifications | DELETE
| AFTER
| bdsoutou |
+---------------+----------------+-----------+---------------+----------+
Notez que MySQL utilise :
q
la colonne TRIGGER_NAME pour désigner le nom du déclencheur d’une database ;
q
la colonne TRIGGER_SCHEMA pour désigner le nom de la base de données à laquelle il
appartient ;
q
les colonnes EVENT_OBJECT_TABLE et EVENT_OBJECT_SCHEMA pour désigner
respectivement le nom de la table qui accueille ce déclencheur ainsi que la base de données
qui la contient (elle peut être différente de celle du déclencheur, ici nous raisonnons sur la
même) ;
q
la colonne EVENT_MANIPULATION pour désigner l’événement déclencheur ;
q
la colonne ACTION_TIMING pour préciser la chronologie de l’événement déclencheur
...
TRIGGERS
WHERE TRIGGER_SCHEMA='bdsoutou' AND EVENT_OBJECT_TABLE='Qualifications'
AND EVENT_MANIPULATION='UPDATE' AND ACTION_TIMING='AFTER';
+-----------------------------------------------------------------------------+
| ACTION_STATEMENT
|
+-----------------------------------------------------------------------------+
|BEGIN
UPDATE Pilote SET nbQualif = nbQualif + 1 WHERE brevet = NEW
...
brevet;
END
|
+-----------------------------------------------------------------------------+
Remarquons que MySQL utilise la colonne ACTION_STATEMENT pour contenir le corps du
déclencheur (visible aussi par SHOW TRIGGERS)
...
Les colonnes ACTION_REFERENCE_OLD_ROW et ACTION_REFERENCE_NEW_ROW contiennent,
pour l’instant, toujours respectivement 'OLD' et 'NEW' (il n’est pas encore possible de renommer
ces identificateurs)
...
Les deux premières colonnes sont relatives à la notion
de catalogue, la suivante a la possibilité de conditionner un déclencheur (clause WHEN d’Oracle), la dernière contiendrait le moment de création du déclencheur
...
Nous avons étudié au chapitre 5 la possibilité d’en programmer à l’aide de vues
...
Attention, il n’est pas toujours possible
d’utiliser un déclencheur pour valider une contrainte de vérification
...
Vue simulant la contrainte CHECK) qui
décrit la table Pilote et la contrainte vérifiant qu’un pilote :
q
ne peut être commandant de bord qu’à la condition qu’il ait entre 1 000 et 4 000 heures de
vol ;
q
ne peut être copilote qu’à la condition qu’il ait entre 100 et 1 000 heures de vol ;
q
ne peut être instructeur qu’à partir de 3 000 heures de vol
...
Ici, on choisit de forcer la valeur de la
colonne grade pour conserver la cohérence avec les conditions initiales
...
BEGIN
IF ( NEW
...
nbHVol <1000)) THEN
SET NEW
...
grade = 'CDB' AND ( NEW
...
grade := 'INST';
END IF;
IF (NEW
...
nbHVol >1000)) THEN
SET NEW
...
grade = 'INST' AND ( NEW
...
nbHVol <100) THEN
SET NEW
...
Test des conditions et mise à
jour éventuelle de la nouvelle
valeur à insérer au niveau de
la colonne grade
...
Le test de ce
déclencheur est le suivant
...
Tableau 7-27 Test du déclencheur BEFORE INSERT
Insertions valides
Insertions non valides
INSERT INTO Pilote VALUES
INSERT INTO Pilote VALUES
('PL-1','Daniel Vielle',1000,'CDB');
('PL-5','Trop jeune', 100,'CDB' );
INSERT INTO Pilote VALUES
('PL-2','Benoit Treihlou',450,'COPI'); INSERT INTO Pilote VALUES
INSERT INTO Pilote VALUES
('PL-6','Inexperimente', 2999,'INST' );
('PL-3','Pierre Filoux',9000,'INST');
INSERT INTO Pilote VALUES
('PL-4','Philippe Minier',1000,'COPI');
SELECT * FROM Pilote;
+--------+-----------------+---------+-------+
| brevet | nom
| nbHVol | grade |
+--------+-----------------+---------+-------+
| PL-1
| Daniel Vielle
| 1000
...
00 | COPI |
| PL-3
| Pierre Filoux
| 9000
...
00 | COPI |
| PL-5
| Trop jeune
| 100
...
00 | NULL |
+--------+-----------------+---------+-------+
274
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
Invalidation dans le déclencheur
Une fonctionnalité importante des déclencheurs consiste à pouvoir invalider l’événement qui
a déclenché l’action
...
Ces cas concernent les déclencheurs lignes
de type BEFORE, puisqu’il faudra vérifier des conditions dans le corps du déclencheur avant
éventuellement d’accepter l’événement
...
Cela signifie que l’on peut changer un enregistrement avant de
l’insérer
...
La valeur actualisée de la séquence ne sera effective que lors de
l’insertion
...
Principe
Sans parler de MySQL, 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é
...
Il n’est pas non plus possible d’utiliser ROLLBACK dans un déclencheur (ERROR 1422
(HY000): Explicit or implicit commit is not allowed in stored function
or trigger)
...
Il faut une erreur sémantiquement correcte qui pose problème à
l’exécution (NULL dans une clé primaire)
...
© Éditions Eyrolles
275
Partie II
Programmation procédurale
Exemple
Considérons à nouveau l’exemple précédent et programmons la contrainte que tout pilote ne
peut être qualifié sur plus de trois types d’appareils
...
L’événement déclencheur est ici BEFORE INSERT, car il faudra s’assurer de la condition
avant d’autoriser
...
Tableau 7-28 Déclencheur avant insertion
Déclencheur
Commentaires
CREATE TRIGGER TrigInsQualif
BEFORE INSERT ON Qualifications
FOR EACH ROW
BEGIN
DECLARE v_compteur TINYINT(1);
DECLARE v_nom VARCHAR(30);
SELECT nbQualif, nom INTO v_compteur, v_nom
FROM Pilote WHERE brevet = NEW
...
brevet;
ELSE
Déclaration de l’événement déclencheur
...
Test de la condition
...
Erreur volontaire
...
On remarque que
le premier INSERT est bien évité (le pilote PL-1 a déjà trois qualifications)
...
La seconde insertion, en revanche, est bien effectuée (le pilote PL3 n’a qu’une seule qualification)
...
09 sec)
-- fait l'INSERT dans Qualifications et met à jour
-- la table Pilote (colonne nbQualif)
Citons le travail de Roland Bouman, un Hollandais qui a écrit une fonction (UDF user-defined
function) en C, qui se comporte comme une fonction native (built-in) simulant le RAISE_
APPLICATION_ERROR
...
blogspot
...
html)
...
Si on tente d’y parvenir en mise à jour (INSERT,
UPDATE ou DELETE), l’erreur est « ERROR 1442 (HY000): Can't update table
'xxx' in stored function/trigger because it is already used by
statement which invoked this stored function/trigger »
...
Tableau 7-30 Déclencheur (table mutante)
Web
Déclencheur
Trace
SET @vs_nombre=0$
SELECT @vs_nombre$
+------------+
| @vs_nombre |
+------------+
| 0
|
+------------+
INSERT INTO Trace
VALUES ('Test TrigMutant')$
SELECT @vs_nombre$
+------------+
| @vs_nombre |
+------------+
| 1
|
+------------+
CREATE TRIGGER TrigMutant
AFTER INSERT ON Trace FOR EACH ROW
BEGIN
SELECT COUNT(*) INTO @vs_nombre
FROM Trace;
END;
$
© Éditions Eyrolles
277
Partie II
Programmation procédurale
Restrictions
Pour en finir avec les déclencheurs, je vais terminer la « litanie »…
• Pas de déclencheur sur une table temporaire ou une vue, ou sur un événement système
(connexion, arrêt de la base, etc
...
• Les déclencheurs état (statement trigger) ne sont pas encore reconnus
...
• Les déclencheurs ne peuvent être écrits qu’avec le langage procédural de MySQL (qui sert
aussi aux procédures et aux fonctions cataloguées)
...
• Les déclencheurs ne sont pas activés par des actions en cascade résultant d’opérations sur
des clés primaires ou étrangères (CASCADE voir le chapitre 2)
...
La syntaxe de l’instruction DROP TRIGGER est la suivante :
DROP TRIGGER [nomBase
...
Le fait de détruire une table a pour conséquence d’effacer aussi tous les déclencheurs qui lui
sont associés
...
Par conséquent, les déclencheurs passent ainsi tous « à la casserole »
...
En plus des directives SQL (LMD, LID), il est
possible de construire automatiquement certaines instructions SQL du LDD
...
Net (MySQL Connector/NET) ou PHP par
une API écrite en C (mysqli extension)
...
Il sera aussi permis de construire automatiquement une requête
SQL en fonction des choix d’un utilisateur
...
Une instruction SQL dynamique est stockée en tant que chaîne de caractères qui sera évaluée
à l’exécution et non à la compilation (en opposition aux instructions SQL statiques qui
peuplent la majorité des sous-programmes)
...
Les états préparés ne peuvent être utilisés dans un déclencheur (seuls les sous-programmes
peuvent en bénéficier pour l’heure)
...
;
exécute l’expression (ou les expressions) sans retourner aucun résultat
...
mais sans renvoi de résultat
...
Syntaxe
La construction dynamique d’instructions SQL (prepared statements) est basée sur les trois
directives suivantes :
PREPARE nomEtat FROM étatPréparé;
EXECUTE nomEtat [USING @var1 [, @var2]
...
q
étatPréparé est soit une chaîne soit une variable de session contenant le texte de
l’instruction SQL construite (instruction simple, pas d’instructions multiples)
...
q
L’instruction EXECUTE lance l’ordre paramétré avec éventuellement la clause USING qui
reliera les paramètres aux variables de session
...
© Éditions Eyrolles
279
Partie II
Programmation procédurale
Exemples
Considérons la table Avion contenant deux enregistrements
...
Tableau 7-31 Utilisation de DELETE
Web
Code MySQL
Commentaires
SET @vs_nbhVol = 1000 $
CREATE PROCEDURE bdsoutou
...
Préparation de l’ordre
...
L’appel (CALL bdsoutou
...
Instruction SELECT
Le tableau suivant décrit 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)
...
Tableau 7-32 Utilisation de SELECT
Web
Code MySQL
Commentaires
SET @vs_chaine =
'SELECT * FROM Avion WHERE nbHVol=?'$
SET @vs_nbhVol = 1000$
CREATE PROCEDURE bdsoutou
...
Préparation de l’ordre
...
L’appel de cette procédure aura pour conséquence d’extraire l’avion immatriculé 'F-GLFS'
...
Notez qu’il n’est pas besoin de doubler
le guillemet dans la spécification du deuxième placeholder : paramètre immat (bien qu’il
s’agisse d’une chaîne de caractères)
...
1$
Web
Déclaration des variables de session
...
sousProg()
BEGIN
PREPARE etat FROM @vs_chaine;
EXECUTE etat USING @vs_pourcent,@vs_immat;
DROP PREPARE etat;
END;
Préparation de l’ordre
...
L’appel de cette procédure aura pour conséquence d’aumenter de 10 % le nombre d’heures de
vol de l’avion immatriculé 'F-GLFS'
...
, dans une instruction, de sorte à construire
un ordre dynamiquement
...
• dans la clause VALUES pour un INSERT
...
N’oubliez pas de
doubler chaque guillemet pour affecter une telle chaîne de caractères dans une variable de session
...
SELECT ? FROM table WHERE
...
SELECT * FROM table WHERE ? > 1000
INSERT INTO table VALUES (?,?,?,?)
INSERT INTO ? VALUES(''F-FRTY'',?,?,?)
UPDATE table SET col=? WHERE col =?
...
UPDATE ? SET
...
DELETE FROM table WHERE ? =
...
Afin de pallier cette limitation, il faut construire l’instruction dynamique à l’aide de la fonction CONCAT en incluant éventuellement des placeholders aux endroits permis
...
Le nom de la seconde colonne de la table (ici de type INT)
est passé en second paramètre de la procédure
...
sousProg
(IN v_param1 VARCHAR(10),
IN v_param2 VARCHAR(10))
Construction de la chaîne :
BEGIN
SET @vs_chaine := CONCAT
‘CREATE TABLE IF NOT EXISTS
( 'CREATE TABLE IF NOT EXISTS
bdsoutou
...
',v_param1,' (immat CHAR(4), ' CHAR(4),
,v_param2,' INT)') ;
v_param2 INT)’
PREPARE etat FROM @vs_chaine;
EXECUTE etat;
Création de la table
...
La commande
DESCRIBE confirme la structure de la nouvelle table
...
sousProg('Helico','turbine')$
Query OK, 0 rows affected (0
...
Helico $
282
© Éditions Eyrolles
chapitre n° 7
Programmation avancée
+---------+---------+------+-----+---------+-------+
| Field
| Type
| Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| immat
| char(4) | YES |
| NULL
|
|
| turbine | int(11) | YES |
| NULL
|
|
+---------+---------+------+-----+---------+-------+
2 rows in set (0
...
Cette condition fait intervenir un paramètre (placeholder)
valant ici 'F-GLFS'
...
sousProg
(IN v_param1 CHAR(6), IN v_param2 CHAR(6),
IN v_param3 CHAR(5), IN v_param4 CHAR(5))
BEGIN
SET @vs_immat := 'F-GLFS';
SET @vs_chaine :=
CONCAT( 'SELECT ',v_param1,',',v_param2,
' FROM bdsoutou
...
Avion
WHERE immat=?’
Exécution de la requête paramétrée
...
CALL bdsoutou
...
00 |
+--------+---------+
1 row in set (0
...
01 sec)
© Éditions Eyrolles
283
Partie II
Programmation procédurale
Exercices
L’objectif de ces exercices est d’écrire des sous-programmes MySQL manipulant des curseurs
et gérant des exceptions sur la base de données Parc informatique
...
1
Curseur
On désire connaître, pour chaque logiciel installé, le temps (nombre de jours entier décimal) passé
entre l’achat et l’installation
...
Utiliser une table test
...
Écrire la procédure calculTemps pour programmer ce processus
...
Trace à produire en sortie :
+------------------------------------------------------------------+
| message
|
+------------------------------------------------------------------+
| Logiciel Oracle 6 sur Poste 2 attente 2924 jour(s)
...
|
| …
|
| Logiciel I
...
S
...
|
| En format TIME étendu 3876 j 10:59:17
|
| …
|
+------------------------------------------------------------------+
7
...
La transaction doit enregistrer dans un premier
temps le nouveau logiciel, puis les différentes installations sur tous les postes du segment de même
type que celui du logiciel acheté
...
Penser à mettre à jour la
colonne delai comme programmé précédemment
...
Trace
...
L’état de sortie doit être
le suivant
...
Ne programmer le COMMIT qu’une fois la procédure bien testée
...
120
...
9', 'PCWS', 999
...
3
Exceptions
Modifier la procédure installLogSeg afin de prendre en compte quelques-unes des exceptions
potentielles :
•
numéro de segment inconnu (erreur NOT FOUND) ;
•
numéro de logiciel déjà présent (ERROR 1062 Duplicate entry) ;
•
type du logiciel inconnu (ERROR 1452 Cannot add or update a child row) ;
•
date d’achat postérieure à celle du jour (se servir du même calcul que pour la colonne delai de
l’exercice précédent) ;
•
aucune installation réalisée, car pas de poste de travail de ce type (erreur utilisateur pas_
install_possible)
...
9',
'PCWS', 999
...
120
...
9', 'PCWS', 999
...
120
...
0)$
--date d’achat plus grande que celle du jour ?
CALL installLogSeg('130
...
80', 'log98','Mozilla', '2010-11-04', '1',
'PCWS', 100
...
120
...
120
...
3', 'PCWS', 90)$
© Éditions Eyrolles
285
Partie II
Programmation procédurale
7
...
Prévoir les cas de désinstallation d’un logiciel ( AFTER DELETE) sur un
poste, et d’installation (AFTER INSERT) d’un logiciel sur un autre
...
Écrire le déclencheur Trig_AU_Salle sur la table Salle qui met à jour automatiquement la
colonne nbPoste de la table Segment après la modification de la colonne nbPoste
...
Ajouter un poste pour vérifier le rafraîchissement des deux tables
(Salle et Segment)
...
Programmation de contraintes
Écrire le déclencheur Trig_BI_Installer sur la table Installer permettant de contrôler, avant
chaque nouvelle installation, que le type du logiciel correspond au type du poste, et que la date
d’installation est soit nulle soit postérieure à la date d’achat
...
q
Connector/ODBC (Open DataBase Connectivity) pour Windows, Linux, Mac OS X, et
Unix ;
Connector/J pour toute plate-forme Java en utilisant JDBC (Java DataBase
Connectivity) ;
Connector/Net pour toute plate-forme
...
q
Ce chapitre explique l’utilisation de l’API JDBC 3
...
q
JDBC avec Connector/J
L’interface JDBC initialement programmée par Sun, appelée aussi « passerelle » ou « API »,
est composée d’un ensemble de classes permettant le dialogue entre une application Java et
une source de données compatible SQL (tables relationnelles en général, mais aussi données
issues d’un fichier texte ou d’un classeur Excel par exemple)
...
0 que MySQL
fournit gratuitement est appelée Connector/J
...
La communication est réalisée en mode client-serveur
déconnecté et s’effectue en plusieurs étapes :
q
connexion à la base de données ;
q
émissions d’instructions SQL et exploitation des résultats provenant de la base de
données ;
q
déconnexion de la base
...
© Éditions Eyrolles
289
Partie III
Langages et outils
Classification des pilotes (drivers)
Un pilote (driver) JDBC est une couche logicielle chargée d’assurer la liaison entre l’application
Java (cliente) et le SGBD (serveur)
...
Le client est dit « épais », puisque le pilote JDBC convertit les appels Java
en appels ODBC avant de les exécuter
...
q
Les pilotes de type 2 (Native-API Partly-Java Driver) utilisent un pilote fourni par le constructeur de la base de données (natif)
...
En effet, les commandes JDBC sont toutes converties en appels natifs du SGBD considéré
...
q
Les pilotes de type 3 (Net Protocol All-Java Driver) utilisent un pilote générique natif écrit
en Java
...
Cette approche convient pour des sources de données hétérogènes
...
Le client est
léger car il ne nécessite aucune couche logicielle supplémentaire
...
Cette approche est la plus simple, mais pas
forcément la plus puissante ; elle convient pour tous les types d’architectures
...
Driver
IBM
Driver
IBM
BD
BD
Le choix du pilote n’a pas d’influence majeure sur la programmation
...
En d’autres termes, si vous avez une application déjà écrite et que
290
© Éditions Eyrolles
chapitre n° 8
Utilisation avec Java
vous décidez de changer le type du pilote – soit que la source de données migre de MySQL à
Access, à Oracle ou à SQL Server par exemple, soit que vous optiez pour un autre pilote en
conservant votre source de données –, seules quelques instructions devront être réécrites
...
Le paquetage java
...
0 de JDBC est composée de classes et d’interfaces situées dans le paquetage
java
...
MySQL propose également une API propriétaire (qui redéfinit et étend
celle de Sun)
...
Tableau 8-1 L’API JDBC 3
...
sql
...
sql
...
java
...
Statement
java
...
PreparedStatement
java
...
CallableStatement
Construction d’ordres SQL
...
sql
...
java
...
DriverManager
Gestion des pilotes de connexion
...
sql
...
java
...
DatabaseMetaData
java
...
ResultSetetaData
Gestion des méta-informations (description de la base de
données, des tables…)
...
sql
...
Structure d’un programme
La structure d’un programme Java utilisant JDBC comprend successivement les phases :
d’importation de paquetages ;
q
de chargement d’un pilote ;
q
de création d’une ou de plusieurs connexions ;
de création d’un ou de plusieurs états ;
q
d’émission d’instructions SQL sur ces états ;
q
de fermeture des objets créés
...
java) décrit la syntaxe du plus simple programme JDBC
...
q
© Éditions Eyrolles
291
Partie III
Langages et outils
Tableau 8-2 Programme de test de connexion JDBC
Web
Code Java
Commentaires
import java
...
*;
public class JDBCTest
{public static void main(String[] args)
throws SQLException, Exception
{
try
{ System
...
println
("Initialisation de la connexion");
Class
...
mysql
...
Driver")
...
out
...
toString()); }
try
{ Connection cx = DriverManager
...
createStatement ();
ResultSet rset = etat
...
next ())
System
...
println("Nous sommes le : "+
rset
...
out
...
err
...
Classe ayant une méthode main
...
Création d’une connexion
...
Extraction de la date courante
...
Gestion des erreurs
...
Nous détaillerons en
fin de section le traitement des exceptions
...
Le JDK est en général installé dans C:\j2sdk1
...
La variable CLASSPATH doit inclure le paquetage JDBC (fichier
...
Pour ma part, j’ai dézippé le fichier mysql-connector-java-3
...
12
...
q
292
© Éditions Eyrolles
chapitre n° 8
Utilisation avec Java
Vous pouvez tester votre environnement en utilisant le fichier JDBCTest
...
Si vous utilisez l’outil JCreator, configurez la variable CLASSPATH de la manière suivante : Configure/Options/JDK Profiles, clic sur la version du JDK, puis Edit, onglet Classes,
faire Add Archive et choisir le fichier jar (pour mon cas mysql-connector-java3
...
12-bin
...
Figure 8-2 Interface JCreator
Cet exemple décrit le code nécessaire à la connexion à votre base (il faudra modifier le nom de
la base, le nom et le mot de passe de l’utilisateur) et doit renvoyer les messages suivants :
Initialisation de la connexion
Nous sommes le : date et heure courante
JDBC correctement configuré
Connexion à une base
La connexion à une base de données est rendue possible par l’utilisation de la classe DriverManager et de l’interface Connection
...
lang
...
forName
...
getConnection(chaîneConnexion);
Pour MySQL, nous verrons que le paramètre chaîneConnexion représente une variable
dont une syntaxe simplifiée est de type :
jdbc:mysql://[host][:port]/[database][?user][=nomUtil][&password][=motPasse]
Cette chaîne permettra de désigner la base et d’identifier l’utilisateur
...
La figure suivante
illustre les parties du panneau de configuration Windows qui permettent de désigner une base
Access
...
MDB) est située dans un répertoire sous
l’unité de disque D:\ et désignée par le DSN (Data Source Name) sourcebaseGTR :
Figure 8-3 Source de données ODBC
Le code suivant (TestJDBCODBC
...
Le DSN est noté en gras dans le script
...
sql
...
forName("sun
...
odbc
...
out
...
getConnection
("jdbc:odbc:sourcebaseGTR","","");
...
Classe ayant une
méthode main
...
Connexion à la base
Access
...
© Éditions Eyrolles
chapitre n° 8
Utilisation avec Java
Base MySQL
Seules les phases de chargement de pilote et de création de la connexion changent
...
forName()
...
mysql
...
Driver
...
Tableau 8-4 Chargement du pilote MySQL
Code Java
Commentaires
try
{ Class
...
mysql
...
Driver")
...
out
...
toString()); }
try
{ Connection cx = DriverManager
...
}
catch(SQLException ex)
{ System
...
println("Erreur : "+ex); }
Chargement du pilote
MySQL
...
Gestion des erreurs
...
Nous détaillerons l’invocation de certaines de ces méthodes à l’aide des exemples des
sections suivantes
...
prepareStatement(String)
Précompile un ordre SQL acceptant des paramètres et pouvant
être exécuté plusieurs fois
...
void setAutoCommit(boolean)
Positionne ou non le commit automatique
...
void rollback()
Invalide la transaction
...
295
Partie III
Langages et outils
États d’une connexion
Une fois la connexion établie, il est nécessaire de définir des états qui permettront l’encapsulation d’instructions SQL dans du code Java
...
On peut affecter à un état une ou plusieurs instruction SQL
...
Figure 8-4 Connexion et états
Données (INT VARCHAR
...
Ces états sont construits par la méthode
createStatement appliquée à la connexion
...
Ces états sont construits par la
méthode prepareStatement appliquée à la connexion
...
Ces états sont construits par la méthode prepareCall appliquée à la connexion
...
Méthodes génériques pour les paramètres
Une fois qu’un état est créé, il est possible de lui passer des paramètres par des méthodes génériques (étudiées plus en détail par la suite) :
q
setxxx où XXX désigne le type de la variable (exemple : setString ou setInt) du
sens Java vers MySQL (setter methods)
...
Il s’agit ici
q
d’extraire des données de la base dans des variables hôtes Java via un curseur Java (getter
methods) ;
updatexxx (exemple : updateString ou upadateInt) du sens Java vers MySQL
...
Ces méthodes sont disponibles seulement depuis la version 2 de JDBC (SDK 1
...
États simples (interface
Statement)
Nous décrivons ici l’utilisation d’un état simple (interface Statement)
...
Le tableau suivant décrit les principales
méthodes de l’interface Statement
...
int executeUpdate(String)
Exécute une instruction SQL et retourne le nombre de lignes
traitées (INSERT, UPDATE ou DELETE) ou 0 pour les instructions ne renvoyant aucun résultat (LDD)
...
Connection getConnection()
Retourne l’objet de la connexion
...
int getUpdateCount()
Nombre de lignes traitées par l’instruction SQL (-1 si c’est une
requête ou si l’instruction n’affecte aucune ligne)
...
Le code suivant (Etats
...
Nous supposons qu’un pilote JDBC est chargé et que la
connexion cx a été créée
...
© Éditions Eyrolles
297
Partie III
Langages et outils
Tableau 8-7 États simples
Web
Code Java
Commentaires
Statement etatSimple = cx
...
execute ("CREATE TABLE IF NOT EXISTS
Compagnie(comp VARCHAR(4), nomComp VARCHAR(30),
CONSTRAINT pk_Compagnie PRIMARY KEY(comp))");
int j = etatSimple
...
executeUpdate ("INSERT INTO
Compagnie VALUES ('AF','Air France')");
etatSimple
...
execute ("INSERT INTO Avion VALUES
('F-FGFB','A320',148,'AF')");
etatSimple
...
Ordre LDD
...
Ordre LMD, k contient 1
(une ligne est concernée)
...
Pas plus de 10 lignes
retournées par les prochaines extractions
...
executeQuery ("SELECT * FROM Avion"); Java
...
execute("DELETE FROM Avion");
Ordre LMD, l contient 2
int l = etatSimple
...
Méthodes à utiliser
Le tableau suivant indique la méthode préférentielle à utiliser sur l’état courant (objet Statement) en fonction de l’instruction SQL à émettre :
Tableau 8-8 Méthodes Java pour les ordres SQL
Instruction SQL
Méthode
Type de retour
CREATE ALTER DROP
executeUpdate
int
INSERT UPDATE DELETE
executeUpdate
int
SELECT
executeQuery
ResultSet
Correspondances de types
Les échanges de données entre variables Java et colonnes des tables Oracle impliquent de
prévoir des conversions de types
...
lang
...
Les types numériques trouvent aussi une
correspondance dans les types numériques Java (attention toutefois aux arrondis, dépassement
de capacité ou perte de précision)
...
lang
...
io
...
io
...
sql
...
sql
...
lang
...
lang
...
lang
...
lang
...
lang
...
math
...
lang
...
sql
...
sql
...
lang
...
lang
...
lang
...
INT et INTEGER[(n)] [UNSIGNED]
java
...
Integer (si UNSIGNED
java
...
Long)
...
lang
...
lang
...
BIGINT[(n)] [UNSIGNED]
java
...
Long, (si UNSIGNED
java
...
BigInteger)
...
) et SET(
...
lang
...
lang
...
DECIMAL[(n[,p])]
java
...
BigDecimal
DATE
java
...
Date
YEAR[(2|4)]
java
...
Date (date initialisée au 1er Janvier 0h)
TIME
java
...
Time
DATETIME, TIMESTAMP[(n)]
© Éditions Eyrolles
java
...
Boolean si la configuration
tinyInt1isBit est mise à true (par défaut) et la taille
de la variable = 1 (java
...
Integer sinon)
...
sql
...
Pour ce
faire, utiliser la méthode Class getClass() appliqué à l’objet résultant de l’extraction de la
colonne, dans le ResultSet, par getObject("col")
...
Le code suivant (CorresTypes
...
Tableau 8-11 Déduction du type Java à utiliser
Web
Code Java
Commentaires
ResultSet curseurJava = etatSimple
...
next ())
{ Object obj = curseurJava
...
out
...
getObject("cap"));
Class clJava = obj
...
out
...
getName());}
Extraction dans un curseur de la
capacité du premier avion
...
Extraction de l’objet Java équivalent
...
La trace de ce programme est la suivante :
Valeur : 148
Classe Java equivalente : java
...
Integer
Manipulations avec la base
Détaillons à présent les différents scénarios que l’on peut rencontrer lors d’une manipulation
de la base de données par un programme Java
...
Les autres cas (relatifs aux contraintes référentielles et aux
problèmes de syntaxe) seront étudiés dans la section Traitement des exceptions
...
j = etat
...
executeUpdate("DELETE FROM Avion");
Fait la suppression, affecte à j le nombre
d’enregistrements supprimés et passe en
séquence
...
executeUpdate("DELETE FROM Avion");
Aucune action sur la base et passe en
séquence
...
executeUpdate("DELETE FROM Avion");
Aucune action sur la base, affecte à j la
valeur 0 et passe en séquence
...
executeUpdate("INSERT INTO Compagnie
VALUES ('TAF','Toulouse Air Free')");
Fait l’insertion et passe en séquence
...
executeUpdate("INSERT INTO Compa- Fait l’insertion, affecte à j le nombre 1 et
gnie VALUES ('TAF','Toulouse Air Free')");
passe en séquence
...
executeUpdate("UPDATE Compagnie SET
nomComp = 'Air France Compagny' WHERE comp =
'AF'");
Fait la modification et passe en
séquence
...
int j= etat
...
2");
Fait la (les) modification(s), affecte à j le
nombre d’enregistrements modifiés et
passe en séquence (0 si aucun enregistrement n’est modifié)
...
Le résultat d’une requête est placé dans un objet de l’interface ResultSet qui s’apparente à
un curseur Java
...
Les méthodes relatives aux curseurs navigables seront étudiées par la suite
...
Initialement (après création et chargement du curseur),
on est positionné avant la première ligne
...
© Éditions Eyrolles
301
Partie III
Langages et outils
Tableau 8-16 Méthodes principales de l’interface ResulSet
Méthode
Description
boolean next()
Charge l’enregistrement suivant en retournant true, renvoie
false lorsqu’il n’y a plus d’enregistrement suivant
...
getxxx(int)
Récupère, au niveau de l’enregistrement, la valeur de la
colonne numérotée de type xxx
...
, pour récupérer la valeur de la première colonne
...
Exemple : updateInt(1,i),
updateString(1,nom), etc
...
Object getObject(String)
Retourne la valeur de la colonne désignée par le paramètre
dans une variable Java de type adéquat
...
Curseurs statiques
Le code suivant (SELECTstatique
...
Notez l’utilisation des différentes méthodes
get pour récupérer des valeurs issues de colonnes
...
createStatement();
ResultSet curseurJava =
etatSimple
...
next())
{System
...
print("Immat : "+ curseurJava
...
out
...
getInt(2));
moyenneCapacité += curseurJava
...
out
...
close();
} catch(SQLException ex) { … }
302
Commentaires
Création de l’état
...
Parcours du curseur
...
Fermeture du curseur
...
© Éditions Eyrolles
chapitre n° 8
Utilisation avec Java
Curseurs navigables
Un curseur ResultSet déclaré sans option n’est ni navigable ni modifiable
...
Il est possible de rendre un curseur
navigable en permettant de le parcourir en avant ou en arrière, et en autorisant l’accès direct à
un enregistrement d’une manière absolue (en partant du début ou de la fin du curseur) ou relative (en partant de la position courante du curseur)
...
Dès l’instant où on déclare un curseur navigable, il faut aussi statuer sur le fait qu’il soit modifiable ou pas (section suivante)
...
TYPE_FORWARD_ONLY
Le parcours du curseur s’opère invariablement du début
à la fin (non navigable)
...
TYPE_SCROLL_INSENSITIVE Le curseur est navigable mais pas sensible aux modifications
...
TYPE_SCROLL_SENSITIVE
Le curseur est navigable et sensible aux modifications
...
Lorsqu’il est déclaré insensible, les modifications de la table ne sont pas renvoyées dans le curseur
...
Les deux premières sont aussi des méthodes de l’interface Statement qui affectent et précisent le sens de parcours pour tous les curseurs de l’état donné
...
FETCH_FORWARD (1000),
ResultSet
...
FETCH_UNKNOWN (1002)
...
boolean isBeforeFirst()
Indique si le curseur est positionné avant le premier enregistrement (false si aucun enregistrement n’existe)
...
boolean isFirst()
Indique si le curseur est positionné sur le premier enregistrement
(false si aucun enregistrement n’existe)
...
boolean isAfterLast()
Indique si le curseur est positionné après le dernier enregistrement (false si aucun enregistrement n’existe)
...
boolean first()
Positionne le curseur sur le premier enregistrement (false si
aucun enregistrement n’existe)
...
boolean last()
Positionne le curseur sur le dernier enregistrement (false si
aucun enregistrement n’existe)
...
boolean relative(int)
Positionne le curseur sur le n-ième enregistrement en partant de
la position courante (en avant si n est positif, ou en arrière si n est
négatif, false si aucun enregistrement n’existe à cet indice)
...
FETCH_
FORWARD est interprétée)
...
Ainsi, pour parcourir un curseur à l’envers, il faudra soit utiliser des indices négatifs (dans les
méthodes absolute et relative), soit employer la méthode previous en partant de la
fin du curseur (afterLast)
...
java) présente une utilisation du curseur navigable
curseurNaviJava
...
Tableau 8-20 Parcours d’un curseur navigable
Code Java
Web
Commentaires
try {…
Statement etatSimple =createStatement
Création de
(ResultSet
...
CONCUR_READ_ONLY); l’état
...
executeQuery("SELECT
chargement du
immat,typeAvion,cap FROM Avion");
curseur
...
isBeforeFirst() )
Test renvoyant
System
...
println("Curseur positionné au début");
true
...
isFirst() )
Test renvoyant
System
...
println("Curseur positionné sur le 1er déjà");
false
...
next() )
Parcours du
{if ( curseurNaviJava
...
out
...
isLast() )
mier et dernier
System
...
println("Dernier avion : ");
enregistreSystem
...
print("Immat: "+curseurNaviJava
...
System
...
println(" type : "+curseurNaviJava
...
isAfterLast() )System
...
println("Curseur Test renvoyant
positionné après la fin");
true
...
previous() )
Affiche l’avantif ( curseurNaviJava
...
out
...
curseurNaviJava
...
first() )
Affiche le pre{System
...
println("First avion : "+
mier enregistrecurseurNaviJava
...
if ( curseurNaviJava
...
out
...
getString(1));}
ment
...
close();
Ferme le curseur
...
Créez des curseurs non navigables quand vous voulez rapatrier de très gros volumes de données (taille du cache limitative côté client)
...
Les prochaines versions de MySQL et Connector/J devraient
prendre en charge une gestion côté serveur des curseurs navigables
...
Notez que absolute(1) équivaut à first(), de même absolute(-1) équivaut à last()
...
D’autre part, l’utilisation de relative(0) n’a aucun effet
...
java) présente les méthodes qui permettent d’accéder
directement à des enregistrements de ce curseur :
Tableau 8-21 Positionnements dans un curseur navigable
Web
306
Code Java
try {…
Statement etatSimple =createStatement
(ResultSet
...
CONCUR_READ_ONLY);
ResultSet curseurPosJava =
etatSimple
...
absolute(1);
if ( curseurPosJava
...
out
...
getString(1));
else
System
...
println("Pas de 3ème avion!");
if ( curseurPosJava
...
out
...
getString(1));
else
System
...
println("Pas retour -2 possible !");
Commentaires
Création de l’état avec curseurs insensibles et non modifiables
...
Curseur sur le premier avion
...
Retour au premier avion
...
absolute(-2)
System
...
println("absolute(-2) : "+
curseurPosJava
...
out
...
afterLast();
while( curseurPosJava
...
close();
} catch(SQLException ex) { … }
Accès à l’avant-dernier enregistrement
...
Fermeture du curseur
...
Pour définir un curseur navigable :
• Une requête ne doit pas contenir de jointure
...
* FROM table a… » à la place de « SELECT * FROM table…»
...
Les valeurs permises du deuxième paramètre (modifCurseur) de la méthode createStatement, définie à la section précédente,
sont présentées dans le tableau suivant :
Tableau 8-22 Constantes de modification d’un curseur
Constante
Explication
ResultSet
...
ResultSet
...
Le caractère modifiable d’un curseur est indépendant de sa navigabilité
...
Pour spécifier un curseur de nature CONCUR_UPDATABLE :
• Une requête ne doit pas contenir de jointure ni de regroupement, elle doit seulement extraire
des colonnes (les fonctions monolignes et multilignes sont interdites)
...
* FROM table a… » à la place de « SELECT * FROM table… » ;
© Éditions Eyrolles
307
Partie III
Langages et outils
Il est aussi possible de définir un curseur par une requête de type SELECT… FOR UPDATE
...
TYPE_FORWARD_ONLY…)
...
CONCUR_READ_ONLY ou
ResultSet
...
int getType()
Renvoie le caractère navigable d’un curseur donné
...
void deleteRow()
Supprime l’enregistrement courant
...
void cancelRowUpdates()
Annule les modifications faites sur l’enregistrement courant
...
void insertRow()
Insère dans la table l’enregistrement courant
...
Les opérations de modification et d’insertion (UPDATE et INSERT) à travers un curseur se réalisent
en deux temps : mise à jour du curseur puis propagation à la table de la base de données
...
La suppression d’enregistrements (DELETE) à travers un curseur s’opère en une seule instruction qui n’est pas forcément validée par la suite : il faudra programmer explicitement le commit
ou laisser le paramètre d’autocommit à true (par défaut)
...
java) supprime le troisième enregistrement du curseur et
répercute la mise à jour au niveau de la table Avion du schéma connecté
...
createStatement(ResultSet
...
CONCUR_UPDATABLE );
désactivation de la valicx
...
ResultSet curseurModifJava = etatSimple
...
("SELECT immat,typeAvion,cap FROM Avion");
if ( curseurModifJava
...
deleteRow();
sième avion, supprescx
...
System
...
println("Pas de 3ème avion!");
curseurModifJava
...
} catch(SQLException ex) { … }
Gestion des erreurs
...
java) supprime le même enregistrement en supposant
son indice a priori inconnu
...
Notez l’utilisation de la méthode equals pour comparer deux chaînes de caractères :
Tableau 8-25 Suppression d’un enregistrement
Web
Code Java
try {…
Statement etatSimple =
cx
...
TYPE_FORWARD_ONLY,
ResultSet
...
setAutoCommit(false);
ResultSet curseurModifJava = etatSimple
...
next())
{if (curseurModifJava
...
equals(p_immat))
{ curseurModifJava
...
close();
} catch(SQLException ex) { … }
© Éditions Eyrolles
Commentaires
Création de l’état et
désactivation de la validation automatique
...
Accès à l’enregistrement
et suppression
...
Gestion des erreurs
...
Les méthodes updatexxx ont chacune deux signatures
...
java) change, au niveau de la table Avion, deux colonnes
du deuxième enregistrement du curseur
...
Tableau 8-26 Modifications d’un enregistrement
Web
Code Java
Commentaires
try {…
Statement etatSimple =
cx
...
TYPE_SCROLL_SENSITIVE,
Création de l’état et
ResultSet
...
setAutoCommit(false);
dation automatique
...
executeQuery
Création du curseur
...
absolute(2))
Accès à l’enregistrement
...
updateString(2,"A380");
Première étape
...
updateInt(3,350);
curseurModifJava
...
commit(); }
else
System
...
println("Pas de 2ème avion!");
curseurModifJava
...
Validation
...
Gestion des erreurs
...
L’éventuel retour à l’enregistrement courant se programme à l’aide de
la méthode moveToCurrentRow
...
java) insère un nouvel enregistrement au niveau de la
table Avion
...
Tableau 8-27 Insertion d’un enregistrement
Code Java
Web
Commentaires
try {…
Statement etatSimple =
cx
...
TYPE_SCROLL_SENSITIVE,
Création de l’état et
ResultSet
...
setAutoCommit(false);
dation automatique
...
executeQuery
Création du curseur
...
curseurModifJava
...
updateString(1,"F-LUTE");
curseurModifJava
...
updateInt(3,4);
curseurModifJava
...
commit();
curseurModifJava
...
Troisième étape
...
Fermeture du curseur
...
Gestion des séquences
Avant la version 3
...
Avec des anciens
pilotes JDBC pour MySQL, il était possible d’utiliser une méthode spécifique de l’interface
Statement, ou d’exécuter une requête du type SELECT LAST_INSERT_ID() après avoir
inséré un enregistrement
...
À présent, JDBC 3
...
Dans tous les cas, il n’est pas nécessaire d’insérer réellement un nouvel enregistrement (annulation possible par rollback)
...
Cette action est irréversible dans
le sens où la séquence sera incrémentée qu’on valide ou non l’ajout de l’enregistrement
...
java) insère un nouvel enregistrement dans la table Affreter (décrite au chapitre 2, section Séquences) et récupère la valeur courante de la séquence à
l’aide de la méthode getGeneratedKeys()
...
createStatement
(java
...
ResultSet
...
sql
...
CONCUR_UPDATABLE);
cx
...
Insertion avec l’option de
etat
...
Affreter
(comp,immat,dateAff,nbPax)VALUES('AF','A1',NOW(),100)", récupération de clé générée
...
RETURN_GENERATED_KEYS);
ResultSet curseur = etat
...
next())
System
...
println("Valeur de la sequence "+
curseur
...
out
...
rollback();
curseur
...
close(); cx
...
Invalidation de l’ajout
...
Gestion des erreurs
...
java) insère un nouvel enregistrement dans la table Affreter par un curseur modifiable, et récupère la valeur courante de la séquence à l’aide de la
méthode getInt() appliquée à la colonne AUTO_INCREMENT
...
createStatement
(java
...
ResultSet
...
sql
...
CONCUR_UPDATABLE);
cx
...
© Éditions Eyrolles
chapitre n° 8
Utilisation avec Java
Tableau 8-29 Récupération d’une séquence à l’aide d’un curseur modifiable (suite)
Code Java
Commentaires
ResultSet curseur = etat
...
Affreter" );
curseur
...
curseur
...
last();
Extraction de la séquence
...
out
...
getInt(1));
cx
...
close(); etat
...
close();
Invalidation de l’ajout
...
} catch(SQLException ex) { … }
Gestion des erreurs
...
Cette interface est intéressante pour
programmer dynamiquement des requêtes ou d’autres instructions SQL
...
Une fois un curseur ResultSet programmé, il suffit de lui appliquer la méthode getMetaData() pour disposer d’un objet ResultSetMetaData
...
String getColumnName(int)
Retourne le nom de la colonne d’un indice donné du curseur
...
sql
...
String getColumnTypeName(int) Retourne le nom du type SQL de la colonne d’un indice donné
du curseur
...
int getScale(int)
Nombre de décimales de la colonne désignée
...
String getTableName(int)
© Éditions Eyrolles
Indique si la colonne d’un indice donné du curseur peut être
nulle (constantes retournées :
ResultSetMetaData
...
columnNullable ou
ResultSetMetaData
...
Nom de la table de la colonne
...
Ainsi, la méthode getSchemaName() n’est pas encore reconnue
...
java) utilise des méthodes de l’interface ResultSetMetaData sur la base de la requête extrayant trois colonnes dans la table Avion :
Tableau 8-31 Extraction de méta-informations au niveau d’un curseur
Web
Code Java
Commentaires
try { …
ResultSet curseurJava=etatSimple
...
getMetaData();
int nbCol = rsmd
...
getColumnName(2);
String type2emeCol = rsmd
...
getColumnType(2);
if (rsmd
...
columnNoNulls)
…
int p1 = rsmd
...
getScale(3);
curseurJava
...
Création d’un objet
ResultSetMetaData
...
nom2emeCol contient typeAvion
...
codeType2emeCol contient 12
(code pour VARCHAR)
...
Taille de la colonne cap (renvoie 6
pour un SMALLINT)
...
Fermeture du curseur
...
Interface DatabaseMetaData
L’interface DatabaseMetaData est utile pour connaître des aspects plus généraux de la
base de données cible (version, éditeur, prise en charge des transactions…) ou des informations sur la structure de la base (structures des tables et vues, prérogatives
...
Le tableau
suivant en présente quelques-unes
...
Tableau 8-32 Méthodes principales de l’interface ResultSetMetaData
Méthode
Description
ResultSet getColumns(String,
String, String, String)
Description de toutes les colonnes d’une table d’un
schéma donné
...
String getDatabaseProductVersion() Numéro de la version de la base utilisée
...
String getUserName()
Nom de l’utilisateur connecté (schéma courant)
...
boolean supportsTransactions()
Renvoie true si la base reconnaît les transactions
...
java) emploie ces méthodes pour extraire des informations à
propos de la base cible et des objets (tables, vues, séquences…) du schéma courant
...
getMetaData();
Commentaires
Création d’un objet
DatabaseMetaData
...
getTables("",
infoBase
...
out
...
getUserName());
while (toutesLesTables
...
out
...
getString(3));
System
...
println(" Type : "+
toutesLesTables
...
out
...
getDatabaseProductName ());
System
...
println("Version base : "+
infoBase
...
supportsTransactions ())
System
...
println("Supporte les Transactions");
toutesLesTables
...
Parcours du curseur en affichant quelques caractéristiques
...
Affichage de la version de la
base
...
Fermeture du curseur
...
La trace de ce programme est la suivante (dans notre jeu d’exemples) :
Objets du schema soutou@localhost
Nom de l'objet: Avion Type : TABLE
Nom de l'objet: Compagnie Type : TABLE
Nom base : MySQL
Version base : 5
...
15-nt
Supporte les SelectForUpdate
Supporte les Transactions
© Éditions Eyrolles
315
Partie III
Langages et outils
Instructions paramétrées (PreparedStatement)
L’interface PreparedStatement hérite de l’interface Statement, et la spécialise en
permettant de paramétrer des objets (états préparés) représentant des instructions SQL
précompilées
...
La chaîne de caractères contient l’ordre SQL dont les paramètres, s’il en possède, doivent être indiqués par le symbole « ? »
...
Le tableau suivant décrit les principales méthodes de
l’interface preparedStatement :
Tableau 8-34 Méthodes de l’interface PreparedStatement
Méthode
Description
ResultSet executeQuery()
Exécute la requête et retourne un curseur ni navigable, ni
modifiable par défaut
...
boolean execute()
Exécute une instruction SQL et renvoie true, si c’est une instruction SELECT, false sinon
...
sql
...
void close()
Ferme l’état
...
On suppose la connexion cx créée :
Extraction de données (executeQuery)
Le code suivant (PrepareSELECT
...
PreparedStatement étatPréparé =
cx
...
executeQuery(); Création du curseur résultant de
la compilation de l’état
...
next())
Parcours du curseur
...
close();
Fermeture du curseur
...
étatPréparé
...
Mises à jour (executeUpdate)
Le code suivant (PrepareINSERT
...
prepareStatement(ordreSQL);
étatPréparé
...
setString(2, "A319");
étatPréparé
...
setString(4, "AF");
System
...
println( étatPréparé
...
");
étatPréparé
...
Passage des paramètres
...
Fermeture de l’état
...
Instruction LDD (execute)
Le code suivant (PrepareDELETE
...
setAutoCommit(false);
String ordreSQL =
"DELETE FROM Avion WHERE immat = ?";
PreparedStatement étatPréparé =
cx
...
setString(1, "F-NEW ");
if (! étatPréparé
...
out
...
commit(); }
étatPréparé
...
Passage du paramètre
...
Fermeture de l’état
...
Il n’est pas possible de paramétrer des instructions SQL du LDD (CREATE, ALTER…)
...
Cette chaîne sera ensuite l’unique
paramètre de la méthode prepareStatement
...
L’interface CallableStatement spécialise l’interface PreparedStatement
...
Les paramètres de sortie (définis
OUT au niveau du sous-programme) sont extraits à l’aide des méthodes getxxx
...
Chaque paramètre est indiqué par un symbole « ? » :
Tableau 8-38 Paramètre de prepareCall
Type du sous-programme
Fonction
{? = call nomFonction( [?, ?,
...
] ) }
© Éditions Eyrolles
chapitre n° 8
Utilisation avec Java
Une fois l’état créé, il faut répertorier le type des paramètres de sortie (méthode registerOutParameter), passer les valeurs des paramètres d’entrée, appeler le sous-programme et
analyser les résultats
...
int executeUpdate()
Idem PreparedStatement
...
void registerOutParameter(int,
int)
Transfère un paramètre de sortie à un indice donné d’un
type Java (classification java
...
Types)
...
Cette méthode doit être seulement invoquée
après une méthode de type getxxx
...
java) décrit l’appel de la procédure
leNomCompagnieEst (ayant deux paramètres)
...
CREATE PROCEDURE bdsoutou
...
© Éditions Eyrolles
319
Partie III
Langages et outils
Tableau 8-40 Appel d’une procédure (paramètre en entrée et sortie)
Web
Code Java
String ordreSQL =
"{call bdsoutou
...
prepareCall(ordreSQL);
étatAppelable
...
sql
...
VARCHAR);
étatAppelable
...
execute();
System
...
print("Compagnie de F-GLFS : "+
étatAppelable
...
close();
} catch(SQLException ex) { … }
Commentaires
Création d’un état appelable
...
Passage du paramètre d’entrée
...
Extraction du résultat
...
Gestion des erreurs
...
* TO 'soutou'@'localhost' et GRANT SELECT ON mysql
...
Si
vous ne le faites pas, JDBC vous rappellera clairement à l’ordre
...
Nous avons déjà décrit, à la section Interface Connection, les méthodes qui
permettent à un programme Java de coder des transactions (setAutoCommit, commit et
rollback)
...
Lorsque ce mode est
désactivé, il faut gérer manuellement les transactions avec commit ou rollback
...
• Chaque instruction du LDD (CREATE, ALTER, DROP) valide implicitement la transaction
...
0 de JDBC (JDK 1
...
Les interfaces Connection et Savepoint rendent
possible cette programmation
...
Savepoint setSavepoint(String)
Positionne un point de validation nommé et retourne un
objet Savepoint
...
void rollback(Savepoint)
Invalide la transaction à partir du point de validation
...
Le
tableau suivant présente les deux seules méthodes de l’interface Savepoint :
Tableau 8-42 Méthodes de l’interface Savepoint
Méthode
Description
int getSavepointId()
Retourne l’identifiant du point de validation de l’objet Savepoint
...
Le code suivant (TransactionJDBC
...
Dans notre exemple, nous validons seulement la
première partie (seul l’avion 'F-NEW2' sera inséré dans la table)
...
© Éditions Eyrolles
321
Partie III
Langages et outils
Tableau 8-43 Points de validation
Web
Code Java
Commentaires
try { …
cx
...
String ordreSQL =
"INSERT INTO Avion VALUES (?, ?, ?, ?)";
PreparedStatement étatPréparé =
cx
...
setSavepoint("P1");
Création d’un état appelable
...
étatPréparé
...
if (! étatPréparé
...
out
...
setSavepoint("P2");
étatPréparé
...
execute() )
System
...
println("F-NEW3 inséré");
cx
...
commit();
cx
...
Passage de paramètres et deuxième
insertion
...
Validation de la première partie
...
Gestion des erreurs
...
Le bloc d’exceptions permet de programmer des
traitements en fonction des codes d’erreur renvoyés par la base Oracle
...
Afin de gérer les erreurs renvoyées par le SGBD, JDBC propose la classe SQLException
qui hérite de la classe Exception
...
String getSQLState()
Code erreur SQL Standard (XOPEN ou SQL99)
...
SQLException getNextException() Chaînage à l’exception suivante (si une erreur renvoie plusieurs messages)
...
java) illustre une manière d’afficher explicitement toutes
les erreurs sans effectuer d’autres instructions :
Tableau 8-45 Affichage des erreurs
Code Java
Web
import java
...
*;
public class Exceptions1
{ public static void main
(String args []) throws SQLException, Exception
{try
{Class
...
mysql
...
Driver")
...
out
...
toString()); }
try
{ Connection cx =
DriverManager
...
Commentaires
Classe principale
...
Connexion
...
close(); }
Gestion des erreurs
...
err
...
err
...
getSQLState());
System
...
println("Message : "+
ex
...
err
...
getErrorCode());
ex = ex
...
On peut appeler des méthodes de la classe principale ou coder directement dans
le bloc des exceptions
...
java) insère un enregistrement dans la table Avion en gérant
un certain nombre d’exceptions possibles
...
Si l’avion à insérer n’est pas rattaché à une
compagnie existante (contrainte référentielle), exception 1452-Cannot add or update a
child row: a foreign key constraint fails)
...
© Éditions Eyrolles
323
Partie III
Langages et outils
Tableau 8-46 Traitement des exceptions
Web
324
Code Java
try
{Connection cx =
DriverManager
...
Avion VALUES
('F-NOUV','A310', 5600, 'AF')";
PreparedStatement étatPréparé =
cx
...
out
...
executeUpdate() +
" avion insere en base
...
close(); }
catch(SQLException ex){
if ( ex
...
out
...
getErrorCode() == 1044 )
System
...
println("Nom de base inconnu!");
else if ( ex
...
out
...
getErrorCode() == 1146 )
System
...
println("Nom de table inconnue!");
else if (( ex
...
getErrorCode() == 0 ))
System
...
println("Valeur trop longue ou
valeur trop importante!");
else if ( ex
...
out
...
err
...
err
...
getSQLState());
System
...
println("Message : "+ ex
...
err
...
getErrorCode());
ex = ex
...
Non unique
...
Mauvais nombre de colonnes
...
Mauvais type de colonnes
...
Gestion des autres
erreurs
...
8
...
•
main qui se connecte à la base, appelle la méthode getSalles et affiche les résultats (exemple
donné ci-dessous) :
nSalle nomSalle
nbPoste indIP
-----------------------------------------s01
Salle 1
3
130
...
80
s02
Salle 2
2
130
...
80
…
Ajoutez une nouvelle salle dans la table Salle dans l’interface de commande, et lancez à nouveau le
programme pour vérifier
...
2
Curseur modifiable
Écrivez la méthode void deleteSalle(int) qui supprime de la table Salle l’enregistrement de
rang passé en paramètre
...
Appelez dans le main cette méthode pour supprimer l’enregistrement de la table Salle que vous
avez ajouté en test, dans l’exercice précédent
...
© Éditions Eyrolles
325
Partie III
Langages et outils
8
...
CREATE PROCEDURE supprimeSalle(IN ns VARCHAR(7),OUT res TINYINT)
BEGIN
DECLARE ligne VARCHAR(20);
DECLARE EXIT HANDLER FOR NOT FOUND
SET res := -1;
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET res := -2;
SELECT nomSalle INTO ligne FROM Salle WHERE nSalle = ns;
DELETE FROM Salle WHERE nsalle = ns;
SET res := 0;
COMMIT ;
END;
La procédure retourne en second paramètre :
•
0 si la suppression s’est déroulée correctement ;
•
-1 si le code de la salle est inconnu ;
•
-2 si la suppression est impossible (contraintes référentielles)
...
Essayer les différents cas d’erreurs en appelant cette méthode d’abord avec un numéro de
salle référencé par un poste de travail, et ensuite avec un numéro de salle inexistant
...
326
© Éditions Eyrolles
Chapitre 9
Utilisation avec PHP
Ce chapitre détaille les moyens de faire interagir un programme PHP 5 avec une base MySQL
...
La première convient à des
bases MySQL de version antérieure à 4
...
Nous détaillerons donc l’extension mysqli qui
correspond toutefois à des bases plus anciennes (jusqu’à la version 3
...
Pour plus de détails
consultez une documentation en ligne mise à jour (http://www
...
net/docs/php/annotee/ref
...
php)
...
Nous avons opté pour faire interagir un programme PHP 5
avec une base MySQL 5 sous Apache 1
...
Je décris ici une procédure minimale sans plus
d’explication
...
Logiciels
Récupérez et installez Apache (www
...
org)
...
exe s’il n’est pas automatiquement lancé après l’installation
...
Installez PHP (http://www
...
net/downloads
...
Fichiers de configuration
Dans le fichier httpd
...
conf dans mon cas), modifiez ou ajoutez les lignes suivantes (le « # » désigne
un commentaire) :
# modif pour MySQL et PHP ici 9999 par exemple
Port 9999
…
© Éditions Eyrolles
327
Partie III
Langages et outils
#Ajout pour PHP
LoadModule php5_module "c:/php/php5apache
...
c
SEtEnv PHPRC C:/php
AddType application/x-httpd-php
...
html index
...
ini (se trouvant dans C:\WINDOWS dans mon cas), ajoutez les lignes
suivantes (le « ; » désigne un commentaire) :
; Paths and Directories ;
extension_dir = "C:\PHP\ext"
; Dynamic Extensions ;
extension=php_mysqli
...
dll qui se situe dans le répertoire de PHP (C:\PHP dans mon
cas), dans le répertoire de Windows (C:\WINDOWS dans mon cas)
...
php) et disposez-le dans le répertoire contenant les
sources PHP (D:/dev/PHP-MySQL dans mon cas)
...
3 PHP5
Test de la configuration Apache 1
...
Soutou
phpinfo();
?>