Chapitre 3 LES OBJETS MySQL - Free
15.5.1 Exemples d'opérations de l'AR. 15.6 TP modèle relationnel PARISCOPE.
15.6.1 Enoncé. 15.6.2 Corrigé. 15.7 TP algèbre relationnelle PARISCOPE.
part of the document
MYSQL 5 - SQL
Sommaire
TOC \o "1-9" \t "Titre 9;9;Titre 8;8;Titre 7;7;Titre 6;6;Titre 5;5;Titre 4;4;Titre 3;3;Titre 2;2;Titre 1;1" \h HYPERLINK \l "_Toc258332274" Chapitre 1 INTRODUCTION PAGEREF _Toc258332274 \h 7
HYPERLINK \l "_Toc258332275" 1.1 Bases utilisées PAGEREF _Toc258332275 \h 7
HYPERLINK \l "_Toc258332276" 1.2 Définition d'un SGBDR PAGEREF _Toc258332276 \h 7
HYPERLINK \l "_Toc258332277" Chapitre 2 INSTALLATION et CONFIGURATION PAGEREF _Toc258332277 \h 8
HYPERLINK \l "_Toc258332278" 2.1 Fichiers à télécharger PAGEREF _Toc258332278 \h 8
HYPERLINK \l "_Toc258332279" 2.1.1 WAMP5 PAGEREF _Toc258332279 \h 8
HYPERLINK \l "_Toc258332280" 2.1.2 EasyPHP PAGEREF _Toc258332280 \h 9
HYPERLINK \l "_Toc258332281" 2.1.3 Xampp PAGEREF _Toc258332281 \h 9
HYPERLINK \l "_Toc258332282" 2.1.4 Autres PAGEREF _Toc258332282 \h 9
HYPERLINK \l "_Toc258332283" 2.1.5 MySQL PAGEREF _Toc258332283 \h 10
HYPERLINK \l "_Toc258332284" 2.2 Installations PAGEREF _Toc258332284 \h 11
HYPERLINK \l "_Toc258332285" 2.2.1 Installation du SGBDR PAGEREF _Toc258332285 \h 11
HYPERLINK \l "_Toc258332286" 2.2.2 Installation des outils PAGEREF _Toc258332286 \h 11
HYPERLINK \l "_Toc258332287" 2.2.2.1 PhpMyAdmin PAGEREF _Toc258332287 \h 11
HYPERLINK \l "_Toc258332288" 2.2.2.2 MysqlQueryBrowser de MySQL AB PAGEREF _Toc258332288 \h 11
HYPERLINK \l "_Toc258332289" 2.2.2.3 DBDesignor de FabForge.net PAGEREF _Toc258332289 \h 11
HYPERLINK \l "_Toc258332290" 2.2.2.4 MySQL Workbench de Mysql AB PAGEREF _Toc258332290 \h 11
HYPERLINK \l "_Toc258332291" 2.2.2.5 MysqlAministrator de Mysql AB PAGEREF _Toc258332291 \h 11
HYPERLINK \l "_Toc258332292" 2.3 Le MySQL Query Browser PAGEREF _Toc258332292 \h 12
HYPERLINK \l "_Toc258332293" 2.3.1 Connexion PAGEREF _Toc258332293 \h 12
HYPERLINK \l "_Toc258332294" 2.3.2 Interface PAGEREF _Toc258332294 \h 13
HYPERLINK \l "_Toc258332295" 2.3.3 Création d'une base PAGEREF _Toc258332295 \h 14
HYPERLINK \l "_Toc258332296" 2.3.4 Suppression d'une base de données. PAGEREF _Toc258332296 \h 15
HYPERLINK \l "_Toc258332297" 2.3.5 Création d'une table PAGEREF _Toc258332297 \h 16
HYPERLINK \l "_Toc258332298" 2.3.6 Création d'une clé étrangère PAGEREF _Toc258332298 \h 18
HYPERLINK \l "_Toc258332299" 2.3.7 Modification, suppression d'une table PAGEREF _Toc258332299 \h 20
HYPERLINK \l "_Toc258332300" 2.3.8 Travailler en mode ligne de commandes PAGEREF _Toc258332300 \h 21
HYPERLINK \l "_Toc258332301" 2.3.8.1 Avec MySQL Query Browser PAGEREF _Toc258332301 \h 21
HYPERLINK \l "_Toc258332302" 2.4 Travailler avec l'utilitaire mysql PAGEREF _Toc258332302 \h 22
HYPERLINK \l "_Toc258332303" 2.5 Travailler Avec PHPMyADMIN PAGEREF _Toc258332303 \h 24
HYPERLINK \l "_Toc258332304" Chapitre 3 LES OBJETS MySQL PAGEREF _Toc258332304 \h 25
HYPERLINK \l "_Toc258332305" 3.1 Le LDD PAGEREF _Toc258332305 \h 25
HYPERLINK \l "_Toc258332306" 3.2 Les bases de données PAGEREF _Toc258332306 \h 26
HYPERLINK \l "_Toc258332307" 3.2.1 Création PAGEREF _Toc258332307 \h 26
HYPERLINK \l "_Toc258332308" 3.2.2 Modification d'une base de données PAGEREF _Toc258332308 \h 27
HYPERLINK \l "_Toc258332309" 3.2.3 Supression d'une base de données PAGEREF _Toc258332309 \h 27
HYPERLINK \l "_Toc258332310" 3.3 Les tables PAGEREF _Toc258332310 \h 28
HYPERLINK \l "_Toc258332311" 3.3.1 Les types de données. PAGEREF _Toc258332311 \h 28
HYPERLINK \l "_Toc258332312" 3.3.2 Création d'une table PAGEREF _Toc258332312 \h 30
HYPERLINK \l "_Toc258332313" 3.3.3 Création d'une table à partir d'une autre table PAGEREF _Toc258332313 \h 31
HYPERLINK \l "_Toc258332314" 3.3.4 Le schéma de la base COURS PAGEREF _Toc258332314 \h 31
HYPERLINK \l "_Toc258332315" 3.3.5 Renommage d'une table PAGEREF _Toc258332315 \h 32
HYPERLINK \l "_Toc258332316" 3.3.6 Suppression d'une table PAGEREF _Toc258332316 \h 32
HYPERLINK \l "_Toc258332317" 3.3.7 Modification de la structure d'une table PAGEREF _Toc258332317 \h 33
HYPERLINK \l "_Toc258332318" 3.4 Les contraintes (Constraint) PAGEREF _Toc258332318 \h 35
HYPERLINK \l "_Toc258332319" 3.4.1 Création d'une contrainte PAGEREF _Toc258332319 \h 35
HYPERLINK \l "_Toc258332320" 3.4.2 Suppression d'une contrainte PAGEREF _Toc258332320 \h 36
HYPERLINK \l "_Toc258332321" 3.5 Les index (Index) PAGEREF _Toc258332321 \h 37
HYPERLINK \l "_Toc258332322" 3.5.1 Création d'un index PAGEREF _Toc258332322 \h 37
HYPERLINK \l "_Toc258332323" 3.5.2 Suppression d'un index PAGEREF _Toc258332323 \h 38
HYPERLINK \l "_Toc258332324" 3.5.3 Visualisation des Index PAGEREF _Toc258332324 \h 39
HYPERLINK \l "_Toc258332325" 3.5.4 Utilisation des index PAGEREF _Toc258332325 \h 41
HYPERLINK \l "_Toc258332326" 3.6 TP PARISCOPE : Création et Manipulation des objets de la base PAGEREF _Toc258332326 \h 42
HYPERLINK \l "_Toc258332327" 3.6.1 Enoncés PAGEREF _Toc258332327 \h 42
HYPERLINK \l "_Toc258332328" Chapitre 4 MISE A JOUR DES DONNEES PAGEREF _Toc258332328 \h 43
HYPERLINK \l "_Toc258332329" 4.1 Présentation PAGEREF _Toc258332329 \h 44
HYPERLINK \l "_Toc258332330" 4.2 Insertion de données (INSERT) PAGEREF _Toc258332330 \h 45
HYPERLINK \l "_Toc258332331" 4.2.1.1 Première syntaxe PAGEREF _Toc258332331 \h 45
HYPERLINK \l "_Toc258332332" 4.2.1.2 Deuxième syntaxe PAGEREF _Toc258332332 \h 46
HYPERLINK \l "_Toc258332333" 4.2.1.3 Troisième syntaxe PAGEREF _Toc258332333 \h 46
HYPERLINK \l "_Toc258332334" 4.3 Insertion de données (REPLACE) PAGEREF _Toc258332334 \h 47
HYPERLINK \l "_Toc258332335" 4.4 Suppression de données (DELETE) PAGEREF _Toc258332335 \h 48
HYPERLINK \l "_Toc258332336" 4.5 Suppression des données (TRUNCATE) PAGEREF _Toc258332336 \h 49
HYPERLINK \l "_Toc258332337" 4.6 Modification de données (UPDATE) PAGEREF _Toc258332337 \h 50
HYPERLINK \l "_Toc258332338" 4.7 TP PARISCOPE : Mise à jour des données PAGEREF _Toc258332338 \h 51
HYPERLINK \l "_Toc258332339" 4.7.1 Enoncés MAJ PARISCOPE PAGEREF _Toc258332339 \h 51
HYPERLINK \l "_Toc258332340" Chapitre 5 L'EXTRACTION DES DONNEES (L'ORDRE SELECT) PAGEREF _Toc258332340 \h 52
HYPERLINK \l "_Toc258332341" 5.1.1 SELECT mono table sans condition PAGEREF _Toc258332341 \h 52
HYPERLINK \l "_Toc258332342" 5.1.2 Extraire un certain nombre d'enregistrements (Restriction) PAGEREF _Toc258332342 \h 52
HYPERLINK \l "_Toc258332343" 5.1.3 Le tri PAGEREF _Toc258332343 \h 53
HYPERLINK \l "_Toc258332344" 5.1.4 Quelques fonctions propriétaires PAGEREF _Toc258332344 \h 54
HYPERLINK \l "_Toc258332345" 5.1.4.1 Sur les chaînes PAGEREF _Toc258332345 \h 54
HYPERLINK \l "_Toc258332346" 5.1.4.2 Sur les numériques PAGEREF _Toc258332346 \h 55
HYPERLINK \l "_Toc258332347" 5.1.4.3 Sur les dates PAGEREF _Toc258332347 \h 56
HYPERLINK \l "_Toc258332348" 5.1.5 Les opérateurs de comparaison PAGEREF _Toc258332348 \h 57
HYPERLINK \l "_Toc258332349" 5.1.6 Les opérateurs logiques PAGEREF _Toc258332349 \h 58
HYPERLINK \l "_Toc258332350" 5.1.7 Les opérateurs ensemblistes PAGEREF _Toc258332350 \h 59
HYPERLINK \l "_Toc258332351" 5.1.7.1 IN PAGEREF _Toc258332351 \h 59
HYPERLINK \l "_Toc258332352" 5.1.7.2 BETWEEN PAGEREF _Toc258332352 \h 59
HYPERLINK \l "_Toc258332353" 5.1.7.3 LIKE PAGEREF _Toc258332353 \h 60
HYPERLINK \l "_Toc258332354" 5.1.7.4 IS NULL IS NOT NULL PAGEREF _Toc258332354 \h 60
HYPERLINK \l "_Toc258332355" 5.1.8 Les requêtes calculées PAGEREF _Toc258332355 \h 61
HYPERLINK \l "_Toc258332356" 5.1.8.1 Numériques PAGEREF _Toc258332356 \h 61
HYPERLINK \l "_Toc258332357" 5.1.8.2 Chaînes PAGEREF _Toc258332357 \h 61
HYPERLINK \l "_Toc258332358" 5.1.9 TP PARISCOPE : les requêtes simples PAGEREF _Toc258332358 \h 62
HYPERLINK \l "_Toc258332359" Chapitre 6 LES JOINTURES PAGEREF _Toc258332359 \h 63
HYPERLINK \l "_Toc258332360" 6.1 Principes PAGEREF _Toc258332360 \h 63
HYPERLINK \l "_Toc258332361" 6.2 L'equi-jointure PAGEREF _Toc258332361 \h 64
HYPERLINK \l "_Toc258332362" 6.2.1 Syntaxe simplifiée PAGEREF _Toc258332362 \h 64
HYPERLINK \l "_Toc258332363" 6.2.2 Syntaxe ANSI PAGEREF _Toc258332363 \h 65
HYPERLINK \l "_Toc258332364" 6.3 Auto-jointure PAGEREF _Toc258332364 \h 66
HYPERLINK \l "_Toc258332365" 6.4 Les jointures externes PAGEREF _Toc258332365 \h 67
HYPERLINK \l "_Toc258332366" 6.5 Plus loin avec la syntaxe ANSI PAGEREF _Toc258332366 \h 68
HYPERLINK \l "_Toc258332367" 6.6 Le produit cartésien PAGEREF _Toc258332367 \h 69
HYPERLINK \l "_Toc258332368" 6.6.1 Premier exemple PAGEREF _Toc258332368 \h 69
HYPERLINK \l "_Toc258332369" 6.6.2 Deuxième exemple PAGEREF _Toc258332369 \h 70
HYPERLINK \l "_Toc258332370" 6.6.3 TP PARISCOPE sur les jointures PAGEREF _Toc258332370 \h 71
HYPERLINK \l "_Toc258332371" Chapitre 7 LES REQUETES AGREGATS PAGEREF _Toc258332371 \h 72
HYPERLINK \l "_Toc258332372" 7.1 Les fonctions agrégats PAGEREF _Toc258332372 \h 72
HYPERLINK \l "_Toc258332373" 7.2 La clause GROUP BY PAGEREF _Toc258332373 \h 74
HYPERLINK \l "_Toc258332374" 7.3 La clause HAVING PAGEREF _Toc258332374 \h 76
HYPERLINK \l "_Toc258332375" 7.3.1 TP PARISCOPE sur les Agrégats PAGEREF _Toc258332375 \h 77
HYPERLINK \l "_Toc258332376" Chapitre 8 LES REQUETES ENSEMBLISTES PAGEREF _Toc258332376 \h 78
HYPERLINK \l "_Toc258332377" 8.1 Principes PAGEREF _Toc258332377 \h 78
HYPERLINK \l "_Toc258332378" 8.2 Union PAGEREF _Toc258332378 \h 79
HYPERLINK \l "_Toc258332379" 8.3 Intersection (N'existe pas en MySQL) PAGEREF _Toc258332379 \h 80
HYPERLINK \l "_Toc258332380" 8.4 Différence (N'existe pas en MySQL) PAGEREF _Toc258332380 \h 81
HYPERLINK \l "_Toc258332381" 8.4.1 TP PARISCOPE sur les requêtes ensemblistes PAGEREF _Toc258332381 \h 82
HYPERLINK \l "_Toc258332382" Chapitre 9 LES REQUETES IMBRIQUEES PAGEREF _Toc258332382 \h 83
HYPERLINK \l "_Toc258332383" 9.1 Principes PAGEREF _Toc258332383 \h 83
HYPERLINK \l "_Toc258332384" 9.2 Format 1 : la sous-requête renvoie un seul résultat PAGEREF _Toc258332384 \h 84
HYPERLINK \l "_Toc258332385" 9.3 Format 2 : la sous-requête renvoie plusieurs résultats PAGEREF _Toc258332385 \h 86
HYPERLINK \l "_Toc258332386" 9.4 La requête renvoie vrai ou faux PAGEREF _Toc258332386 \h 87
HYPERLINK \l "_Toc258332387" 9.5 La sous requête renvoie un agrégat PAGEREF _Toc258332387 \h 89
HYPERLINK \l "_Toc258332388" 9.6 Les opérateurs ANY, ALL PAGEREF _Toc258332388 \h 90
HYPERLINK \l "_Toc258332389" 9.7 Mise à jour en fonction d'une sous-requête PAGEREF _Toc258332389 \h 95
HYPERLINK \l "_Toc258332390" 9.8 Insert contrôlé PAGEREF _Toc258332390 \h 96
HYPERLINK \l "_Toc258332391" 9.8.1 TP PARISCOPE sur les requêtes imbriquées PAGEREF _Toc258332391 \h 97
HYPERLINK \l "_Toc258332392" Chapitre 10 LES TABLEAUX CROISES DYNAMIQUES PAGEREF _Toc258332392 \h 98
HYPERLINK \l "_Toc258332393" 10.1 Sur une table PAGEREF _Toc258332393 \h 98
HYPERLINK \l "_Toc258332394" 10.2 Sur une jointure statique PAGEREF _Toc258332394 \h 100
HYPERLINK \l "_Toc258332395" 10.3 Sur une jointure dynamique PAGEREF _Toc258332395 \h 101
HYPERLINK \l "_Toc258332396" Chapitre 11 LES TRANSACTIONS PAGEREF _Toc258332396 \h 102
HYPERLINK \l "_Toc258332397" 11.1 Principes PAGEREF _Toc258332397 \h 102
HYPERLINK \l "_Toc258332398" 11.2 Validation PAGEREF _Toc258332398 \h 103
HYPERLINK \l "_Toc258332399" 11.3 Annulation PAGEREF _Toc258332399 \h 103
HYPERLINK \l "_Toc258332400" 11.4 Les savepoints PAGEREF _Toc258332400 \h 104
HYPERLINK \l "_Toc258332401" 11.5 Le verrouillage de table PAGEREF _Toc258332401 \h 105
HYPERLINK \l "_Toc258332402" 11.6 Le verrouillage de ligne PAGEREF _Toc258332402 \h 106
HYPERLINK \l "_Toc258332403" Chapitre 12 LES VUES (VIEWS) PAGEREF _Toc258332403 \h 107
HYPERLINK \l "_Toc258332404" 12.1 Création, suppression, modification PAGEREF _Toc258332404 \h 108
HYPERLINK \l "_Toc258332405" 12.1.1 Création PAGEREF _Toc258332405 \h 108
HYPERLINK \l "_Toc258332406" 12.1.2 Suppression PAGEREF _Toc258332406 \h 108
HYPERLINK \l "_Toc258332407" 12.1.3 Modification PAGEREF _Toc258332407 \h 108
HYPERLINK \l "_Toc258332408" 12.2 Les vues et les mises à jour PAGEREF _Toc258332408 \h 109
HYPERLINK \l "_Toc258332409" 12.3 TP sur les views PAGEREF _Toc258332409 \h 111
HYPERLINK \l "_Toc258332410" Chapitre 13 OPTIMISATION PAGEREF _Toc258332410 \h 112
HYPERLINK \l "_Toc258332411" 13.1 Indexation PAGEREF _Toc258332411 \h 113
HYPERLINK \l "_Toc258332412" 13.2 Explain PAGEREF _Toc258332412 \h 114
HYPERLINK \l "_Toc258332413" 13.2.1 La commande PAGEREF _Toc258332413 \h 114
HYPERLINK \l "_Toc258332414" 13.2.2 Un select PAGEREF _Toc258332414 \h 114
HYPERLINK \l "_Toc258332415" 13.2.3 Explain et les index PAGEREF _Toc258332415 \h 115
HYPERLINK \l "_Toc258332416" 13.2.4 Explain et les jointures PAGEREF _Toc258332416 \h 117
HYPERLINK \l "_Toc258332417" 13.2.5 Explain et les requêtes imbriquées PAGEREF _Toc258332417 \h 124
HYPERLINK \l "_Toc258332418" 13.3 ANALYZE TABLE PAGEREF _Toc258332418 \h 125
HYPERLINK \l "_Toc258332419" Chapitre 14 DIVERS PAGEREF _Toc258332419 \h 126
HYPERLINK \l "_Toc258332420" 14.1 Les événements (> 5.1) PAGEREF _Toc258332420 \h 126
HYPERLINK \l "_Toc258332421" 14.2 Quelques éléments meta-basiques PAGEREF _Toc258332421 \h 127
HYPERLINK \l "_Toc258332422" 14.2.1 La commande SHOW PAGEREF _Toc258332422 \h 127
HYPERLINK \l "_Toc258332423" Chapitre 15 LE MODELE RELATIONNEL DE CODD PAGEREF _Toc258332423 \h 128
HYPERLINK \l "_Toc258332424" 15.1 Les domaines, les relations et les attributs. PAGEREF _Toc258332424 \h 128
HYPERLINK \l "_Toc258332425" 15.1.1 Domaine PAGEREF _Toc258332425 \h 128
HYPERLINK \l "_Toc258332426" 15.1.2 Attribut PAGEREF _Toc258332426 \h 128
HYPERLINK \l "_Toc258332427" 15.1.3 Relation PAGEREF _Toc258332427 \h 129
HYPERLINK \l "_Toc258332428" 15.1.4 BD R PAGEREF _Toc258332428 \h 129
HYPERLINK \l "_Toc258332429" 15.2 Les dépendances fonctionnelles élémentaires, clés candidates, clé primaire. PAGEREF _Toc258332429 \h 130
HYPERLINK \l "_Toc258332430" 15.2.1 Les dépendances fonctionnelles (DF) PAGEREF _Toc258332430 \h 130
HYPERLINK \l "_Toc258332431" 15.2.2 Clés candidates PAGEREF _Toc258332431 \h 130
HYPERLINK \l "_Toc258332432" 15.2.3 Clé primaire PAGEREF _Toc258332432 \h 131
HYPERLINK \l "_Toc258332433" 15.2.4 Clé étrangère PAGEREF _Toc258332433 \h 131
HYPERLINK \l "_Toc258332434" 15.3 La valeur NULL, l'intégrité d'entité, l'intégrité référentielle. PAGEREF _Toc258332434 \h 132
HYPERLINK \l "_Toc258332435" 15.3.1 La valeur NULL PAGEREF _Toc258332435 \h 132
HYPERLINK \l "_Toc258332436" 15.3.2 L'intégrité d'entité PAGEREF _Toc258332436 \h 132
HYPERLINK \l "_Toc258332437" 15.3.3 L'intégrité référentielle PAGEREF _Toc258332437 \h 132
HYPERLINK \l "_Toc258332438" 15.4 La normalisation des données PAGEREF _Toc258332438 \h 133
HYPERLINK \l "_Toc258332439" 15.4.1 Première forme normale (1ère FN) PAGEREF _Toc258332439 \h 133
HYPERLINK \l "_Toc258332440" 15.4.2 Deuxième forme normale (2ème FN) PAGEREF _Toc258332440 \h 134
HYPERLINK \l "_Toc258332441" 15.4.3 Troisième forme normale (3ème FN) PAGEREF _Toc258332441 \h 135
HYPERLINK \l "_Toc258332442" 15.5 Les opérateurs de l'algèbre relationnelle PAGEREF _Toc258332442 \h 136
HYPERLINK \l "_Toc258332443" 15.5.1 Exemples d'opérations de l'AR PAGEREF _Toc258332443 \h 137
HYPERLINK \l "_Toc258332444" 15.6 TP modèle relationnel PARISCOPE PAGEREF _Toc258332444 \h 138
HYPERLINK \l "_Toc258332445" 15.6.1 Enoncé PAGEREF _Toc258332445 \h 138
HYPERLINK \l "_Toc258332446" 15.6.2 Corrigé PAGEREF _Toc258332446 \h 139
HYPERLINK \l "_Toc258332447" 15.7 TP algèbre relationnelle PARISCOPE PAGEREF _Toc258332447 \h 140
HYPERLINK \l "_Toc258332448" 15.7.1 Enoncés PAGEREF _Toc258332448 \h 140
HYPERLINK \l "_Toc258332449" 15.7.2 Corrigés PAGEREF _Toc258332449 \h 141
HYPERLINK \l "_Toc258332450" Chapitre 16 ANNEXES PAGEREF _Toc258332450 \h 142
HYPERLINK \l "_Toc258332451" 16.1 La BD COURS PAGEREF _Toc258332451 \h 142
HYPERLINK \l "_Toc258332452" 16.1.1 Schéma PAGEREF _Toc258332452 \h 142
HYPERLINK \l "_Toc258332453" 16.1.2 Script de création des tables PAGEREF _Toc258332453 \h 143
HYPERLINK \l "_Toc258332454" 16.1.3 Script d'insertion des données PAGEREF _Toc258332454 \h 146
HYPERLINK \l "_Toc258332455" 16.2 La BD PARISCOPE PAGEREF _Toc258332455 \h 148
HYPERLINK \l "_Toc258332456" 16.2.1 Schéma PAGEREF _Toc258332456 \h 148
HYPERLINK \l "_Toc258332457" 16.2.2 Corrigés PAGEREF _Toc258332457 \h 149
HYPERLINK \l "_Toc258332458" 16.2.2.1 TP Pariscope sur les objets tables PAGEREF _Toc258332458 \h 149
HYPERLINK \l "_Toc258332459" 16.2.2.2 TP Pariscope sur les clés étrangères PAGEREF _Toc258332459 \h 153
HYPERLINK \l "_Toc258332460" 16.2.2.3 TP Pariscope sur les index PAGEREF _Toc258332460 \h 155
HYPERLINK \l "_Toc258332461" 16.2.2.4 TP Pariscope sur les modifications de table PAGEREF _Toc258332461 \h 155
HYPERLINK \l "_Toc258332462" 16.2.3 SQL Insertion des données dans Pariscope PAGEREF _Toc258332462 \h 156
HYPERLINK \l "_Toc258332463" 16.2.4 Corrigés MAJ PARISCOPE PAGEREF _Toc258332463 \h 158
HYPERLINK \l "_Toc258332464" 16.3 TP Extraction des données PAGEREF _Toc258332464 \h 159
HYPERLINK \l "_Toc258332465" 16.3.1 Corrigés PAGEREF _Toc258332465 \h 159
HYPERLINK \l "_Toc258332466" 16.4 La BD Ingénieurs PAGEREF _Toc258332466 \h 163
HYPERLINK \l "_Toc258332467" 16.4.1 Le schéma PAGEREF _Toc258332467 \h 163
HYPERLINK \l "_Toc258332468" 16.4.2 La création du schéma et l'insertion des données PAGEREF _Toc258332468 \h 163
HYPERLINK \l "_Toc258332469" 16.5 La BD Ingénieurs Light PAGEREF _Toc258332469 \h 164
HYPERLINK \l "_Toc258332470" 16.5.1 Schéma PAGEREF _Toc258332470 \h 164
HYPERLINK \l "_Toc258332471" 16.5.2 Script de création et d'insertions dans BD_INGENIEURS_LIGHT PAGEREF _Toc258332471 \h 165
HYPERLINK \l "_Toc258332472" 16.6 Bibliographie PAGEREF _Toc258332472 \h 167
HYPERLINK \l "_Toc258332473" 16.7 Quelques corrigés PAGEREF _Toc258332473 \h 168
INTRODUCTION
Pour supprimer le service Mysql : sc delete MySQL dans une VDM DOS.
Bases utilisées
Cours : cours.
TP : pariscope, bd_light_ingenieurs, bd_ingenieurs.
Les schémas et scripts de création des bases et d'insertion des données sont en fin de support o u sous forme de fichiers externes.
Définition d'un SGBDR
Un SGBDR est un Système de Gestion de bases de Données Relationnelles.
C'est-à-dire un ensemble de logiciels capable de gérer une base de données relationnelles.
Une base de données est un ensemble de tables bien souvent reliées entre elles (il peut exister des tables paramètre qui sont complètement indépendantes) qui modélisent un domaine du SI d'une organisation.
Les tables sont composées de colonnes (les champs) et de lignes (les enregistrements).
Une table comprend une clé primaire, composée d'un ou plusieurs champs; celle-ci permet d'identifier chaque enregistrement; chaque valeur est unique. La clé primaire doit être renseignée (Elle est NOT NULL). Elle est indexée.
Une table peut comprendre zéro, une ou plusieurs clé(s) étrangère(s) qui sont des champs correspondant à une clé primaire dans une autre table. Une clé étrangère dans une table (enfant) permet de faire un lien vers une autre table (une table parent). Mais c'est aussi une contrainte, dans la mesure où les valeurs de la clé primaire de la table parent sont références pour la table enfant. On parle de contrainte d'intégrité référentielle.
Le R signifie relationnel parce que l'implémentation des SGBDR dépend du modèle relationnel de CODD qui a aussi créé une algèbre relationnelle dont est issu le langage standard d'interrogation des BDR, le SQL (Structured Query Language).
MySQL est OpenSource et Propriétaire. Il existe donc deux licences.
INSTALLATION et CONFIGURATION
Fichiers à télécharger
Il existe deux possibilités :
Soit installer un LAMP (Linux, Apache, MySQL, PHP), WAMP ou MAMP. Un LAMP install automatiquement une serveur HHTPd (Apache), module PHP, un SGBDR (MySQL) et une interface d'amininistration et de requêtage (PHPMyAdmin).
Soit installer des produits séparément (MySQL, MySQL Query Browser, MySQL Administrator).
WAMP5
HYPERLINK "http://www.wampserver.com/" http://www.wampserver.com/
EasyPHP
HYPERLINK "http://www.easyphp.org/" http://www.easyphp.org/
Xampp
HYPERLINK "http://www.apachefriends.org/fr/xampp-windows.html" http://www.apachefriends.org/fr/xampp-windows.html
Autres
LAMP sous Linux.
MAMP sous Mac.
MySQL
L'installation séparée de MySQL consiste à n'installer que le SGBDR MySQL.
Il est possible de ne travailler qu'avec l'utilitaire mysql en mode commande, mais vous pouvez dans le cadre de cette formation initiale installer MySQL Qurey Browser qui est une interface client lourd multi-plateforme.
D'autres outils existent AGL (Atelier de Génie Logiciel), Outils de migration,
, pilotes pour des connections applicatives, références hors-ligne.
La liste correspond aux versions à une certaine date. Les versions évoluent rapidement.
Sites :
HYPERLINK "http://www-fr.mysql.com/"http://www-fr.mysql.com/
HYPERLINK "http://dev.mysql.com/downloads/" http://dev.mysql.com/downloads/
Tableau des téléchargements possibles (non exhaustifs et versions non définitives).
FonctionFichierMYSQLmysql-5.1.40-win32.msiInterface d'administration (MySQL Administrator),
Interface d'interrogation (MySQL Query Browser),
Interface de migration (MySQL Migration Toolkit).mysql-gui-tools-noinstall-5.0-r15-win32.zipMySQL WorkBenchConcepteur graphique de BD.
Nécessite sous Windows le framework .NET 2.0 minimum.DBDesignerConcepteur graphique de BD (Obsolète mais intéressant dans la mesure où il possède un QBE).Connecteur ODBC 5.1mysql-connector-odbc-5.1.5-win32.msiConnecteur JDBC mysql-connector-java-5.1.7.zipConnecteur PHP php_mysqli.dll for PHP 5.2.1Connecteur .NETmysql-connector-net-5.2.5.zipLa référence en français (> 1500 pages)mysql_5_reference_fr.pdfLe fichier d'aide (format Winhelp) HYPERLINK "http://downloads.mysql.com/docs/refman-5.0-fr.chm" http://downloads.mysql.com/docs/refman-5.0-fr.chm
ou
HYPERLINK "http://www.placeoweb.com/chm/" http://www.placeoweb.com/chm/
Installations
Installation du SGBDR
Au moins quatre possibilités avec Windows :
MYSQL : installation rapide et assistée (Cf support Administration).
EasyPHP : installation rapide et assistée (WAMP).
WAMP5 : installation rapide et assistée (WAMP).
XAMPP : installation rapide et assistée (WAMP).
Installation des outils
PhpMyAdmin
Avec EasyPHP, WAMP et XAMPP l'outil PHPMyAdmin est fourni.
Pour l'installer de façon indépendante, phpMyAdmin-3.2.3-all-languages.zip est téléchargeable à HYPERLINK "http://www.phpmyadmin.net/home_page/downloads.php" http://www.phpmyadmin.net/home_page/downloads.php
MysqlQueryBrowser de MySQL AB
Mais il existe un outil plus convivial : MySQL Query Browser (pour Windows, Mac et Linux). C'est un utilitaire gratuit édité par MySQL.
DBDesignor de FabForge.net
AGL pour la conception de la BD (AGL de conception, reverse engineering, QBE).
MySQL Workbench de Mysql AB
AGL pour la conception de la BD (AGL de conception, reverse engineering, QBE).
MysqlAministrator de Mysql AB
Outil d'administration des BD.
Le MySQL Query Browser
MySQL Query Browser est un client lourd graphique (à la différence du client léger PHPMyADMIN) qui permet de :
Créer, modifier et supprimer des bases de données,
Créer, modifier et supprimer des tables.
Créer, visualiser, modifier et supprimer des enregistrements.
Créer et modifier des procédures et fonctions stockées.
Pour de plus amples détails cf le support MySQL Query Browser.
Connexion
EMBED PBrush
Interface
Ligne de commande Shémas Signets Histoique des commandes
Rafraîchissement Exécution
Espace Résultats Syntaxe et aide Fonctions
Création d'une base
Cliquez droit dans le volet de droite nommé Schemata.
Et validez sur Create New Schéma.
Nommez la nouvelle base.
Le jeu de caractères et la collation sont définis par défaut. Sa modification s'effectue en mode commande. Cf plus loin.
Suppression d'une base de données.
Pour supprimer une base de données il faut cliquer droit dans l'espace shemata sur l'objet et sélectionner soit Drop Schema.
C'est irréversible.
Création d'une table
Permet de créer une table avec des champs typés.
La clé primaire est automatiquement le premier champ. Cela est modifiable par clic.
La table Pays par exemple
pays (id_pays, nom_pays)
Champs de la table
Type de table (Moteur) et jeu de caractères.
Le moteur InnoDB permet la gestion des clés étrangères, la gestion des transactions et le verrouillage au niveau des lignes de tables.
Ce moteur est plutôt utilisé pour l'insertion et la mise à jour.
Le moteur MyISAM ne pas permet ces gestions.
Ce moteur est plutôt utilisé pour la consultation de données, pour DataWarehouse.
C'est un moteur plus rapide.
Les jeux de caractères permettent de préciser les "alphabets" que l'on va utiliser (Les caractères accentués
).
Pour les jeux de caractères soyez attentif aussi à ceux des colonnes.
La collation détermine l'algorthime de comparaison donc de tri ou de comparaison pour les jointures.
Création d'une clé étrangère
Il faut au préalable créer la table parent pays id_pays, nom_pays).
Ensuite créer la table enfant villes cp, nom_ville, id_pays).
Les tables doivent être de moteur InnoDB.
Il est préférable que la colonne clé étrangère soit NOT NULL (id_pays de villes).
Il est préférable d'indexer la future colonne étrangère (id_pays de villes).
Pour modifier la strucrure d'une table appuyez sur la touche F2.
La table Villes (et son parent la table Pays)
Dans l'onglet Foreign Keys, cliquez sur +, nommez la clé étrangère, sélectionnez la table parent, reliez les colonnes parent et enfant.
Les options de DELETE et de UPDATE sont au nombre de 4 :
Cascade : supprime ou modifie en cascade,
No Action : même effet que restrict,
Set Null : affecte la valeur NULL; possible si la clé étrangère est positionnée à NULL,
Restrict : interdit la suppression du parent si au mois un enfant existe.
Modification, suppression d'une table
Pour modifier ou visualiser la structure d'une table il faut la sélectionner, cliquer droit et sélectionner Edit Table.
Ou la sélectionnez et F2.
EMBED MSPhotoEd.3
Pour supprimer une table il faut cliquer droit sur l'objet et sélectionner Drop table.
C'est irréversible.
Travailler en mode ligne de commandes
Avec MySQL Query Browser
Vous sélectionnez une base de données. Vous cliquez droit et vous sélectionnez "Make Default Schema".
Vous saisissez la commande SQL dans le bandeau du haut : SELECT cp, nom_ville FROM villes;
Vous vous assurez que vous êtes dans la ligne de commande.
Vous cliquez sur le bouton Execute.
EMBED MSPhotoEd.3
Les résultats s'affichent en-dessous.
EMBED MSPhotoEd.3
Note : vous pouvez aussi cliquer/glisser la table vers le volet "Résultats"
Travailler avec l'utilitaire mysql
Se connecter au serveur
Mysql h serveur u utilisateur p
Exemples
C:\
\mysql\bin>mysql --host=localhost --user=root --password= --database=cours
ou
C:\
\mysql\bin>mysql -h localhost -u root -D cours p
ou
C:\
\mysql\bin>mysql h localhost u root -p
Note : le mode raccourci ne fonctionne pas avec toutes les versions.
Ensuite il vous sera demandé de saisir le mot de passe.
Enfin vous êtes dans l'interface MySQL avec son prompt.
Lister les bases de données du serveur
Mysql>show databases;
Pour sélectionner une base
Mysql>use nom_de_la_bd;
Exemple
MySQL>use mysql;
Puis les commandes SQL
Mysql>SELECT * FROM user;
Lister les tables
Mysql>show tables;
Lister la structure d'une table
Desc nom_de_table;
Exemple
dans la base MySQL
Desc user;
Pour sortir
Exit;
Travailler Avec PHPMyADMIN
Au niveau de la base de données cliquez sur EMBED MSPhotoEd.3
LES OBJETS MySQL
Le LDD
Le LDD (Data Definition Language ou Langage de Définition de Données) permet de créer, modifier ou supprimer les objets.
Les objets MySQL sont les bases de données, les users, les tables, les contraintes, les index, les views,
Il comprend 3 verbes :
CREATE pour créer un objet,
ALTER pour modifier un objet,
DROP pour supprimer un objet.
Les bases de données
Création
Syntaxe
CREATE DATABASE [IF NOT EXISTS] nom_de_base
[DEFAULT CHARACTER SET jeu_de_caractères
COLLATE collation];
Exemples
CREATE DATABASE IF NOT EXISTS base_exos;
CREATE DATABASE IF NOT EXISTS base_exos
DEFAULT CHARACTER SET utf8
COLLATE utf8_general_ci;
USE base_exos;
Autres jeux de caractères :
CREATE DATABASE bd1 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE DATABASE bd2 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Notes :
Un jeu de caractères est un ensemble de symboles et de codes.
Une collation est un ensemble de règles permettant la comparaison de caractères dans un jeu.
utf8 : un encodage UTF-8 encode un ensemble de caractères Unicode sur 1, 2 ou octets.
Il permet le stockage de textes de 650 langages.
La collation general_ci est basée sur un algorithme simple et rapide de comparaison.
La collation unicode_ci sur un algoritme plus complexe.
Cf : HYPERLINK "http://dev.mysql.com/doc/refman/5.1/en/charset-unicode-sets.html" http://dev.mysql.com/doc/refman/5.1/en/charset-unicode-sets.html
Utf8 : un encodage Utf8, correspond à la norme ISO 8859-1 (Alphabet de l'Europe occidentale). C'est une table de 191 caractères. Elle comprend les caractères accentués du français.
La collation pour le français est utf8_general_ci ou utf8_general_cs.
Attention, par défaut de nombreuses plateformes MySQL sont en utf8 collation utf8_swedish_ci.
Modification d'une base de données
Syntaxe
ALTER DATABASE nom_de_base DEFAULT CHARACTER SET jeu COLLATE collation;
Exemple
Modification de la collation du jeu de caractères.
ALTER DATABASE base_exos DEFAULT CHARACTER SET utf8 COLLATE utf8_general_cs;
Supression d'une base de données
DROP DATABASE nom_de_base;
DROP DATABASE base_exos;
Les tables
Les types de données.
Les grandes catégories de types de données sont :
Numériques
Caractères
Dates
Binaires
Ensemble (Enumeration ou Set)
La taille de l'affichage est paramétrable avec l'attribut (M).
Les types numériques peuvent être signés ou non (UNSIGNED).
Ils peuvent aussi être complétés par des 0 (ZEROFILL).
TypeSous-typesOctetsExtensionsNumériquesTinyInt10 à 255 ou 127 à 128Smallint2-32 768 à 32 767 ou 0 à 65 535Mediumint3-8 388 608 à 8 388 607 ou 0 à 16 777 215Int[(M)]4-2 147 483 648 à 2 147 483 647
Bigint80 à 18 446 744 073 709 551 615Float,
Float(M,D)4Ce type de données permet de stocker des nombres flottants à précision simple. Va de -1.175494351E-38 à 3.402823466E+38
Float est à éviter (Les calculs renvoyés sont incertains)
Float(M,D); M pour le nombre de chiffres à afficher, D pour le nombre de chiffres décimaux.Double ,
Double(M,D) 8Stocke des nombres flottants à double précision de -1.7976931348623157E+308 à -2.2250738585072014E-308, 0, et de 2.2250738585072014E-308 à 1.7976931348623157E+308.DateDate3'AAAA-MM-JJ'Time3'HH:MM:SS'Datetime8'AAAA-MM-JJ HH:MM:SS'Timestamp4Year1CaractèresChar(N)N255 caractères maximumVarchar(N)N255 caractères maximum (MySQL convertit en TEXT ou MEDUIMTEXT si vous dépassez 255)BinaireTinyBlob255Blob65 535Mediumblob16 MoOu 16 777 215 d'octetsLongblob4 GoOu 4 294 967 295 d'octetsTextesTinyText255Text65 535MediumText16 MoOu 16 777 215 d'octetsLongText4 GoOu 4 294 967 295 d'octetsEnumérationEnum('valeur1','valeur2',...)Une chaîne qui peut prendre une valeur, sélectionnée parmi une liste 'valeur1', 'valeur2', ..., NULL ou la valeur spéciale d'erreur "". 65535 valeurs distinctes sont autorisées. Donc un choix unique et obligatoire dans la liste autrement une erreur survient et une chaîne vide est affectée.
L'interface sera une liste déroulante ou des boutons radio.EnsembleSet('valeur1' , 'valeur2',...)Une chaîne, qui peut prendre zéro, une ou plusieurs valeurs, choisies parmi une liste de valeurs 'valeur1', 'valeur2', ... Une valeur SET peut avoir un maximum de 64 membres. Donc choix multiple facultatif.
L'interface sera une liste à choix multiples ou des cases à cocher.
Notes :
Pour les chaînes :
L'attribut BINARY signifie que les valeurs sont classées et triées en tenant compte de la casse, suivant l'ordre des caractères ASCII de la machine.
L'attribut ASCII peut être spécifiée avec, pour assigner le jeu de caractère utf8 à une colonne de type CHAR.
L'attribut UNICODE peut être spécifié pour assigner le jeu de caractères ucs2 à une colonne CHAR.
Pour les numériques :
UNSIGNED signifie non signé,
ZEROFILL signifie complété par des 0 et est de fait UNSIGNED.
Création d'une table
Syntaxe
CREATE TABLE nom_de_table(
nom_de_colonne TYPE CONTRAINTE
[, col2
,
[Contrainte de table]])
[ENGINE moteur_de_table]
[DEFAULT CHARSET=jeu_de_caractères COLLATE=collation];
Exemple de base (sans contrainte)
CREATE TABLE villes (cp CHAR(5), nom_ville VARCHAR(50));
Avec une clé primaire, un auto_increment et un moteur spécifique
CREATE TABLE clients (
id_client INT(5) NOT NULL AUTO_INCREMENT ,
nom VARCHAR(50) NOT NULL ,
prenom VARCHAR(50) NULL ,
adresse VARCHAR(100) NULL ,
date_naissance DATE NULL ,
cp CHAR(5) NOT NULL ,
PRIMARY KEY ( id_client )
) ENGINE = InnoDB;
Avec en plus un test d'existence et un jeu de caractères spécifique
CREATE TABLE IF NOT EXISTS clients (
id_client INT(5) NOT NULL AUTO_INCREMENT ,
nom VARCHAR(50) NOT NULL ,
prenom VARCHAR(50) NULL ,
adresse VARCHAR(100) NULL ,
date_naissance DATE NULL ,
cp CHAR(5) NOT NULL ,
PRIMARY KEY (id_client)
) ENGINE = InnoDB
DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
Avec une énumération (Choix obligatoire parmi la liste de valeurs)
connu_par ENUM('Internet','Bouche à oreille','Presse') default NULL,
Avec un ensemble (Choix facultatif dans la liste, le choix peut être multiple)
lectures SET('Romans','Essais','Scolaires','Art','Techniques') default NULL,
Les contraintes
Les contraintes prises en charge par MySQL 5 sont (D'autres sont acceptées mais non validées : palges,
) :
NOT NULL,
PRIMARY KEY,
INDEX.
Exemple avec des colonnes NOT NULL
CREATE TABLE villes (cp CHAR(5) NOT NULL, nom_ville VARCHAR(50) NOT NULL, site VARCHAR(50) NULL , photo VARCHAR(50) NULL , id_pays CHAR(3) NOT NULL);
Exemple avec la création d'une clé primaire.
CREATE TABLE villes
(
cp CHAR(5) NOT NULL ,
nom_ville VARCHAR(50) NOT NULL ,
site VARCHAR(50) NULL ,
photo VARCHAR(50) NULL ,
id_pays CHAR(3) NOT NULL ,
PRIMARY KEY (cp)
)
ENGINE = InnoDB;
Exemple de création d'une table avec une clé primaire et une colonne indexée
CREATE TABLE villes (
cp CHAR(5) NOT NULL ,
nom_ville VARCHAR(50) NOT NULL ,
site VARCHAR(50) NULL ,
photo VARCHAR(50) NULL ,
PRIMARY KEY (cp) ,
INDEX (nom_ville)
) ENGINE = InnoDB;
Création d'une table à partir d'une autre table
CREATE TABLE table_a_creer
AS SELECT * | colonnes FROM table_source | jointure [WHERE condition];
CREATE TABLE villes_bis AS SELECT * FROM villes;
EMBED MSPhotoEd.3 Seule la structure de base est copiée. Les clés
sont omises dans la copie.
Le schéma de la base COURS
Cf les annexes
Renommage d'une table
Syntaxe
ALTER TABLE ancien_nom RENAME TO nouveau_nom;
Exemple
ALTER TABLE villes_bis RENAME TO villes_2;
Suppression d'une table
Syntaxe
DROP TABLE [IF EXISTS] nom_de_table;
Exemple
DROP TABLE villes_2;
Modification de la structure d'une table
Syntaxes
Pour ajouter une colonne ou une contrainte.
ALTER TABLE nom_de_table ADD
[, ADD
]
Pour supprimer une colonne.
ALTER TABLE nom_de_table DROP nom_de_colonne [, DROP nom_de_colonne];
Pour modifier une colonne ou une contrainte.
ALTER TABLE nom_de_table CHANGE
Exemple : ajout d'une clé primaire
CREATE TABLE villes (
cp CHAR(5) NOT NULL ,
nom_ville VARCHAR(50) NOT NULL
) ENGINE = InnoDB;
ALTER TABLE villes ADD PRIMARY KEY (cp);
Exemple : ajout d'une colonne
ALTER TABLE villes ADD id_pays CHAR(3) NOT NULL;
Exemple : suppression d'une colonne
ALTER TABLE villes DROP id_pays;
Exemple : ajout d'un index
Cf plus loin
Exemple : modification d'un type
ALTER TABLE villes CHANGE id_pays id_pays INT(3) NOT NULL;
Exemple : modification d'une contrainte (NOT NULL -> NULL)
ALTER TABLE villes CHANGE id_pays id_pays CHAR(3) NULL;
Et inversement (Si aucune données n'est dans la table)
ALTER TABLE villes CHANGE id_pays id_pays CHAR(3) NOT NULL;
Autre syntaxe pour la modification d'une colonne
ALTER TABLE nomDeTable MODIFY COLUMN nomDeColonne Type Contrainte;
Exemple
ALTER TABLE villes MODIFY COLUMN id_pays CHAR(3) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
Ou
ALTER TABLE villes MODIFY COLUMN id_pays CHAR(3) NOT NULL;
Les contraintes (Constraint)
Création d'une contrainte
Syntaxe
ALTER TABLE nom_de_table
ADD CONSTRAINT nom_contrainte Contrainte [, ADD CONSTRAINT
];
Note : bien entendu une contrainte peut être créée lors de la création de la table comme nous l'avons vu précédemment.
Admettons la table suivante STAGIAIRES(#id_stagiaire, nom, statut, #cp).
CREATE TABLE stagiaires(id_stagiaire INT(5), nom VARCHAR(50), age INT, cp CHAR(5)) ENGINE = innoDB;
Clé primaire
ALTER TABLE stagiaires
ADD CONSTRAINT pk_stagiaires
PRIMARY KEY (id_stagiaire);
Clé étrangère
ALTER TABLE stagiaires
ADD CONSTRAINT fk_stagiaires_cp
FOREIGN KEY (cp)
REFERENCES villes(cp)
ON DELETE CASCADE ON UPDATE CASCADE;
Valeur unique
ALTER TABLE stagiaires
ADD CONSTRAINT stagiaires_nom_u
UNIQUE (nom);
Validité (Plage,
) MySQL ne supporte pas encore ce type de contrainte.
ALTER TABLE stagiaires ADD CONSTRAINT cst_age CHECK age BETWEEN 18 AND 25;
Cf le type ENUM.
Clé étrangère réflexive
ALTER TABLE vendeurs ADD CONSTRAINT FK_vendeurs_id_vendeur FOREIGN KEY FK_vendeurs_id_vendeur (chef)
REFERENCES vendeurs (id_vendeur)
ON DELETE RESTRICT
ON UPDATE RESTRICT
, ROW_FORMAT = DYNAMIC;
Suppression d'une contrainte
ALTER TABLE nom_de_table DROP TYPE_DE_CONTRAINTE [nom_de_contrainte];
ALTER TABLE stagiaires DROP PRIMARY KEY;
ALTER TABLE stagiaires DROP FOREIGN KEY fk_stagiaires_cp;
ALTER TABLE stagiaires DROP INDEX stagiaires_nom_u;
Les index (Index)
Création d'un index
Un index est un accélérateur.
Un index peut être créé dans l'instruction de création de table (cela permet d'en créer plusieurs) ou via Create Index (Un seul à la fois).
Un index peut s'appliquer à un champ ou plusieurs.
Un index peut être appliqué à un champ scalaire.
Un index peut être UNIQUE (Mais accepte les valeurs NULL, à la différence des Primary Key) ou NOT UNIQUE.
Un index peut-être appliqué à un préfixe de colonne (colonne(n)).
Un index peut être appliqué à un texte long (FULL TEXT).
Syntaxe de CREATE INDEX.
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX nom_d_index ON nom_de_table (nom_de_colonne[(n)],...)
FULLTEXT précise que l'index, même sur les textes longs, doit être créé sur toute la valeur du texte.
SPATIAL indexe les colonnes dont les types sont géométriques.
Exemple
CREATE INDEX i_villes_ville ON villes(nom_ville);
CREATE INDEX i_clients_nom_prenom ON clients(nom, prenom);
CREATE INDEX i_nom_ville ON villes(nom_ville(5)); -- Préfixe de colonne
Syntaxe de ALTER TABLE
ADD INDEX
ALTER TABLE nom_de_table ADD INDEX [nom_d_index] (nom_de_colonne [(n)] [, nom_de_colonne]);
Exemples
ALTER TABLE villes ADD INDEX i_villes_nom_ville (nom_ville); -- Un index
ALTER TABLE villes ADD INDEX i_villes_nom_ville (nom_ville), add index i_villes_id_pays(id_pays); -- Deux index
ALTER TABLE villes ADD INDEX i_villes_nom_ville_id_pays (nom_ville,id_pays); -- Un index sur 2 colonnes
Suppression d'un index
Syntaxe
DROP INDEX nom_d_index ON nom_de_table;
Exemple
DROP INDEX ind_villes_ville ON villes;
Syntaxe
ALTER TABLE nom_de_table DROP INDEX nom_d_index;
Exemple
ALTER TABLE villes DROP INDEX ind_villes_nom_ville;
Visualisation des Index
Via la structure de la table
Mysql>SHOW CREATE TABLE nom_de_table \G
mysql> SHOW CREATE TABLE villes \G
Table: villes
Create Table: CREATE TABLE villes (
cp varchar(5) NOT NULL,
nom_ville varchar(50) NOT NULL,
site varchar(50) DEFAULT NULL,
photo varchar(50) DEFAULT NULL,
id_pays char(3) DEFAULT NULL,
PRIMARY KEY (cp),
KEY Index_id_pays (id_pays)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
Via la structure des index d'une table
SHOW INDEX FROM nom_de_table \G
mysql> SHOW INDEX FROM villes \G
*************************** 1. row ***************************
Table: villes
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: cp
Collation: A
Cardinality: 12
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
*************************** 2. row ***************************
Table: villes
Non_unique: 1
Key_name: Index_id_pays
Seq_in_index: 1
Column_name: id_pays
Collation: A
Cardinality: NULL
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Index sur préfixe
Les index sur préfixe sont plus rapides.
CREATE INDEX i_nom_ville ON villes(nom_ville(5));
Table: villes
Non_unique: 1
Key_name: i_nom_ville
Seq_in_index: 1
Column_name: nom_ville
Collation: A
Cardinality: NULL
Sub_part: 5
Packed: NULL
Null:
Index_type: BTREE
Notes :
Les index par défaut sont de type B-TREE (arbre balancé).
Les index FULLTEXT ne peuvent indexer que des colonnes VARCHAR ou TEXT, et seulement dans les tables MyISAM
Les index SPATIAL peuvent indexer les colonnes spatiales, et uniquement avec les tables MyISAM.
Si une base de données est suffisamment petite pour tenir en mémoire, alors le plus rapide pour faire des requêtes est d'utiliser les index hash.
R-trees are tree data structures that are similar to B-trees, but are used for spatial access methods i.e., for indexing multi-dimensional information
Utilisation des index
Par défaut les index sont utilisés avec un SELECT comportant une clause WHERE sur une colonne indexée.
Pour les désactiver vous pouvez utiliser une fonction ou une opération neutre (+0, CONCAT '',
).
Ou utiliser une clause d'usage d'index :
USE INDEX, IGNORE INDEX et FORCE INDEX affectent les index qui sont utilisés lors du choix de la méthode de sélection des lignes dans la table lors d'une jointure.
Elles n'affectent pas l'utilisation de l'index dans les clauses ORDER BY ou GROUP BY.
SELECT * FROM villes USE INDEX (i_villes_nom_ville) where nom_ville = 'Lyon';
Ou
SELECT * FROM villes IGNORE INDEX (i_villes_nom_ville) where nom_ville = 'Lyon';
Cf explain.
TP PARISCOPE : Création et Manipulation des objets de la base
Enoncés
Les corrigés sont dans les annexes.
Créez les tables de la BD Pariscope.
Toutes les tables du modèle relationnel PARISCOPE (cf le modèle au chapitre au 15.6).
Créez les clés étrangères.
Toutes les clés étrangères.
Créez les index.
Titre du film dans Films.
Genre dans Genres.
Nom de l'acteur dans Acteurs.
Modifiez les tables.
Ajouter une colonne à la table cinemas : acces_handicapes.
Modifier le type de l'année du film (INT(4) vers CHAR(4)) et rétablissez ensuite.
Passez la colonne annee du film de NOT NULL à NULL.
Ajouter une contrainte sur l'année du film (entre 1900 et 2030) [KO].
MISE A JOUR DES DONNEES
Présentation
Il existe 4 verbes (CRUD : Create, Read, Update, Delete) du LMD (Langage de manipulation de données) dont 3 permettant la mise à jour des données :
INSERT pour ajouter un ou des enregistrements.
DELETE pour supprimer un ou des enregistrements.
UPDATE pour modifier un ou des enregistrements.
Pour visualiser les résultats des opérations de MAJ il faut savoir extraire les données d'une table; l'ordre SELECT le permet.
Exemple : SELECT * FROM villes;
qui visualisera l'ensemble des champs et des enregistrements de la table Villes.
Insertion de données (INSERT)
Première syntaxe
Insérer un enregistrement.
INSERT INTO nom_de_table [(col1, col2,
)]
VALUES (valeur1, valeur2,
);
Exemples
-- Insère le 21ème arrondissement
INSERT INTO villes(cp, nom_ville) VALUES('75021' , 'Paris 21');
-- Insertion dans une table ayant un champ de type ENUM.
-- Une interface graphique présentera des boutons radio.
INSERT INTO personnels (nom ,categorie)
VALUES ('Tintin', 'M');
INSERT INTO personnels (nom ,categorie)
VALUES ('Casta', 'C');
-- Insertion dans une table ayant un champ de type SET.
-- On insère la valeur de type SET entre ' (Quote simple).
-- Si plusieurs valeurs doivent être insérées on les sépare par une virgule.
-- Une interface graphique présentera une liste à choix multiples.
INSERT INTO personnes (nom ,hobbies ,cp)
VALUES ('Tintin', 'S', '75011');
INSERT INTO personnes (nom ,hobbies ,cp)
VALUES ('Haddock', 'C,T', '75011');
-- Insertion dans une table avec un auto_increment
-- Et récupération de la nouvelle valeur.
INSERT INTO clients(nom, prenom, cp)
VALUES('Tournesol','Bruno', '75011');
SELECT LAST_INSERT_ID();
Note : ne fonctionne pas avec MySQL Query Browser mais fonctionne sous le client Mysql.
Deuxième syntaxe
Insérer plusieurs enregistrements via un seul ordre INSERT (Syntaxe non standard propre à MySQL).
INSERT INTO nom_de_table(col1, col2,
)
VALUES (valeur1, valeur2,
) , (valeur3, valeur4)
;
Exemple
-- Insère Caen et Lille
INSERT INTO villes (cp , nom_ville)
VALUES
('14000', 'Caen'),
('59000', 'Lille');
Troisième syntaxe
Insérer un ou plusieurs enregistrements à partir d'un SELECT (Donc d'une autre table).
INSERT INTO table1 [(col1, col2,
)]
SELECT col1, col2,
FROM table2
;
Exemple
-- Insère dans la table villes_bis l'ensemble des enregistrements de la table Villes
INSERT INTO villes_bis
SELECT *
FROM villes;
Insertion de données (REPLACE)
Objectif
Insérer des données en remplaçant les données qui créent des confilts d'unicité.
C'est un équivalent d'un INSERT si la ligne n'existe pas et d'un DELETE + INSERT si la ligne existe. D'ailleurs le message de MySQL est soit "1 row affected"
soit "2 rows affected".
Syntaxes
REPLACE INTO nom_de_table(colonne1 [, colonne2])
VALUES(valeur1 [, valeur2]);
REPLACE INTO nom_de_table [(colonne1 [, colonne2])]
SELECT colonne1 [, colonne2]
FROM nom_de_table
[WHERE condition];
Exemple
REPLACE INTO villes(cp, nom_ville)
VALUES('75031','Paris XXXI');
Suppression de données (DELETE)
Syntaxe
DELETE FROM nom_de_table [WHERE condition];
Exemples
-- Supprime toutes les villes
DELETE FROM villes;
-- Supprime les clients qui habitent le 12ème à Paris
DELETE FROM clients WHERE cp = '75012';
Autre Syntaxe
Supprimer dans une table en fonction d'un SELECT (cf les requêtes imbriquées)
DELETE FROM nom_de_table WHERE colonne Opérateur (SELECT
);
Exemples
-- Supprime les lignes de commandes de l'an 2000
DELETE FROM ligcdes WHERE id_cde IN
(SELECT id_cde FROM cdes WHERE date_cde LIKE '%2000%');
ou
DELETE FROM ligcdes WHERE id_cde IN
(SELECT id_cde FROM cdes WHERE YEAR(date_cde) = 2000);
-- Supprime les lillois
DELETE FROM clients WHERE cp IN
(SELECT cp FROM villes WHERE nom_ville LIKE 'Lille%');
Suppression des données (TRUNCATE)
TRUNCATE supprime toutes les données de la table. Le résultat est le même que DELETE FROM nom_de_table.
L'exécution est plus rapide.
En fait TRUNCATE droppe la table et la recrée.
Syntaxe
TRUNCATE TABLE nom_de_table;
Exemple
TRUNCATE TABLE villes_bis;
Si la table villes_bis n'existe pas lancez les commandes suivantes :
CREATE TABLE villes_bis AS SELECT * FROM villes;
SELECT * FROM villes_bis;
TRUNCATE villes_bis;
SELECT * FROM villes_bis;
Modification de données (UPDATE)
Syntaxe
UPDATE nom_de_table SET col1 = valeur1 [, col2 = valeur2] [WHERE condition];
Exemples
-- Met en majuscule les noms des villes
UPDATE villes SET nom_ville = UPPER(nom_ville);
-- Modifie le nom de la ville en question
UPDATE villes SET nom_ville = 'Paris' WHERE nom_ville = 'Paris 12';
Autre syntaxe
Modifier dans une table en fonction d'un SELECT (cf les requêtes imbriquées)
UPDATE nom_de_table SET col1 = valeur1 [, col2 = valeur2]
WHERE colonne Opérateur (SELECT
);
Exemple
Mettre en majuscules les noms des clients qui habitent Lille.
UPDATE clients SET nom = UPPER(nom)
WHERE cp IN
(SELECT cp FROM villes WHERE UPPER(nom_ville) LIKE UPPER('lille%'));
TP PARISCOPE : Mise à jour des données
Enoncés MAJ PARISCOPE
Les corrigés sont dans les annexes.
EnoncéAjoutez le genre "Divers"Insérez un film de ce nouveau genrePassez ce film dans les policiersSupprimez le genre "divers"Archivez les films d'avant 2000 (Sans les supprimer)Mettez les titres des films en majusculesPuis mettez-les en nom propre
L'EXTRACTION DES DONNEES (L'ORDRE SELECT)
SELECT mono table sans condition
Syntaxe
SELECT [DISTINCT] *| col1, col2,
FROM nom_de_table;
Exemples
Tout sur les villes
SELECT * FROM villes;
Les noms et cp des clients (Projection)
SELECT nom, cp FROM clients;
SELECT DISTINCT cp FROM clients;
Extraire un certain nombre d'enregistrements (Restriction)
Syntaxe
SELECT *| col1, col2,
FROM nom_de_table
LIMIT début, nombre;
Note : syntaxe spécifique à MySQL. Cf plus loin pour le WHERE.
Exemples
Les 3 premiers : SELECT * FROM clients LIMIT 0,3;
Les trois suivants : SELECT * FROM clients LIMIT 3,3;
Le tri
Syntaxe
SELECT *| col1, col2,
FROM nom_de_table
ORDER BY col1 [ASC | DESC] [, col2
];
Exemples
SELECT * FROM clients ORDER BY nom;
SELECT * FROM clients ORDER BY nom DESC;
SELECT * FROM clients ORDER BY cp, nom;
Note : la clause ORDER BY est toujours la dernière clause d'un ordre SELECT.
Quelques fonctions propriétaires
Sur les chaînes
SyntaxeActionExempleType résultatCHAR(n)Retourne le caractère dont la valeur ASCII= nCHR(65) donne AcharASCII(char)Retourne le code ASCIIASCII('A') donne 65intCONCAT(c1, c2 )Retourne une seule chaîne (La concaténation)CONCAT('PA','RIS') donne PARISChaîneUPPER(ch)Transforme ch en majusculeUPPER('paris') retourne PARISChaîneLOWER(ch)Retourne la chaîne en minusculeLOWER('ORACLE') donne oracleChaîneREPLACE(ch1, ch2, ch3)Cherche dans ch1 la ch2 puis la remplace par ch3REPLACE('JACK et JUE','J','BL') donne BLACK et BLUEChaîneTRIM(ch) et RTRIM(ch) et LTRIM(ch)Supprime des caractères espace devant et derrière TRIM(' PARIS ') donne PARISChaîneSOUNDEX(ch1)Retourne la représentation phonétique de ch1SELECT nom FROM clients WHERE SOUNDEX(nom)=SOUNDEX('Dupaunt')
trouvera Dupont, Dupond, ...ChaîneLEFT(ch, n)Extrait de la chaîne ch n caractères au débutSELECT LEFT(CP,2) FROM villes retourne le code du départementChaîneRIGHT(ch, n)Extrait de la chaîne ch n caractères à la finSELECT RIGHT(CP,3) FROM villes retourne le code de la communeChaîneSUBSTR(ch1,n[,m])
SUBSTRING(ch1,n[,m])Extrait de la chaîne ch1 à partir de la position n, le nombre de caractères mSUBSTR('PARIS LA DEFENSE',7,2) retourne LAChaîneLENGTHCalcule la longueur d'une chaîneLENGTH('Tintin') retourne 6int
Sur les numériques
SyntaxeActionExempleType de résultatsABS(n)Extrait la valeur absolue de nSELECT ABS(-125) [FROM dual];
affiche 125NumériqueROUND(m, n)Arrondit m à n décimalesSELECT ROUND(15.2358,2) [FROM dual]; donne 15.24NumériqueCEIL(n)Calcule l'entier >= nSELECT CEIL(15.4) [FROM dual]; donne 16NumériqueFLOOR(n)La partie entière de nSELECT FLOOR(15.8) [FROM dual]; donne 15NumériqueMOD(m, n)Renvoie le reste de la division de m par nSELECT MOD(25,7) [FROM dual]; donne 4NumériquePOWER(m, n)Calcule m à la puissance nSELECT POWER(3,2) "Puissance" [FROM dual]; donne 9NumériqueSIN, COS, TANCalcule le sinus, cosinus tangente, etc. Numérique
Sur les dates
SyntaxeActionExempleType de résultatsYEAR(d)Extrait l'annéeSELECT YEAR(date_cde), date_cde FROM cdes;NumériqueMONTH(d)Extrait le moisSELECT MONTH(date_cde), date_cde FROM cdes;NumériqueDAY(d)Extrait le quantième du moisSELECT DAY(date_cde), date_cde FROM cdes;NumériqueMONTHNAME(d)Extrait le nom du moisSELECT MONTHNAME(date_cde), date_cde FROM cdes;NumériqueDAYNAME(d)Extrait le nom du jourSELECT DAYNAME(date_cde), date_cde FROM cdes;NumériqueDAYOFWEEK(d)Extrait le jour de la semaineSELECT DAYOFWEEK(date_cde), date_cde FROM cdes;NumériqueDAYOFYEAR(d)Extrait le jour de l'annéeSELECT DAYOFYEAR(date_cde), date_cde FROM cdes;NumériqueWEEKOFYEAR(d)Extrait la semaine de l'annéeSELECT WEEKOFYEAR(date_cde), date_cde FROM cdes;Numérique
Fonctions système
Curdate()Date du serveurNow()Date et heure du serveurSysDate()Date et heure du serveur
Afficher une date au format français
EMBED MSPhotoEd.3
SELECT nom "Nom", date_naissance "Date de naissance USF",
DATE_FORMAT(date_naissance, '%d/%m/%Y') 'Date de naissance FRF'
FROM clients;
Autres formats :
%D : quantième avec suffixe anglais.
%W : Nom du jour.
%M : Mois en toutes lettres.
Cf la documentation officielle pour le reste.
Exercices :
Affichage long.
L'âge du capitaine.
Les opérateurs de comparaison
Les opérateurs de comparaison
OPERATEURDESCRIPTION=Egal!= , Différent de>Supérieur à>=Supérieur ou égal à= valeur = 5;
Note : si l'on veut une seule fois le même produit il faut cette requête-ci :
SELECT DISTINCT designation "Désignation"
FROM produits p , ligcdes l
WHERE p.id_produit = l.id_produit
AND qte >= 5;
Syntaxe ANSI
SELECT table1.col1, table1.col2, table2.col3
FROM table1 [INNER] JOIN table2
ON table1.col1 = table2.col2;
Exemples
Les villes et les clients (Sans alias de tables)
SELECT villes.nom_ville, clients.nom
FROM villes JOIN clients
ON villes.cp = clients.cp;
Les pays et les villes (Avec des alias de tables)
SELECT p.nom_pays, v.nom_ville
FROM pays p JOIN villes v
ON p.id_pays = v.id_pays;
Auto-jointure
C'est une jointure sur la même table.
Championnat (Theta auto-jointure).
SELECT c1.id_client, c1.nom, c2.id_client, c2.nom
FROM clients c1, clients c2
WHERE c1.id_client > c2.id_client;
Ou
SELECT c1.id_client, c1.nom, c2.id_client, c2.nom
FROM clients c1 JOIN clients c2
ON c1.id_client > c2.id_client;
Rapport hiérarchique : les vendeurs et leur chef
SELECT v1.id_vendeur, v1.nom, v1.chef, v2.nom "Nom du chef"
FROM vendeurs v1, vendeurs v2
WHERE v1.chef = v2.id_vendeur;
Cf plus loin pour voir le chef !
Les jointures externes
Objectif
Une jointure externe permet d'extraire les enregistrements d'une table ainsi que ceux de la deuxième table de jointure mais aussi ceux de la première table qui n'ont pas de correspondants dans la deuxième table.
Dans la table Villes il y a des villes qui n'ont pas de clients; ainsi une équi-jointure n'affiche que les villes où il y a des clients.
La jointure externe permettra d'afficher ainsi toutes les villes même celles sans clients.
Une jointure externe permettra avec une condition supplémentaire d'afficher les enregistrements sans correspondances.
Une jointure externe peut l'être à gauche ou à droite.
Une jointure externe à gauche ajoute un enregistrement NULL à droite (Deuxième table) pour le concaténer à l'enregistrement de la table de gauche (Première table) qui n'a pas de correspondants.
Syntaxe (ANSI)
SELECT table1.col1, table1.col2, table2.col3
FROM table1 RIGHT | LEFT OUTER JOIN table2
ON table1.col1 = table2.col2;
Exemples
Toutes les villes avec leurs clients ainsi que celles qui n'ont pas de clients
SELECT nom_ville, nom
FROM villes v LEFT OUTER JOIN clients c
ON v.cp = c.cp
ORDER BY nom;
Toutes les villes qui n'ont pas de clients
SELECT nom_ville, nom
FROM villes v LEFT OUTER JOIN clients c
ON v.cp = c.cp
WHERE nom IS NULL;
Plus loin avec la syntaxe ANSI
Trois tables : Equi jointure
SELECT pays.nom_pays, villes.nom_ville, clients.nom
FROM pays JOIN villes JOIN clients
ON pays.id_pays = villes.id_pays
AND villes.cp = clients.cp;
ou
SELECT pays.nom_pays, villes.nom_ville, clients.nom
FROM (pays JOIN villes ON pays.id_pays = villes.id_pays) JOIN clients
ON villes.cp = clients.cp;
Trois tables : jointures externes
SELECT pays.nom_pays, villes.nom_ville, clients.nom
FROM
(pays LEFT OUTER JOIN villes ON pays.id_pays = villes.id_pays)
LEFT OUTER JOIN clients ON villes.cp = clients.cp;
Les vendeurs et leur chef (Auto-jointure externe)
SELECT v1.id_vendeur, v1.nom, v1.chef, v2.nom "Nom du chef"
FROM vendeurs v1 LEFT OUTER JOIN vendeurs v2
ON v1.chef = v2.id_vendeur;
Le produit cartésien
Le produit cartésien est la concaténation de chaque ligne d'une table avec toutes les autres lignes d'une autre table.
D'emploi rare il peut être très utile pour des "saisies" de masse.
Premier exemple
Admettons deux tables Listes (Listes candidates) et Bureaux (Bureaux de votes)
CREATE TABLE listes (
id_liste int(10) unsigned NOT NULL default '0',
nom_liste varchar(50) NOT NULL default '',
PRIMARY KEY (id_liste)
) ENGINE=InnoDB;
INSERT INTO listes (id_liste, nom_liste) VALUES
(1, 'MODEM'),
(2, 'UMP'),
(3, 'PS'),
(4, 'PCF'),
(5, 'VERTS');
CREATE TABLE bureaux (
id_bureau int(10) unsigned NOT NULL default '0',
nom_bureau varchar(50) NOT NULL default '',
adresse varchar(100) NOT NULL default '',
inscrits int(10) unsigned NOT NULL default '0',
PRIMARY KEY (id_bureau)
) ENGINE=InnoDB;
INSERT INTO bureaux (id_bureau, nom_bureau, adresse, inscrits) VALUES
(1, 'Mairie', 'Place Léon Blum', 1101),
(2, 'Ecole Roquette', 'Rue de la Roquette', 1200),
(3, 'Ecole Folie Régnault', 'Rue de la Folie Régnault', 1001),
(4, 'Ecole Faidherbe', 'Rue Faidherbe', 1000),
(11, 'Ecole élémentaire Pihet', 'Rue Pihet', 800),
(12, 'Ecole Popincourt', 'Rue Popincourt', 1300),
(52, 'Ecole Roubo', 'Rue Roubo', 800);
Le produit cartésien sera
SELECT id_bureau, nom_bureau, adresse, inscrits, id_liste, nom_liste
FROM bureaux, listes;
Vous créez une table nommée 'resultats' ainsi
CREATE TABLE resultats
AS
SELECT id_bureau, nom_bureau, adresse, inscrits, id_liste, nom_liste, 0 "Voix"
FROM bureaux, listes;
Il ne restera plus qu'à saisir les résultats dans la colonne voix.
Deuxième exemple
Admettons la table 'Fourchettes' de prix
CREATE TABLE fourchettes (
plancher int(10) unsigned NOT NULL default '0',
plafond int(10) unsigned NOT NULL default '0',
libelle VARCHAR(45) NOT NULL default '',
PRIMARY KEY (plancher,plafond)
) ENGINE=InnoDB;
INSERT INTO fourchettes (plancher, plafond, libelle) VALUES
(0, 10, 'Economique'),
(11, 100, 'Moyen'),
(101, 1000, 'Cher');
La requête qui permet d'afficher les produits et leur libellé de fourchette.
SELECT designation, prix, libelle
FROM produits, fourchettes
WHERE prix BETWEEN plancher AND plafond
ORDER BY plancher, prix;
EMBED PBrush
TP PARISCOPE sur les jointures
JOINTURESListez les films et leur genre (libelle)Listez les films de Julia RobertsListez les films de CoppolaListez les films projetés actuellementListez les films de Julia Roberts projetés actuellementListez les films de Coppola projetés actuellement
LES REQUETES AGREGATS
Les fonctions agrégats
Objectif
Faire des calculs sur des ensembles ou sous-ensembles d'enregistrements.
Syntaxe
SELECT fonction_agregat(col1 | *),
FROM nom_de_table;
Fonctions
FONCTIONDESCRIPTIONCOUNT(*)Nombre de lignes satisfaisant une requête.COUNT(DISTINCT | ALL COLONNE)Nombre des valeurs de colonnes vérifiant la requête.
SUM(DISTINCT | ALL COLONNE)Somme des valeurs de colonnes vérifiant la requête.
Avec DISTINCT somme les valeurs uniques (sans les doublons).AVG(DISTINCT | ALL COLONNE)Moyenne des valeurs de colonnes vérifiant la requête.
Avec DISTINCT moyenne des valeurs uniques (sans les doublons).MAX(DISTINCT | ALL COLONNE)Maximum des valeurs de la colonne.MIN(DISTINCT | ALL COLONNE)Minimum des valeurs de la colonne.STDDEV(DISTINCT | ALL COLONNE)Ecart type des valeurs de la colonne.VARIANCE(DISTINCT | ALL COLONNE)La variance des valeurs de la colonne.
Exemples
Nombre de villes
EMBED MSPhotoEd.3
SELECT COUNT(*) "Nombre de villes" FROM villes;
Nombre clients
EMBED MSPhotoEd.3
SELECT COUNT(*) FROM clients;
Nombre clients dont on connaît la date de naissance
EMBED MSPhotoEd.3
SELECT COUNT(date_naissance) FROM clients;
Nombre de noms de client différents
SELECT COUNT(DISTINCT nom) "Nombre de noms de client différents" FROM clients;
Moyenne des prix
SELECT AVG(prix) "Moyenne des prix" FROM produits;
Prix le plus élevé
SELECT MAX(prix) "Prix le plus élevé" FROM produits;
Nombre de clients résidant dans une ville
SELECT COUNT(*) "Nombre de clients"
FROM clients c, villes v
WHERE c.cp = v.cp
AND UPPER(nom_ville) = ('LILLE');
La clause GROUP BY
Regrouper les enregistrements lorsque l'on applique une fonction agrégat.
Syntaxe
SELECT fonction_agregat(col1 | *) [, colonne | fonction_agregat() ]
FROM nom_de_table
GROUP BY col1,
;
Il n'est possible d'avoir dans le SELECT que des fonctions agrégats ou des colonnes présentent dans la clause GROUP BY.
Exemples
Nombre de clients par cp.
EMBED MSPhotoEd.3
SELECT cp, COUNT(*) "Nombre de clients"
FROM clients
GROUP BY cp;
Nombre de clients par ville.
EMBED MSPhotoEd.3
SELECT nom_ville "Ville", COUNT(*) "Nombre de clients"
FROM clients c, villes v
WHERE c.cp = v.cp
GROUP BY nom_ville;
Nombre de commandes par année par client
EMBED MSPhotoEd.3
SELECT YEAR(date_cde) "Année", nom "Nom", COUNT(*) "Nombre de commandes"
FROM clients c, cdes cd
WHERE c.id_client = cd.id_client
GROUP BY c.id_client, nom, YEAR(date_cde)
ORDER BY YEAR(date_cde);
La clause HAVING
Appliquer une condition à un groupe.
Syntaxe
SELECT fonction_agregat(col1 | *) [, colonne | fonction_agregat() ]
FROM nom_de_table
GROUP BY col1,
HAVING fonction_agregat(col1 | *) > 1;
Exemples
Nombre de clients en fonction du CP quand ce nombre est supérieur à 1
EMBED MSPhotoEd.3
SELECT cp, COUNT(*) "Nombre de clients"
FROM clients
GROUP BY cp
HAVING COUNT(cp) > 1;
Clients ayant passé commande plus d'une fois en 2005
EMBED MSPhotoEd.3
SELECT YEAR(date_cde) "Année", c.id_client "Code client", nom "Nom", COUNT(*) "Nombre de commandes"
FROM clients c, cdes cd
WHERE c.id_client = cd.id_client
AND YEAR(date_cde) = '2005'
GROUP BY c.id_client, nom, YEAR(date_cde)
HAVING COUNT(*) > 1;
TP PARISCOPE sur les Agrégats
AGREGATSAffichez le nombre de filmsAffichez le nombre de projectionsAffichez le nombre de films sortis par annéeAffichez le nombre de films sortis en 2000Affichez le nombre de films sortis en 2005JOINTURES ET AGREGATSAffichez le nombre de films de CoppolaAffichez le nombre de films projetés actuellementAffichez le nombre de films projetés actuellement avec Julia RobertsAffichez le nombre d'acteurs par filmAffichez la liste des cinémas ouvertsAffichez la liste des cinémas fermés
LES REQUETES ENSEMBLISTES
Principes
Les opérations ensemblistes de SQL sont : l'Union, l'Intersection et la Différence.
Les opérateurs standards sont :
UNION qui renvoie l'ensemble des enregistrements des tables de l'union,
INTERSECT qui renvoie l'ensemble des enregistrements communs des tables de l'intersection,
MINUS ou EXCEPT qui renvoie l'ensemble des enregistrements qui appartiennent à une table et seulement à cette table.
Ces opérateurs doivent avoir comme opérandes des schémas identiques.
Les SGBDR n'implémentent pas nécessairement tous ces opérateurs.
C'est le cas de MySQL qui n'implémente que l'UNION.
Union : T1 Union T2
T1T2
Intersection : T1 Intersect T2
T1T2
Différence : T1 T2
T1T2
Différence : T2 T1
T1T2
Union
Syntaxe
SELECT schéma FROM table1
UNION
SELECT schéma FROM table2;
Exemples
"Cumul" des CP des clients et des villes
SELECT cp FROM clients
UNION
SELECT cp FROM villes;
Les clients et les clients étrangers
Admettons que la table Villes contienne des noms de villes étrangères dont le CP commence par 99.
Et quelques clients habitant ces villes.
Admettons la table clients_etrangers créée avec une requête du style :
CREATE TABLE clients_etrangers
AS SELECT * FROM clients
WHERE cp LIKE '99%';
Ce sont des clients qui résident aussi bien en France qu'à l'étranger.
Ajoutons dans la table clients_etrangers un nouvel enregistrement (ce sera un client qui ne réside qu'à l'étranger).
INSERT INTO clients_etrangers(id_client, nom, prenom, cp)
VALUES (22,'Loren','Sofia','99391');
SELECT * FROM clients
UNION
SELECT * FROM clients_etrangers;
Intersection (N'existe pas en MySQL)
Syntaxe SQL Standard
SELECT schéma FROM table1
INTERSECT
SELECT schéma FROM table2;
Exemples
Les CP communs des clients et des villes
SELECT cp FROM clients
INTERSECT
SELECT cp FROM villes;
D'où en MySQL
SELECT distinct clients.cp
FROM clients, villes
WHERE clients.cp = villes.cp;
Ou (cf requêtes imbriquées)
SELECT DISTINCT cp
FROM clients
WHERE cp
IN (SELECT cp FROM villes);
Les clients communs à Clients et clients_etrangers
SELECT * FROM clients
WHERE id_client
IN (SELECT id_client FROM clients_etrangers);
Différence (N'existe pas en MySQL)
Syntaxe SQL Standard
SELECT schéma FROM table1
MINUS | EXCEPT
SELECT schéma FROM table2
;
Exemple
Les villes où il n'y a pas de clients
SELECT cp FROM villes
EXCEPT
SELECT cp FROM clients;
D'où en MySQL
SELECT DISTINCT nom_ville
FROM villes LEFT JOIN clients ON villes.cp = clients.cp
WHERE clients.cp Is Null;
Ou (cf requêtes imbriquées)
SELECT DISTINCT nom_ville
FROM villes
WHERE cp
NOT IN (SELECT cp FROM clients);
Les clients strictement français
SELECT *
FROM clients
WHERE id_client
NOT IN (SELECT id_client FROM clients_etrangers);
Les clients strictement étrangers
SELECT *
FROM clients_etrangers
WHERE id_client
NOT IN (SELECT id_client FROM clients);
TP PARISCOPE sur les requêtes ensemblistes
REQUETES ENSEMBLISTESLa liste des acteurs et des réalisateursIntersectDifférence
LES REQUETES IMBRIQUEES
Principes
Une requête imbriquée est une requête qui utilise dans sa clause WHERE le résultat d'une autre requête.
Les requêtes imbriquées sont proches des jointures à la différence près que l'on ne peut afficher que les colonnes de la première table.
Une requête peut renvoyer :
Une seule ligne et une seule colonne (une seule valeur),
Une seule colonne (plusieurs valeurs),
Une seule ligne (plusieurs valeurs),
Plusieurs lignes et plusieurs colonnes (plusieurs valeurs).
Format 1 : la sous-requête renvoie un seul résultat
Syntaxe
SELECT col1, col2,
FROM table1
WHERE colonne =
(SELECT colonne FROM table2 WHERE condition);
L'opérateur doit être =.
Exemple 1
Les villes de France (On est sûr que France renvoie un seul ID; jointure possible)
SELECT * FROM villes
WHERE id_pays =
(SELECT id_pays FROM pays WHERE UPPER(nom_pays) = 'FRANCE');
Exemple 2 (Il faut être sûr qu'il n'y a qu'une seule Annabelle Fassiola née le 10 mai 1985)
Les clients qui habitent la même ville qu'Annabelle Fassiola née le 10 mai 1985.
SELECT nom, cp
FROM clients
WHERE cp =
(SELECT cp
FROM clients
WHERE UPPER(nom) = 'FASSIOLA'
AND UPPER(prenom) = 'ANNABELLE'
AND date_naissance = '1985-05-10'
);
La requête renvoie un seul résultat (une seule ligne mais plusieurs colonnes)
Villes2 (Avec une clé double)
EMBED MSPhotoEd.3
CREATE TABLE IF NOT EXISTS villes2 (
cp char(5) collate utf8_general_ci NOT NULL default '',
id_pays char(3) collate utf8_general_ci NOT NULL default '',
nom_ville varchar(45) collate utf8_general_ci NOT NULL default '',
PRIMARY KEY (cp,id_pays)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
INSERT INTO villes2 (cp, id_pays, nom_ville) VALUES
('75001', '033', 'Paris'),
('75001', '039', 'Rome');
Clients2 (Avec une clé étrangère double)
EMBED MSPhotoEd.3
CREATE TABLE IF NOT EXISTS clients2 (
id_client int(10) unsigned NOT NULL auto_increment,
nom varchar(45) character set utf8 collate utf8_general_ci NOT NULL,
cp char(5) character set utf8 collate utf8_general_ci NOT NULL,
id_pays char(3) character set utf8 collate utf8_general_ci NOT NULL,
PRIMARY KEY (id_client)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO clients2 (id_client, nom, cp, id_pays) VALUES
(1, 'Tintin', '75001', '033'),
(2, 'Casta', '75001', '033'),
(3, 'Gassman', '75001', '039');
La requête imbriquée
SELECT * FROM clients2 c
WHERE (cp, id_pays) =
(SELECT cp, id_pays
FROM villes2
WHERE UPPER(nom_ville) = 'ROME');
Format 2 : la sous-requête renvoie plusieurs résultats
Syntaxe
SELECT col1, col2,
FROM table1
WHERE colonne IN
(SELECT colonne FROM table2 WHERE condition);
Exemples
Les clients de Paris (2 niveaux sur 2 tables; une jointure est possible)
SELECT nom, cp
FROM clients
WHERE cp IN
(SELECT cp FROM villes WHERE nom_ville LIKE 'Paris%');
SELECT nom, v.cp
FROM clients c , villes v
WHERE v.cp = c.cp
AND nom_ville LIKE 'Paris%';
Les clients qui habitent la même ville que les Buguet (2 niveaux sur la même table).
SELECT * FROM clients
WHERE cp IN
(SELECT cp FROM clients
WHERE UPPER(nom) = 'BUGUET');
Infos complètes sur les commandes d'Evian (3 niveaux; jointure possible).
Note : EVIAN renvoie un seul enregistrement dans la table Produits.
SELECT * FROM cdes WHERE id_cde IN
(SELECT id_cde FROM ligcdes
WHERE id_produit =
(SELECT id_produit FROM produits
WHERE UPPER(designation) = 'EVIAN'));
La requête renvoie vrai ou faux
C'est la clause EXISTS qui teste la présence ou l'absence de résultats de la requête imbriquée pour chaque enregistrement du premier SELECT. Elle renvoie True ou False.
Syntaxe
SELECT colonnes FROM table(s)
WHERE [NOT] EXISTS
(SELECT colonne(s)
FROM table(s)
[WHERE (conditions)] );
Exemples
On s'appuie sur une table nommée 'bidon' qui possède une seule colonne et un seul enregistrement.
La table BIDON
CREATE TABLE bidon (C1 INTEGER);
INSERT INTO bidon VALUES(1);
Tester l'existence d'une valeur
SELECT 'Trouvé' FROM bidon WHERE EXISTS (SELECT * FROM cdes WHERE YEAR(date_cde) = 2000);
Renverra Trouvé si une commande de cette année existe.
SELECT 'Trouvé' FROM bidon WHERE EXISTS (SELECT * FROM cdes WHERE YEAR(date_cde) = 1999 );
Ne renverra aucun résultat si aucune commande de cette année n'existe.
Tester l'inexistence d'une valeur
SELECT 'Non Trouvé' FROM bidon WHERE NOT EXISTS (SELECT * FROM cdes WHERE YEAR(date_cde) = 1999);
Renverra 'Non trouvé' si aucune commande de cette année n'existe.
EXISTS et NOT EXISTS en substitution d'une jointure externe
EXISTS
Renverra la liste des villes où il y a au moins un client.
SELECT nom_ville
FROM villes v
WHERE EXISTS(SELECT * FROM clients WHERE cp = v.cp);
C'est la même chose que ceci
SELECT DISTINCT nom_ville
FROM villes v , clients c
WHERE v.cp = c.cp;
NOT EXISTS
Renverra la liste des villes où il n'y a pas de clients.
SELECT nom_ville
FROM villes v
WHERE NOT EXISTS
(SELECT * FROM clients WHERE cp = v.cp);
C'est la même chose que ceci
SELECT DISTINCT nom_ville FROM villes v
LEFT OUTER JOIN clients c
ON v.cp = c.cp
WHERE c.cp IS NULL;
La sous requête renvoie un agrégat
Si l'agrégat est mono-valué on emploie l'opérateur = ou > ou
.
Autrement l'opérateur IN.
Exemples mono-valués
Caractéristiques du produit le plus cher.
SELECT *
FROM produits
WHERE prix =
(SELECT MAX(prix) FROM produits);
Produits dont le prix est supérieur à la moyenne des prix
SELECT designation "Désignation"
FROM produits
WHERE prix >
(SELECT AVG(prix) FROM produits);
Exemples multi-valués
Produits qui ont été commandés plus d'une fois
SELECT designation "Désignation"
FROM produits
WHERE id_produit IN
(SELECT p.id_produit
FROM produits p , ligcdes l
WHERE p.id_produit = l.id_produit
GROUP BY p.id_produit
HAVING COUNT(*) > 1
);
Les opérateurs ANY, ALL
Fonctionalités
Les opérateurs ANY et ALL sont combinés aux opérateurs =, >, >=, < et >==MAX sur la même table ANY
(SELECT prix FROM produits);SELECT * FROM produits
WHERE prix >
(SELECT MIN(prix) FROM produits);
L'année où il y a eu le plus grand nombre de commandes
Là MAX(COUNT(*)) est impossible; il faut passer par ce type de requête.
On calcule le nombre de commandes par année (requête de niveau 2).
Ensuite on sélectionne l'année où il y a le plus de commandes (requête de niveau 1).
SELECT YEAR(date_cde) "Année", COUNT(*) "Nombre de commandes"
FROM cdes
GROUP BY YEAR(date_cde)
HAVING COUNT(*) >= ALL
(SELECT COUNT(*)
FROM cdes
GROUP BY YEAR(date_cde));
La commande dont le total est le plus élévé.
On calcule le total de chaque commande (requête de niveau 2).
Ensuite on sélectionne la commande dont le total est le plus élévé (requête de niveau 1).
SELECT l.id_cde "Code commande", SUM(prix * qte) "Total de la commande"
FROM ligcdes l, produits p
WHERE l.id_produit = p.id_produit
GROUP BY l.id_cde
HAVING SUM(prix*qte) >= ALL
(SELECT SUM(prix * qte)
FROM ligcdes l, produits p
WHERE l.id_produit = p.id_produit
GROUP BY l.id_cde);
Exercices
L'année où il y a eu le plus petit nombre de commandes.
La commande dont le total est le plus bas.
Exemples avec les trois tables Vendeurs, Villes, vendeurs_villes : requêtes corrélées (la sous-requête fait appel à la requête principale dans les 3 derniers cas).
VendeursVendeurs_villes EMBED PBrush EMBED PBrush
Donc :
Lucky, Dalton et Mickey ont travaillé (1,2,3),
Lucky a toujours travaillé là où il habite (75011),
Dalton a parfois travaillé là où il habite (75012),
Mickey n'a jamais travaillé là où il habite (75012),
Donald n'a jamais travaillé !!!
Les vendeurs qui ont travaillé au moins une fois (Ils sont dans Vendeurs_villes)
SELECT * FROM vendeurs v
WHERE id_vendeur IN
(SELECT id_vendeur FROM vendeurs_villes);
EMBED PBrush
Les vendeurs qui n'ont jamais travaillé (Ils ne sont pas dans Vendeurs_villes)
SELECT * FROM vendeurs v
WHERE id_vendeur NOT IN
(SELECT id_vendeur FROM vendeurs_villes);
EMBED PBrush
Les vendeurs qui ont travaillé (au moins une fois) dans la ville où ils habitent.
EMBED PBrush
SELECT * FROM vendeurs v
WHERE cp IN
(SELECT cp FROM vendeurs_villes
WHERE id_vendeur = v.id_vendeur);
OU
SELECT * FROM vendeurs v
WHERE cp = ANY
(SELECT cp FROM vendeurs_villes
WHERE id_vendeur = v.id_vendeur);
Les vendeurs qui ont toujours travaillé dans la ville où ils habitent.
EMBED PBrush
SELECT DISTINCT v.id_vendeur, v.nom, v.cp
FROM vendeurs v, vendeurs_villes vv
WHERE v.id_vendeur =vv.id_vendeur
AND v.cp = ALL
(SELECT cp FROM vendeurs_villes
WHERE id_vendeur = v.id_vendeur);
Les vendeurs qui n'ont jamais travaillé dans la ville où ils habitent.
EMBED PBrush
SELECT DISTINCT v.id_vendeur, v.nom, v.cp
FROM vendeurs v, vendeurs_villes vv
WHERE v.id_vendeur=vv.id_vendeur
AND v.cp ALL
(SELECT cp FROM vendeurs_villes
WHERE id_vendeur = v.id_vendeur);
Mise à jour en fonction d'une sous-requête
Mettre en majuscule les noms des villes italiennes.
UPDATE villes
SET nom_ville = UPPER(nom_ville)
WHERE id_pays =
(SELECT id_pays
FROM pays
WHERE UPPER(nom_pays) = 'ITALIE');
Supprimer les villes anglaises.
DELETE FROM villes
WHERE id_pays =
(SELECT id_pays
FROM pays
WHERE UPPER(nom_pays) = 'ANGLETERRE');
Insert contrôlé
Objectif
Contrôler qu'une valeur existe dans une table avant de faire quelque chose.
Démarche
On utilise une clause WHERE NOT EXISTS sur une table 'bidon' pour contrôler l'existence d'un enregistrement de référence.
Exemple 1 : table sans clé primaire
Cette requête ajoutera 75011, Paris 11 si l'enregistrement n'existe pas et ne l'ajoutera pas s'il existe.
INSERT INTO villes(cp, nom_ville)
SELECT '75011', 'Paris 11'
FROM bidon
WHERE NOT EXISTS
(SELECT * FROM villes
WHERE cp = '75011');
Ce type de requête peut aussi servir pour mettre en place une contrainte d'intégrité référentielle quand les clés étrangères ne peuvent pas être mises en place (Tables MyISAM).
Exemple 2
Insérera l'enregistrement Clients puisque '75011' existe dans la table villes.
INSERT INTO clients(nom, prenom, cp)
SELECT 'Milou', 'Le chien', '75011'
FROM bidon
WHERE EXISTS
(SELECT * FROM villes
WHERE cp = '75011');
N'insérera pas l'enregistrement Clients puisque '75016' n'existe pas dans la table villes.
INSERT INTO clients(nom, prenom, cp)
SELECT 'Milou', 'Le chien', '75016'
FROM bidon
WHERE EXISTS
(SELECT * FROM villes
WHERE cp = '75016');
TP PARISCOPE sur les requêtes imbriquées
REQUETES IMBRIQUEESLes policiersLes acteurs-réalisateursLes acteurs seulement acteursLes films projetésLes cinémas ouvertsLes cinémas fermésL'année où le plus grand nombre de films est sorti
LES TABLEAUX CROISES DYNAMIQUES
Sur une table
Définition
Un TCD (Tableau croisé dynamique) permet de passer d'une représentation 1D à une représentation 2D.
EMBED PBrush EMBED PBrush
Exemple
La table 'ventes_croisees'
CREATE TABLE ventes_croisees (
nom varchar(50) NOT NULL default '',
designation varchar(50) NOT NULL default '',
vente int(10) unsigned NOT NULL default '0',
PRIMARY KEY (nom, designation)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO ventes_croisees (nom, designation, vente) VALUES
('Casta', 'Evian', 20),
('Casta', 'Graves', 5),
('Haddock', 'Badoit', 1),
('Haddock', 'Evian', 1),
('Haddock', 'Graves', 10),
('Tintin', 'Badoit', 5),
('Tintin', 'Evian', 10),
('Tintin', 'Graves', 10);
Le TCD
SELECT nom,
SUM(IF( designation = 'Evian' , vente, 0)) AS 'Evian',
SUM(IF( designation = 'Graves' , vente, 0)) AS 'Graves',
SUM(IF( designation = 'Badoit' , vente, 0)) AS 'Badoit'
FROM ventes_croisees
GROUP BY nom;
Note sur le IF en MySQL
Il permet de faire un test sur une valeur d'une colonne, d'un calcul,
IF(condition, vrai, faux)
SELECT * , IF(prix > 10, prix, 0) FROM produits;
EMBED PBrush
Syntaxe du TCD
SELECT colonne à afficher en ligne,
SUM(IF(colonne à afficher en colonne= 'valeur', colonne à afficher à l'intersection, 0)) AS alias,
SUM(IF(colonne à afficher en colonne = 'valeur', colonne à afficher à l'intersection, 0)) AS alias,
GROUP BY colonne à afficher en ligne
Sur une jointure statique
Avec les tables Vendeurs, Ventes et Produits
EMBED PBrush
Même syntaxe mais sur une jointure.
SELECT nom,
SUM(IF(designation = 'Evian' , vente, 0)) AS 'Evian',
SUM(IF(designation = 'Graves' , vente, 0)) AS 'Graves',
SUM(IF(designation = 'Badoit' , vente, 0)) AS 'Badoit'
FROM vendeurs , ventes, produits
WHERE vendeurs.id_vendeur = ventes.id_vendeur
AND ventes.id_produit = produits.id_produit
GROUP BY nom;
Avec une jointure externe
EMBED PBrush
SELECT nom,
SUM(IF(designation = 'Evian' , vente, 0)) AS 'Evian',
SUM(IF(designation = 'Graves' , vente, 0)) AS 'Graves',
SUM(IF(designation = 'Badoit' , vente, 0)) AS 'Badoit'
FROM (vendeurs LEFT JOIN ventes ON vendeurs.id_vendeur = ventes.id_vendeur)
LEFT JOIN produits ON ventes.id_produit = produits.id_produit
GROUP BY nom;
Sur une jointure dynamique
Il faut travailler avec un langage de programmation.
Soit avec une procédure stockée,
Soit avec un langage serveur dynamique de type PHP, ASP, JSP,
En créant d'abord la liste des désignations de la table produits,
Puis le SELECT dynamique.
LES TRANSACTIONS
Principes
Une transaction est l'espace-temps qui s'écoule entre deux états stables de la base de données.
Les transactions doivent garantir les propriétés ACID (Atomicité, Consistence, Isolation, Durabilité).
Atomicité : garantit le fait que toutes les actions élémentaires sont effectuées ou aucune.
Consistence : garantit le fait que l'on passe d'un état cohérent à un autre état cohérent.
Isolation : garantit le fait que d'autres actions ne peuvent accéder aux données pendant la transaction.
Durabilité : garantit le fait qu'une fois la transaction validée elle ne peut être défaite.
Lors des MAJ la BD est en état instable. Ce n'est qu'à la fin de toutes les MAJ d'une transaction (Ajout d'une commande avec ses lignes de commandes, opération de transfert de débit-crédit- d'un compte vers un autre) que la BD retrouve un état stable.
Par défaut mysql (et MySQL Query Browser) est lancé avec l'option AutoCommit=true.
C'est-à-dire qu'à chaque instruction de MAJ la BD est actualisée. Ce n'est pas un bon paramétrage.
Ce n'est pas modifiable dans un fichier de configuration (my.ini).
MySQL Query Browser ne permet pas de passer en autocommit=0.
Seules les tables InnoDB, BDB, Berkeley supportent les transactions.
Pour activer le support des transactions vous devez lancer la commande suivante :
SET AUTOCOMMIT = 0;
Dans ce cas les MAJ seront validées (commit) par une instruction spécifique de validation définitive ou bien elles seront invalidées (rollback).
Les tests ne peuvent être faits qu'avec le client mysql ou un script MysqlQueryBrowser.
Validation
Valide toutes les mises à jour depuis le dernier commit ou l'ouverture de la session.
Commit;
Annulation
Annule toutes les mises à jour depuis le dernier commit ou le dernier rollback ou l'ouverture de la session.
Rollback;
NB : basculez en SET AUTOCOMMIT = 0; si par défaut c'est à 1.
Il faut être dans l'utilitaire mysql pour modifier la variable Autocommit.
Pour connaître l'état de l'autocommit tapez mysql>SELECT @@AUTOCOMMIT;
La gestion des transactions peut aussi être réalisée grâce à la commande START TRANSACTION depuis MySQL 4.0.11.
(Avec l'utilitaire mysql et pas avec MYSQL QUERY BROWSER)
SET AUTOCOMMIT = 0;
START TRANSACTION;
INSERT INTO villes (cp, nom_ville) VALUES ('24300','AILLAC');
SELECT * FROM VILLES;
ROLLBACK;
SELECT * FROM villes;
Note : depuis la version 4.0.14 MySQL supporte (avec les tables InnoDB) les commandes SAVEPOINT point_de_sauvegarde; et ROLLBACK TO point_de_sauvegarde;
Les savepoints
Objectif
Diviser une transaction en plusieurs sous-parties.
Syntaxes
Création d'un point de sauvegarde
SAVEPOINT point_de_sauvegarde;
Création d'un point de sauvegarde
ROLLBACK TO SAVEPOINT point_de_sauvegarde;
Suppression d'un point de sauvegarde
RELEASE SAVEPOINT point_de_sauvegarde;
Exemple
Au final vous n'aurez que 75031.
SELECT * FROM villes;
SET AUTOCOMMIT=0;
START TRANSACTION;
SAVEPOINT sp1;
INSERT INTO villes(cp, nom_ville) VALUES('75031','Paris 31');
SAVEPOINT sp2;
INSERT INTO villes(cp, nom_ville) VALUES('75032','Paris 32');
ROLLBACK TO SAVEPOINT sp2;
COMMIT;
SELECT * FROM villes;
Le verrouillage de table
Les commandes LOCK et UNLOCK permettent de verrouiller et de déverrouiller une ou plusieurs tables en lecture ou en lecture/écriture.
Syntaxes
LOCK TABLES nom_de_table verrouillage [, nom_de_table verrouillage];
Verrouillage prend les valeurs READ ou WRITE.
Un verrouillage de type READ autorise les lectures mais pas les écritures de la part des autres utilisateurs.
Un verrouillage de type WRITE n'autorise ni les lectures ni les écritures.
UNLOCK TABLES;
Exemple
Ouvrez deux sessions clients (mysql et MySQL Query Browser par exemple).
UtilisateurAutre utilisateurSELECT * FROM villes;
SET AUTOCOMMIT=0;
START TRANSACTION;
LOCK TABLES villes READ;
UPDATE villes SET nom_ville = 'Marsiglia'
WHERE cp = '13000';
UNLOCK TABLES;
COMMIT;
SELECT * FROM villes; -- OK
UPDATE villes SET nom_ville = 'Marsilia' WHERE cp = '13000'; -- KO
UtilisateurAutre utilisateurSELECT * FROM villes;
SET AUTOCOMMIT=0;
START TRANSACTION;
LOCK TABLES villes WRITE;
UPDATE villes SET nom_ville = 'Marsiglia'
WHERE cp = '13000';
UNLOCK TABLES;
COMMIT;
SELECT * FROM villes; -- KO
UPDATE villes SET nom_ville = 'Marsilia' WHERE cp = '13000'; -- KO
Le verrouillage de ligne
La clause FOR UPDATE appliquée à un SELECT permet de verrouiller un ou plusieurs lignes en écriture.
Syntaxe
SELECT * FROM nomDeTable WHERE condition FOR UPDATE;
Exemple
Ouvrez deux sessions clients (mysql et MySQL Query Browser par exemple).
UtilisateurAutre utilisateurSET AUTOCOMMIT=0;
START TRANSACTION;
SELECT * FROM pays WHERE id_pays = '033' FOR UPDATE;
UPDATE pays SET nom_pays = 'FR' WHERE id_pays = '033';
COMMIT;
SET AUTOCOMMIT=0;
START TRANSACTION;
UPDATE pays SET nom_pays = 'fr' WHERE id_pays = '033'; -- Attente bloquante (*)
COMMIT;
(*) UPDATE sur un autre pays c'est OK.
LES VUES (VIEWS)
Création, suppression, modification
Une vue est une requête stockée.
Une vue permet de ne pas avoir à ressaisir les requêtes statiques, mais aussi de garantir l'intégrité des données et d'assurer la confidentialité. Elles correspondent aux vues des Modèles Organisationnels des données.
Elles en facilitent l'implémentation.
Les autorisations seront données sur des vues plutôt que sur des tables.
On utilise une vue comme une table; SELECT, jointures, vue à partir d'une autre vue, insertions, suppressions, modifications,
.
Création
Syntaxe
CREATE OR REPLACE VIEW nom_de_vue
AS SELECT * | colonnes FROM nom_de_table [WHERE condition]
[WITH CHECK OPTION];
Check Option permet de contrôler les MAJ à partir des vues.
Il est impossible d'insérer ou de modifier un enregistrement via la view si l'enregistrement ne correspond pas au prédicat de celle-ci. Cf plus loin.
Exemple
CREATE VIEW clients_parisiens AS SELECT * FROM clients WHERE cp LIKE '75%';
Suppression
Syntaxe
DROP VIEW nom_de_vue;
Modification
Syntaxe
ALTER VIEW nom_de_la_vue AS SELECT
;
Les vues et les mises à jour
Les views permettent, éventuellement, les mises à jour.
Pour cela il faut qu'elles soient mono-table, que toutes les colonnes NOT NULL soient présentes dans le SELECT et qu'aucun calcul n'ait été effectué dans le SELECT.
A contrario les requêtes suivantes dans la création d'une View ne seront pas susceptibles de mises à jour :
Jointures,
Requêtes calculées,
Requêtes agrégats,
Etc
Exemples
-- Les clients parisiens avec jointure Clients X Villes
-- Aucun ajout possible
CREATE OR REPLACE VIEW clients_parisiens
AS SELECT nom, prenom, c.cp, nom_ville
FROM clients c, villes v
WHERE c.cp = v.cp
AND nom_ville LIKE 'PARIS%';
SELECT * FROM clients_parisiens;
-- Les clients parisiens mono-table avec toutes les colonnes NOT NULL
-- Tous les clients peuvent être ajoutés
CREATE OR REPLACE VIEW clients_parisiens_ajout
AS SELECT nom, prenom, cp
FROM clients
WHERE cp LIKE '75%';
SELECT * FROM clients_parisiens_ajout;
-- L'enregistrement sera inséré, toutes les colonnes NOT NULL sont renseignées
INSERT
INTO clients_parisiens_ajout(nom, prenom, cp)
VALUES ('Casta', 'Laetitia','75012');
-- L'enregistrement sera inséré, toutes les colonnes NOT NULL sont renseignées
INSERT
INTO clients_parisiens_ajout(nom, prenom, cp)
VALUES ('Jolie', 'Laetitia','94100');
-- Les clients parisiens mono-table avec toutes les colonnes NOT NULL mais CHECK OPTION
-- Seuls les clients parisiens peuvent être ajoutés
CREATE OR REPLACE VIEW clients_parisiens_ajout
AS SELECT nom, prenom, cp
FROM clients
WHERE cp LIKE '75%'
WITH CHECK OPTION;
SELECT * FROM clients_parisiens_ajout c, villes v
WHERE c.cp = v.cp;
-- L'enregistrement ne sera pas inséré, le cp ne correspond pas au prédicat
INSERT INTO clients_parisiens_ls(nom, prenom, cp)
VALUES ('Bullock', 'Sandra','69000');
-- Les clients parisiens avec blocage
-- Aucun client ne peut être ajouté, il y a un calcul dans la requête
CREATE OR REPLACE VIEW clients_parisiens_ls
AS SELECT id_client + 0 "id_client", nom, prenom, cp
FROM clients
WHERE cp LIKE '75%';
-- L'enregistrement ne sera pas inséré, la View est en Lecture Seule
INSERT INTO clients_parisiens_ls(nom, prenom, cp)
VALUES ('Roberts', 'Julia','75012');
TP sur les views
Créez une vue sur les cinémas parisiens et une autre sur les cinémas de banlieue.
Les cinémas parisiens
CREATE VIEW cinemas_parisiens AS SELECT * FROM cinemas WHERE cp LIKE '75%';
Les cinémas de banlieue
CREATE VIEW cinemas_de_banlieue AS SELECT * FROM cinemas WHERE cp NOT LIKE '75%';
OPTIMISATION
Indexation
Cf le chapitre sur les Index.
Explain
La commande
La commande EXPLAIN permet de visualiser la structure d'une table (Comme la commande DESC) mais aussi de visualiser le traitement d'un ordre SELECT (Choix des tables, des index). C'est ce deuxième point que nous allons examiner ici.
Syntaxes
EXPLAIN nom_de_table;
EXPLAIN EXTENDED SELECT
\G
Utilsez l'utilitaire mysql pour les exemples :
C:\
\mysql\bin>mysql --host=localhost --user=root --password= --database=cours
Un select
mysql> EXPLAIN EXTENDED SELECT * FROM villes\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: villes
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 12
filtered: 100.00
Extra:
Explain et les index
Utilisation d'un index
mysql> EXPLAIN EXTENDED SELECT * FROM villes WHERE nom_ville LIKE 'par%'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: villes
type: range
possible_keys: i_villes_nom_ville
key: i_villes_nom_ville
key_len: 152
ref: NULL
rows: 1
filtered: 100.00
Extra: Using where
Désactivation d'un index
mysql> EXPLAIN EXTENDED SELECT * FROM villes WHERE UPPER(nom_ville) LIKE 'PAR%'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: villes
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 12
filtered: 100.00
Extra: Using where
Autre exemple :
Avec l'index
mysql> EXPLAIN EXTENDED SELECT * FROM villes USE INDEX (i_villes_nom_ville) where nom_ville = 'Sarlat'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: villes
type: ref
possible_keys: i_villes_nom_ville
key: i_villes_nom_ville
key_len: 152
ref: const
rows: 1
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
Avec la désactivation de l'index
mysql> EXPLAIN EXTENDED SELECT * FROM villes IGNORE INDEX (i_villes_nom_ville) where nom_ville = 'Lyon'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: villes
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 12
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
Explain et les jointures
mysql> EXPLAIN EXTENDED SELECT clients.nom, clients.cp, villes.nom_ville FROM clients, villes WHERE clients.cp = villes.cp\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: clients
type: ALL
possible_keys: Index_cp
key: NULL
key_len: NULL
ref: NULL
rows: 11
filtered: 100.00
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: villes
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 17
ref: cours.clients.cp
rows: 1
filtered: 100.00
Extra: Using where
Sans index dans la table communes.
mysql> EXPLAIN EXTENDED SELECT clients.nom, clients.cp, communes.nom_commune_majus FROM clients, communes WHERE clients.cp = communes.code_insee\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: communes
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 35925
filtered: 100.00
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: clients
type: ALL
possible_keys: Index_cp
key: NULL
key_len: NULL
ref: NULL
rows: 11
filtered: 81.82
Extra: Using where; Using join buffer
Après avoir indexé le code_insee
mysql> EXPLAIN EXTENDED SELECT clients.nom, clients.cp, communes.nom_commune_majus FROM clients, communes WHERE clients.cp = communes.code_insee\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: clients
type: ALL
possible_keys: Index_cp
key: NULL
key_len: NULL
ref: NULL
rows: 11
filtered: 100.00
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: communes
type: ref
possible_keys: code_insee
key: code_insee
key_len: 17
ref: cours.clients.cp
rows: 1
filtered: 100.00
Extra: Using where
Jointure 6 tables
Son ordre : cdes, clients, ligcdes, produits, villes et pays
mysql> EXPLAIN EXTENDED SELECT p.nom_pays, v.nom_ville, c.nom, pr.designation FROM pays p, villes v, clients c, cdes cd, ligcdes l, produits pr WHERE p.id_pays = v.id_pays AND c.cp = c.cp AND c.id_client = cd.id_client AND cd.id_cde = l.id_cde AND l.id_produit = pr.id_produit\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: cd
type: ALL
possible_keys: PRIMARY,FK_cdes_client
key: NULL
key_len: NULL
ref: NULL
rows: 9
filtered: 100.00
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: c
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: cours.cd.id_client
rows: 1
filtered: 100.00
Extra:
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: l
type: ref
possible_keys: PRIMARY,FK_ligcdes_id_produit
key: PRIMARY
key_len: 4
ref: cours.cd.id_cde
rows: 1
filtered: 100.00
Extra: Using index
*************************** 4. row ***************************
id: 1
select_type: SIMPLE
table: pr
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: cours.l.id_produit
rows: 1
filtered: 100.00
Extra:
*************************** 5. row ***************************
id: 1
select_type: SIMPLE
table: v
type: ALL
possible_keys: i_villes_id_pays
key: NULL
key_len: NULL
ref: NULL
rows: 12
filtered: 100.00
Extra: Using join buffer
*************************** 6. row ***************************
id: 1
select_type: SIMPLE
table: p
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 9
ref: cours.v.id_pays
rows: 1
filtered: 100.00
Extra:
La même avec STRAIGHT_JOIN
mysql> EXPLAIN EXTENDED SELECT p.nom_pays, v.nom_ville, c.nom, pr.designation FROM pays p STRAIGHT_JOIN villes v STRAIGHT_JOIN clients c STRAIGHT_JOIN cdes cd STRAIGHT_JOIN ligcdes l STRAIGHT_JOIN produits pr WHERE p.id_pays = v.id_pays AND c.cp = c.cp AND c.id_client = cd.id_client AND cd.id_cde = l.id_cde AND l.id_produit = pr.id_produit\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: p
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 3
filtered: 100.00
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: v
type: ALL
possible_keys: i_villes_id_pays
key: NULL
key_len: NULL
ref: NULL
rows: 12
filtered: 75.00
Extra: Using where; Using join buffer
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: l
type: index
possible_keys: PRIMARY,FK_ligcdes_id_produit
key: PRIMARY
key_len: 8
ref: NULL
rows: 15
filtered: 100.00
Extra: Using index; Using join buffer
*************************** 4. row ***************************
id: 1
select_type: SIMPLE
table: c
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 11
filtered: 100.00
Extra: Using join buffer
*************************** 5. row ***************************
id: 1
select_type: SIMPLE
table: cd
type: eq_ref
possible_keys: PRIMARY,FK_cdes_client
key: PRIMARY
key_len: 4
ref: cours.l.id_cde
rows: 1
filtered: 100.00
Extra: Using where
*************************** 6. row ***************************
id: 1
select_type: SIMPLE
table: pr
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: cours.l.id_produit
rows: 1
filtered: 100.00
Extra:
6 rows in set, 1 warning (0.00 sec)
TableLignes avec JOINLignes avec STRAIGHT_JOINPays13Villes1212Clients115Cdes911Ligcdes11Produits11Total2543
Ordre Join : cdes, clients, ligcdes, produits, villes et pays
Explain et les requêtes imbriquées
mysql> EXPLAIN EXTENDED SELECT * FROM clients WHERE cp IN(SELECT cp FROM villes)\G
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: clients
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 11
filtered: 100.00
Extra: Using where
*************************** 2. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: villes
type: unique_subquery
possible_keys: PRIMARY
key: PRIMARY
key_len: 17
ref: func
rows: 1
filtered: 100.00
Extra: Using index; Using where
2 rows in set, 1 warning (0.05 sec)
ANALYZE TABLE
La commande ANALYZE TABLE met à jour les statistiques de cardinalité des tables, qui affectent les choix de l'optimiseur.
Syntaxe
ANALYZE TABLE nom_de_table[,nom_de_table...];
DIVERS
Les événements (> 5.1)
Objectif
Créer un événement pour effectuer une action, une commande SQL.
L'événement peut gérer une action récurrente (un archivage tous les mois) ou unique (une suppression de données dans 1 heure).
Syntaxes
CREATE EVENT nom_d_evement
ON SCHEDULE horaire
DO commandeSQL;
Horaire peut être défini de deux façons : absolu ou relatif.
ON SCHEDULE AT heure [+ INTERVAL intervalle]
ON SCHEDULE intervalle
ALTER EVENT nom_d_evenement
;
DROP EVENT [IF EXISTS] nom_d_evenement;
Exemples
CREATE EVENT dans_2_minutes
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 MINUTE
DO DELETE FROM villes_bis;
CREATE EVENT tous_les_mois
ON SCHEDULE EVERY 1 MONTH
DO DELETE FROM villes_bis;
Quelques éléments meta-basiques
La commande SHOW
Objectif
Permet de récupérer les caractéristiques d'un objet.
Syntaxe
SHOW objet [FROM objet_parent [ LIKE '%
']];
Exemples
-- Liste des bases
SHOW DATABASES;
-- Liste des tables d'une base
SHOW TABLES FROM cours;
SHOW TABLES FROM cours LIKE 'V%';
-- Liste des colonnes d'une table
SHOW FIELDS FROM villes;
SHOW COLUMNS FROM villes;
-- Liste des clés d'une table
SHOW KEYS FROM villes;
-- Liste des index d'une table
SHOW INDEX FROM villes;
-- Instruction de création d'une table
SHOW CREATE TABLE villes;
LE MODELE RELATIONNEL DE CODD
Les domaines, les relations et les attributs.
Domaine
Un domaine est un ensemble de valeurs typées
Les types de base sont les suivants :
Numérique : entier ou réel (Int, Float, etc.).
Chaîne de caractères (Char, VarChar, etc.).
Date (DATE, TIME, YEAR, etc.).
Type énuméré.
Binaire.
Exemple
Les CP des clients.
Les noms des clients.
Les codes des produits.
Attribut
Un attribut est une information atomique
Le nom du client.
Le nom d'une ville.
Relation
Une relation (dans le modèle de Codd) est représentée de deux façons :
Un Schéma : La structure de la relation. Le schéma est fixé.
Une Extension : Le contenu, qui est un ensemble de n-uplets dont l'ordre n'a pas d'importance.
Exemple
Schéma : Villes(cp, nom_ville)
Extension :
75011Paris 1175012Paris 1275020Paris 20
BD R
Une Base de données Relationnelle est un ensemble de relations représentant un système d'informations. Les relations sont reliées entre elles et forment un tout.
Les dépendances fonctionnelles élémentaires, clés candidates, clé primaire.
Les dépendances fonctionnelles (DF)
Il y a dépendance fonctionnelle entre deux propriétés lorsque la connaissance d'une valeur d'une propriété permet de déterminer une et une seule valeur d'une autre propriété.
Une dépendance fonctionnelle est notée P1 --> P2
Exemple :id_client ---> nom
En revanche nom ne détermine pas l'id client.
Clés candidates
Lorsque plusieurs attributs déterminent le même sous ensemble d'attributs, ces attributs sont clés (primaires) candidates.
Admettons que l'on ait les attributs suivants :
Id_salarie, numero_insee, nom_salarie, prenom_salarie,
.
Id_salarie et numero_insee déterminent nom_salarie et prenom_salarie. Ils sont clés candidates.
Clé primaire
Une clé primaire permet d'identifier tous les tuples d'une relation.
Exemple
Clients(#id_client, nom, cp)
Villes(#cp, nom_ville)
La clé primaire est diésée, en gras et soulignée.
Clé étrangère
Une clé étrangère est un attribut clé primaire dans une autre table.
Elle représente une contrainte d'intégrité référentielle.
La clé étrangère est diésée et en gras.
Exemple
Villes(#cp, nom_ville)
Clients(#id_client, nom, #cp)
La valeur NULL, l'intégrité d'entité, l'intégrité référentielle.
La valeur NULL
Les attributs peuvent dans certains cas ne pas être renseignés.
On leur affecte la valeur NULL qui est différente de 0 ou de chaîne vide.
L'intégrité d'entité
Chaque clé primaire doit être unique et non nulle (NOT NULL).
L'intégrité référentielle
Une contrainte d'intégrité référentielle signifie qu'un tuple d'une relation dépend d'un autre tuple dans une autre rélation.
Exemple : la ville d'un client doit exister dans la relation villes.
La normalisation des données
La normalisation a pour objectif d'éliminer les redondances dans la base ainsi que les anomalies de mise à jour.
Première forme normale (1ère FN)
Toutes les propriétés sont élémentaires et il existe un identifiant.
Sinon on décompose une propriété en plusieurs propriétés et/ou on crée une propriété identifiante.
Exemple de 1ère FN
Cet individu n'est pas en 1ère FN. L'adresse n'est pas atomique.
Cet individu est en 1ère FN
Deuxième forme normale (2ème FN)
Toute propriété dépend de l'identifiant par une dépendance fonctionnelle (DF) élémentaire.
Donc chaque propriété dépend de tout l'identifiant et non pas d'une partie.
Sinon on décompose en plusieurs entités.
Exemple de 2ème FN
Modélisation qui n'est pas en 2ème FN
EMBED Image Microsoft Word
Modélisation en 2ème FN
Troisième forme normale (3ème FN)
Toute propriété doit dépendre de l'identifiant par une DF directe.
Donc tous les attributs non identifiants sont indépendants entre eux.
Sinon on décompose en deux entités.
Exemple de 3 FN
Modélisation qui n'est pas en 3FN
Modélisation en 3FN
EMBED Image Microsoft Word
Note :
Pour se souvenir de l'ordre et des caractéristiques des trois premières formes normales, il suffit de se rappeler le serment que tous les témoins doivent prêter devant la justice : Je jure de dire la vérité, toute la vérité, rien d'autre que la vérité.
Ce qui donne : 1FN = La clé. 2FN = Toute la clé. 3FN = Rien que la clé.
Les opérateurs de l'algèbre relationnelle
L'algèbre relationnelle est l'ensemble des opérations effectuées avec les opérateurs de l'AR et dont les opérandes sont des relations.
Tout résultat d'une opération relationnelle est une relation.
Les opérations de l'algèbre relationnelle
- La Projection : la projection d'une relation R1 de schéma R(a1,a2,.....,ap) selon les attributs a1,..,an est une relation R' de schéma R'(a1,...,an) dont les tuples sont obtenus par élimination des attributs ai+1,...,ap et par élimination des tuples en double.
La projection est notée R' = project(R/a1,....an)
- La Restriction : la restriction d'une relation R de schéma quelconque par une qualification Q est la relation R' de même schéma contenant l'ensemble des tuples satisfaisant la condition Q.
La restriction est notée R' = restrict(R/Q)
- L'Union : L'union de deux relations de même schéma R1 et R2 est une relation R de même schéma contenant les tuples de R1 ou de R2 ou aux deux relations.
L'union est notée R = union(R1,R2)
- L'Intersection : l'intersection de deux relations R1 et R2 de même schéma est une relation R de même schéma contenant les tuples appartenant à la fois à R1 et à R2.
L'intersection est notée R = intersect (R1,R2)
- La Différence : la différence de deux relations de même schéma R1 et R2 est la relation R de même schéma contenant les tuples qui appartiennent à R1 mais n'appartiennent pas à R2.
La différence est notée R = minus(R1,R2)
- Le Produit cartésien : le produit cartésien de deux relations R1 et R2 de schémas quelconques est une relation R dont le schéma est la concaténation des attributs des relations R1 et R2 et dont les tuples sont la concaténation de chaque tuple de R1 concaténé à tous les tuples de R2.
Le produit cartésien est noté R = product (R1,R2)
- La Jointure : la jointure est un sous-produit du produit cartésien. La jointure de deux relations R1 et R2 de schémas quelconques selon une qualification multi-attributs est l'ensemble des tuples du produit cartésien satisfaisant la qualification Q.
La jointure est notée R = join(R1, R2 /Qma)
Exemples d'opérations de l'AR
EnoncéOpérationLister les désignations des produitsR' = project(produits/designation)Lister les clients du 75R' = restrict(clients / cp comme '75*')Lister les noms des clients et leur villeR' = Join(clients, villes / clients.cp = villes.cp)Lister les clients de ClamartR' = Join(clients, villes / clients.cp = villes.cp ET villes.nom_ville = 'Clamart')Lister les cp des villes et des clientsR' = union(project(villes / cp), project(villes / cp))Lister les codes des produits vendusR' = difference(project(produits / id_produit), project(ligcdes / id_produit))Lister les cp communs aux villes et aux clientsR' = intersect(project(villes / cp), project(clients / cp))
TP modèle relationnel PARISCOPE
Enoncé
Créez le modèle PARISCOPE.
SI sur la rubrique cinémas de Pariscope.
Un film est caractérisé par un titre, un titre original, une année de sortie, un genre.
Un film est d'un genre et d'un seul.
Un acteur est caractérisé par un nom.
Deux acteurs peuvent avoir le même nom.
Un acteur joue dans 1 ou plusieurs films.
Un réalisateur est caractérisé par un nom.
Deux réalisateurs peuvent avoir le même nom.
Un réalisateur a réalisé 1 ou plusieurs films.
Un artiste peut être soit acteur, soit réalisateur, soit les deux.
Un film est éventuellement projeté dans un ou plusieurs cinémas.
Un cinéma est caractérisé par un nom, une adresse, un arrondissement pour les cinémas parisiens, un cp pour les cinémas de banlieue, un réseau.
Un cinéma se trouve en un lieu et un seul.
Un arrondissement possède plusieurs cinémas, une ville aussi.
Une ville est située dans un département.
Un film est projeté dans aucun, un ou plusieurs cinémas.
Corrigé
departements(#id_departement, nom_departement)
villes(#cp , nom_ville, #id_departement)
arrondissements(#id_arrondissement, nom_arrondissement)
cinemas(#id_cinema, nom_cinema, #id_arrondissement, #cp, adresse, reseau)
genres(#id_genre, libelle_genre)
films(#id_film, titre, titre_original, annee, #id_genre)
projeter(#id_cinema, #id_film, version, semaine, annee)
acteurs(#id_acteur, nom_acteur)
realisateurs(#id_realisateur, nom_realisateur)
realiser(#id_realisateur, #id_film)
jouer(#id_acteur, #id_film)
TP algèbre relationnelle PARISCOPE
Enoncés
EnoncéCorrigéLister les titres des filmsLister les titres et les titres originaux des filmsLister les policiersLister les films de 2002Lister les titres des films et leur genreLister les films de Julia RobertsLister les films de CoppolaLister les titres des films projetés actuellementLister les titres des films NON projetés actuellementLister les noms des acteurs et des réalisateursLister les noms des acteurs qui sont seulement acteursLister les noms de ceux qui sont acteur et aussi réalisteur
Corrigés
EnoncéCorrigéLister les titres des filmsR' = project(films/titre)Lister les titres et les titres originaux des filmsR' = project(films/titre, titre_original)Lister les policiersR' = restrict(films / id_genre='PO')Lister les films de 2002R' = restrict(films / year(annee) = 2002)Lister les titres des films et leur genreR' = Join(films, genres / films.id_genre = genres.id_genre)Lister les films de Julia RobertsR' = Join (films, jouer, acteurs / films.id_film = jouer.id_film ET jouer.id_acteur = acteurs.id_acteur ET nom_acteur = 'Julia Roberts') Lister les films de CoppolaR' = Join (films, jouer, realisateurs / films.id_film = realiser.id_film ET realiser.id_realisateur = realisateurs.id_ realisateur ET nom_ realisateur = 'Coppola')Lister les titres des films projetés actuellementR' = Join (films, projeter / films.id_film = projeter.id_film)Lister les titres des films NON projetés actuellementR' = Left Join (films, projeter / films.id_film = projeter.id_film ET projeter.id EST NULL)Lister les noms des acteurs et des réalisateursR' = union(project(acteurs / nom_acteur), project(realisateurs / nom_realisateur))Lister les noms des acteurs qui sont seulement acteursR' = difference(project(acteurs / nom_acteur), project(realisateurs / nom_realisateur))Lister les noms de ceux qui sont acteur et aussi réalisteurR' = intersect(project(acteurs / nom_acteur), project(realisateurs / nom_realisateur))
ANNEXES
La BD COURS
Schéma
EMBED MSPhotoEd.3
Script de création des tables
DROP DATABASE IF EXISTS cours;
CREATE DATABASE cours;
USE cours;
SET FOREIGN_KEY_CHECKS = 0;
-- Structure de la table 'utilisateurs'
DROP TABLE IF EXISTS utilisateurs;
CREATE TABLE IF NOT EXISTS utilisateurs (
ut varchar(50) NOT NULL,
mdp varchar(50) NOT NULL,
e_mail varchar(50) NOT NULL,
qualite varchar(50) NOT NULL,
PRIMARY KEY (ut),
UNIQUE KEY e_mail (e_mail)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Structure de la table 'pays'
DROP TABLE IF EXISTS pays;
CREATE TABLE IF NOT EXISTS pays (
id_pays char(3) NOT NULL,
nom_pays varchar(50) NOT NULL,
PRIMARY KEY (id_pays)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- Structure de la table 'villes'
DROP TABLE IF EXISTS villes;
CREATE TABLE IF NOT EXISTS villes (
cp varchar(5) NOT NULL,
nom_ville varchar(50) NOT NULL,
site varchar(50) default NULL,
photo varchar(50) default NULL,
id_pays char(3) default NULL,
PRIMARY KEY (cp),
KEY Index_id_pays (id_pays)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- Structure de la table 'clients'
DROP TABLE IF EXISTS clients;
CREATE TABLE IF NOT EXISTS clients (
id_client int(5) NOT NULL auto_increment,
nom varchar(50) NOT NULL,
prenom varchar(50) NOT NULL,
adresse varchar(100) default NULL,
date_naissance date default NULL,
cp char(5) default NULL,
PRIMARY KEY (id_client),
KEY Index_cp (cp)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- Structure de la table 'cdes'
DROP TABLE IF EXISTS cdes;
CREATE TABLE IF NOT EXISTS cdes (
id_cde int(5) NOT NULL auto_increment,
date_cde date NOT NULL,
id_client int(5) NOT NULL,
PRIMARY KEY (id_cde),
KEY FK_cdes_client (id_client)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Structure de la table 'produits'
DROP TABLE IF EXISTS produits;
CREATE TABLE IF NOT EXISTS produits (
id_produit int(5) NOT NULL auto_increment,
designation varchar(50) NOT NULL,
prix double(7,2) default NULL,
qte_stockee int(5) default NULL,
photo varchar(50) default NULL,
PRIMARY KEY (id_produit)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Structure de la table 'ligcdes'
DROP TABLE IF EXISTS ligcdes;
CREATE TABLE IF NOT EXISTS ligcdes (
id_cde int(5) NOT NULL,
id_produit int(5) NOT NULL,
qte int(5) NOT NULL,
PRIMARY KEY (id_cde,id_produit),
KEY FK_ligcdes_id_produit (id_produit)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- Structure de la table 'vendeurs'
DROP TABLE IF EXISTS vendeurs;
CREATE TABLE IF NOT EXISTS vendeurs (
id_vendeur int(10) unsigned NOT NULL auto_increment,
nom varchar(45) NOT NULL,
chef int(10) unsigned NOT NULL default '0',
cp char(5) NOT NULL,
PRIMARY KEY (id_vendeur),
KEY FK_vendeurs_cp (cp)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- Structure de la table 'vendeurs_villes'
DROP TABLE IF EXISTS vendeurs_villes;
CREATE TABLE IF NOT EXISTS vendeurs_villes (
id_vendeur int(10) unsigned NOT NULL auto_increment,
cp varchar(5) NOT NULL,
Date_debut date NOT NULL default '0000-00-00',
date_fin date NOT NULL default '0000-00-00',
PRIMARY KEY (id_vendeur,cp,Date_debut),
KEY cp (cp)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- Structure de la table 'ventes'
DROP TABLE IF EXISTS ventes;
CREATE TABLE IF NOT EXISTS ventes (
id_vendeur int(10) unsigned NOT NULL default '0',
id_produit int(10) unsigned NOT NULL default '0',
vente int(10) unsigned NOT NULL default '0',
date_vente date default NULL,
PRIMARY KEY (id_vendeur,id_produit,vente)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- Structure de la table 'ventes_croisees'
DROP TABLE IF EXISTS ventes_croisees;
CREATE TABLE IF NOT EXISTS ventes_croisees (
nom_vendeur varchar(50) NOT NULL,
designation varchar(50) NOT NULL,
vente int(10) unsigned NOT NULL default '0',
PRIMARY KEY (nom_vendeur,designation)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- Contraintes pour les tables exportées
-- Contraintes pour la table cdes
ALTER TABLE cdes
ADD CONSTRAINT cdes_ibfk_1 FOREIGN KEY (id_client) REFERENCES clients (id_client) ON DELETE CASCADE ON UPDATE CASCADE;
-- Contraintes pour la table clients
ALTER TABLE clients
ADD CONSTRAINT clients_ibfk_1 FOREIGN KEY (cp) REFERENCES villes (cp) ON DELETE CASCADE ON UPDATE CASCADE;
-- Contraintes pour la table ligcdes
ALTER TABLE ligcdes
ADD CONSTRAINT ligcdes_ibfk_2 FOREIGN KEY (id_produit) REFERENCES produits (id_produit) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT ligcdes_ibfk_1 FOREIGN KEY (id_cde) REFERENCES cdes (id_cde) ON DELETE CASCADE ON UPDATE CASCADE;
-- Contraintes pour la table vendeurs
ALTER TABLE vendeurs
ADD CONSTRAINT vendeurs_ibfk_1 FOREIGN KEY (cp) REFERENCES villes (cp) ON DELETE CASCADE ON UPDATE CASCADE;
-- Contraintes pour la table vendeurs_villes
ALTER TABLE vendeurs_villes
ADD CONSTRAINT vendeurs_villes_ibfk_2 FOREIGN KEY (id_vendeur) REFERENCES vendeurs (id_vendeur) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT vendeurs_villes_ibfk_1 FOREIGN KEY (cp) REFERENCES villes (cp) ON DELETE CASCADE ON UPDATE CASCADE;
-- Contraintes pour la table ventes
ALTER TABLE ventes
ADD CONSTRAINT ventes_ibfk_1 FOREIGN KEY (id_vendeur) REFERENCES vendeurs (id_vendeur) ON DELETE CASCADE ON UPDATE CASCADE;
-- Contraintes pour la table villes
ALTER TABLE villes
ADD CONSTRAINT villes_ibfk_1 FOREIGN KEY (id_pays) REFERENCES pays (id_pays) ON DELETE CASCADE ON UPDATE CASCADE;
Script d'insertion des données
-- Contenu de la table pays
INSERT INTO pays (id_pays, nom_pays) VALUES
('033', 'France'),
('035', 'Angleterre'),
('039', 'Italie');
-- Contenu de la table villes
INSERT INTO villes (cp, nom_ville, site, photo, id_pays) VALUES
('13000', 'Marseille', 'www.ma.net', NULL, '033'),
('24200', 'Sarlat', NULL, NULL, NULL),
('24300', 'Carsac', NULL, NULL, NULL),
('24400', 'Aillac', NULL, NULL, NULL),
('59000', 'Lille', 'www.lille.fr', 'lille.jpg', '033'),
('69000', 'Lyon', 'www.lyon.fr', 'lyon.jpg', '033'),
('75011', 'Paris 11', 'www.paris.fr', 'paris.jpg', '033'),
('75012', 'Paris 12', 'www.paris.fr', 'paris.jpg', '033'),
('75019', 'Paris XIX', 'www.paris.fr', 'paris.jpg', '033'),
('78000', 'Versailles', NULL, NULL, '033'),
('94100', 'Vincennes', NULL, NULL, NULL),
('94200', 'St Mandé', NULL, NULL, NULL),
('99391', 'ROME', NULL, NULL, '039'),
('99392', 'MILAN', NULL, NULL, '039');
-- Contenu de la table clients
INSERT INTO clients (id_client, nom, prenom, adresse, date_naissance, cp) VALUES
(1, 'Buguet', 'Pascal', NULL, '1955-10-03', '75011'),
(2, 'Serra', 'MH', NULL, '1958-11-27', '75019'),
(4, 'Buguet', 'MJ', NULL, '1948-08-22', '75011'),
(5, 'Fassiola', 'Annabelle', NULL, '1985-05-10', '75011'),
(6, 'Roux', 'Françoise', NULL, '1950-10-10', '59000'),
(7, 'Tintin', 'Albert', NULL, NULL, '75011'),
(8, 'Sordi', 'Alberto', NULL, NULL, '99391'),
(9, 'Muti', 'Ornella', NULL, NULL, '99392'),
(10, 'Milou', 'Le chien', NULL, NULL, '75019'),
(11, 'Tournesol', 'Bruno', NULL, NULL, '75011'),
(17, 'Roberts', 'Julia', NULL, '1965-10-03', '75011');
-- Contenu de la table cdes
INSERT INTO cdes (id_cde, date_cde, id_client) VALUES
(1, '2005-10-03', 1),
(2, '2005-10-10', 2),
(3, '2005-11-01', 1),
(4, '2000-11-01', 1),
(5, '2000-12-10', 2),
(6, '2008-12-13', 1),
(7, '2008-12-13', 2),
(8, '2008-12-13', 5),
(9, '2008-12-13', 4);
-- Contenu de la table produits
INSERT INTO produits (id_produit, designation, prix, qte_stockee, photo) VALUES
(1, 'Evian', 1.81, 10, 'evian.jpg'),
(2, 'Badoit', 1.93, 10, 'badoit.jpg'),
(3, 'Graves', 13.20, 10, 'graves.jpg'),
(4, 'Ruinard', 110.00, 10, 'ruinard.jpg'),
(5, 'Dom Pérignon', 165.00, 10, 'dom.jpg'),
(7, 'Picpoul', 5.00, 500, NULL),
(8, 'Picmal', 5.00, 10, NULL);
-- Contenu de la table ligcdes
INSERT INTO ligcdes (id_cde, id_produit, qte) VALUES
(1, 1, 2),
(1, 2, 3),
(2, 1, 2),
(3, 1, 6),
(3, 2, 2),
(3, 3, 1),
(4, 1, 5),
(5, 4, 10),
(6, 1, 1),
(6, 2, 1),
(6, 3, 1),
(6, 4, 1),
(7, 4, 100),
(8, 1, 10),
(9, 1, 10);
-- Contenu de la table vendeurs
INSERT INTO vendeurs (id_vendeur, nom, chef, cp) VALUES
(1, 'Lucky', 0, '75011'),
(2, 'Dalton', 1, '75012'),
(3, 'Mickey', 1, '75012'),
(4, 'Donald', 2, '75011');
-- Contenu de la table vendeurs_villes
INSERT INTO vendeurs_villes (id_vendeur, cp, Date_debut, date_fin) VALUES
(1, '75011', '2006-01-01', '2006-12-31'),
(1, '75011', '2007-01-01', '2007-12-31'),
(2, '75011', '2006-01-01', '2006-12-31'),
(2, '75012', '2007-01-01', '2007-12-31'),
(3, '75011', '2007-01-01', '2007-12-31'),
(3, '75012', '2006-01-01', '2006-12-31');
-- Contenu de la table ventes
INSERT INTO ventes (id_vendeur, id_produit, vente, date_vente) VALUES
(1, 1, 20, '2007-04-16'),
(1, 2, 100, '2007-04-16'),
(2, 1, 1, '2007-04-16'),
(2, 2, 10, '2008-04-16'),
(2, 3, 5, '2008-04-16');
-- Contenu de la table ventes_croisees
INSERT INTO ventes_croisees (nom_vendeur, designation, vente) VALUES
('Casta', 'Evian', 20),
('Casta', 'Graves', 5),
('Haddock', 'Badoit', 1),
('Haddock', 'Evian', 1),
('Haddock', 'Graves', 10),
('Tintin', 'Badoit', 5),
('Tintin', 'Evian', 10),
('Tintin', 'Graves', 10);
-- Contenu de la table utilisateurs
INSERT INTO utilisateurs (ut, mdp, e_mail, qualite) VALUES
('a', 'f', 'af@free.fr', ''),
('p', 'b', 'pb@free.fr', '');
La BD PARISCOPE
Schéma
EMBED PBrush
EMBED MSPhotoEd.3
Corrigés
TP Pariscope sur les objets tables
--
-- Base de données: `pariscope`
--
CREATE DATABASE IF NOT EXISTS pariscope
DEFAULT CHARACTER SET utf8
COLLATE utf8_general_ci;
USE pariscope;
SET FOREIGN_KEY_CHECKS = 0;
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
-- --------------------------------------------------------
--
-- Structure de la table `acteurs`
--
DROP TABLE IF EXISTS `acteurs`;
CREATE TABLE IF NOT EXISTS `acteurs` (
`id_acteur` int(10) unsigned NOT NULL AUTO_INCREMENT,
`nom_acteur` varchar(50) NOT NULL,
PRIMARY KEY (`id_acteur`),
KEY `nom_acteur` (`nom_acteur`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
-- --------------------------------------------------------
--
-- Structure de la table `arrondissements`
--
DROP TABLE IF EXISTS `arrondissements`;
CREATE TABLE IF NOT EXISTS `arrondissements` (
`id_arrondissement` varchar(5) NOT NULL,
`nom_arrondissement` varchar(50) NOT NULL,
PRIMARY KEY (`id_arrondissement`),
UNIQUE KEY `nom_arrondissement` (`nom_arrondissement`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Structure de la table `cinemas`
--
DROP TABLE IF EXISTS `cinemas`;
CREATE TABLE IF NOT EXISTS `cinemas` (
`id_cinema` char(5) NOT NULL,
`nom_cinema` varchar(45) NOT NULL,
`id_arrondissement` varchar(5) DEFAULT NULL,
`cp` char(5) NOT NULL,
`adresse` varchar(100) DEFAULT NULL,
`reseau` varchar(45) NOT NULL,
`acces_handicapes` int(10) unsigned NOT NULL,
PRIMARY KEY (`id_cinema`),
KEY `index_nom_cinema` (`nom_cinema`),
KEY `index_cp` (`cp`),
KEY `index_id_arrondissement` (`id_arrondissement`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Structure de la table `departements`
--
DROP TABLE IF EXISTS `departements`;
CREATE TABLE IF NOT EXISTS `departements` (
`id_departement` int(10) unsigned NOT NULL,
`nom_departement` varchar(50) NOT NULL,
PRIMARY KEY (`id_departement`),
UNIQUE KEY `nom_departement` (`nom_departement`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Structure de la table `films`
--
DROP TABLE IF EXISTS `films`;
CREATE TABLE IF NOT EXISTS `films` (
`id_film` int(10) unsigned NOT NULL AUTO_INCREMENT,
`titre` varchar(50) NOT NULL,
`titre_original` varchar(50) NOT NULL,
`annee` char(4) NOT NULL,
`id_genre` char(2) NOT NULL,
PRIMARY KEY (`id_film`),
KEY `titre` (`titre`,`id_genre`),
KEY `id_genre` (`id_genre`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
-- --------------------------------------------------------
--
-- Structure de la table `genres`
--
DROP TABLE IF EXISTS `genres`;
CREATE TABLE IF NOT EXISTS `genres` (
`id_genre` char(2) NOT NULL,
`libelle_genre` varchar(50) NOT NULL,
PRIMARY KEY (`id_genre`),
KEY `libelle_genre` (`libelle_genre`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Structure de la table `jouer`
--
DROP TABLE IF EXISTS `jouer`;
CREATE TABLE IF NOT EXISTS `jouer` (
`id_film` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id_acteur` int(10) unsigned NOT NULL,
`voix` char(1) DEFAULT NULL,
`rang` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id_film`,`id_acteur`) USING BTREE,
KEY `FK_jouer_id_acteur` (`id_acteur`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
-- --------------------------------------------------------
--
-- Structure de la table `projeter`
--
DROP TABLE IF EXISTS `projeter`;
CREATE TABLE IF NOT EXISTS `projeter` (
`id_film` int(10) unsigned NOT NULL,
`id_cinema` char(5) NOT NULL,
`version` varchar(45) NOT NULL,
`semaine` int(10) unsigned NOT NULL,
`annee` char(4) NOT NULL,
PRIMARY KEY (`id_film`,`id_cinema`,`version`) USING BTREE,
KEY `FK_projeter_id_cinema` (`id_cinema`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Structure de la table `realisateurs`
--
DROP TABLE IF EXISTS `realisateurs`;
CREATE TABLE IF NOT EXISTS `realisateurs` (
`id_realisateur` int(10) unsigned NOT NULL AUTO_INCREMENT,
`nom_realisateur` varchar(50) NOT NULL,
PRIMARY KEY (`id_realisateur`),
KEY `nom_realisateur` (`nom_realisateur`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
-- --------------------------------------------------------
--
-- Structure de la table `realiser`
--
DROP TABLE IF EXISTS `realiser`;
CREATE TABLE IF NOT EXISTS `realiser` (
`id_film` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id_realisateur` int(10) unsigned NOT NULL,
PRIMARY KEY (`id_film`,`id_realisateur`) USING BTREE,
KEY `id_realisateur` (`id_realisateur`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
-- --------------------------------------------------------
--
-- Structure de la table `villes`
--
DROP TABLE IF EXISTS `villes`;
CREATE TABLE IF NOT EXISTS `villes` (
`cp` char(5) NOT NULL,
`nom_ville` varchar(45) NOT NULL,
`id_departement` int(10) unsigned NOT NULL,
PRIMARY KEY (`cp`) USING BTREE,
KEY `index_nom_ville` (`nom_ville`),
KEY `FK_villes_id_departement` (`id_departement`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Contraintes pour les tables exportées
--
--
-- Contraintes pour la table `cinemas`
--
ALTER TABLE `cinemas`
ADD CONSTRAINT `cinemas_ibfk_1` FOREIGN KEY (`cp`) REFERENCES `villes` (`cp`),
ADD CONSTRAINT `cinemas_ibfk_2` FOREIGN KEY (`id_arrondissement`) REFERENCES `arrondissements` (`id_arrondissement`);
--
-- Contraintes pour la table `films`
--
ALTER TABLE `films`
ADD CONSTRAINT `films_ibfk_1` FOREIGN KEY (`id_genre`) REFERENCES `genres` (`id_genre`);
--
-- Contraintes pour la table `jouer`
--
ALTER TABLE `jouer`
ADD CONSTRAINT `FK_jouer_id_acteur` FOREIGN KEY (`id_acteur`) REFERENCES `acteurs` (`id_acteur`),
ADD CONSTRAINT `FK_jouer_id_film` FOREIGN KEY (`id_film`) REFERENCES `films` (`id_film`);
--
-- Contraintes pour la table `projeter`
--
ALTER TABLE `projeter`
ADD CONSTRAINT `FK_projeter_id_cinema` FOREIGN KEY (`id_cinema`) REFERENCES `cinemas` (`id_cinema`),
ADD CONSTRAINT `FK_projeter_id_film` FOREIGN KEY (`id_film`) REFERENCES `films` (`id_film`);
--
-- Contraintes pour la table `realiser`
--
ALTER TABLE `realiser`
ADD CONSTRAINT `FK_realiser_id_film` FOREIGN KEY (`id_film`) REFERENCES `films` (`id_film`),
ADD CONSTRAINT `realiser_ibfk_1` FOREIGN KEY (`id_realisateur`) REFERENCES `realisateurs` (`id_realisateur`);
--
-- Contraintes pour la table `villes`
--
ALTER TABLE `villes`
ADD CONSTRAINT `FK_villes_id_departement` FOREIGN KEY (`id_departement`) REFERENCES `departements` (`id_departement`);
TP Pariscope sur les clés étrangères
ALTER TABLE pariscope.villes
ADD CONSTRAINT FK_villes_departements
FOREIGN KEY FK_villes_departements (id_departement)
REFERENCES departements (id_departement)
ON DELETE CASCADE
ON UPDATE CASCADE;
ALTER TABLE pariscope.cinemas
ADD CONSTRAINT FK_cinemas_villes
FOREIGN KEY FK_cinemas_villes (cp)
REFERENCES villes (cp)
ON DELETE CASCADE
ON UPDATE CASCADE;
ALTER TABLE pariscope.cinemas
ADD CONSTRAINT FK_cinemas_arrondissements
FOREIGN KEY FK_cinemas_arrondissements (id_arrondissement)
REFERENCES arrondissements (id_arrondissement)
ON DELETE CASCADE
ON UPDATE CASCADE;
ALTER TABLE pariscope.films
ADD CONSTRAINT FK_films_genres
FOREIGN KEY FK_films_genres (id_genre)
REFERENCES genres (id_genre)
ON DELETE CASCADE
ON UPDATE CASCADE;
ALTER TABLE pariscope.projeter
ADD CONSTRAINT FK_projeter_cinemas
FOREIGN KEY FK_projeter_cinemas (id_cinema)
REFERENCES cinemas (id_cinema)
ON DELETE CASCADE
ON UPDATE CASCADE;
ALTER TABLE pariscope.projeter
ADD CONSTRAINT FK_projeter_films
FOREIGN KEY FK_projeter_films (id_film)
REFERENCES films (id_film)
ON DELETE CASCADE
ON UPDATE CASCADE;
ALTER TABLE pariscope.jouer
ADD CONSTRAINT FK_jouer_acteurs
FOREIGN KEY FK_jouer_acteurs (id_acteur, id_film)
REFERENCES jouer (id_acteur, id_film)
ON DELETE CASCADE
ON UPDATE CASCADE;
ALTER TABLE pariscope.jouer
ADD CONSTRAINT FK_jouer_films
FOREIGN KEY FK_jouer_films (id_film)
REFERENCES films (id_film)
ON DELETE CASCADE
ON UPDATE CASCADE;
ALTER TABLE pariscope.realiser
ADD CONSTRAINT FK_realiser_realisateurs
FOREIGN KEY FK_realiser_realisateurs (id_realisateur)
REFERENCES realisateurs (id_realisateur)
ON DELETE CASCADE
ON UPDATE CASCADE;
ALTER TABLE pariscope.realiser
ADD CONSTRAINT FK_realiser_films
FOREIGN KEY FK_realiser_films (id_film)
REFERENCES films (id_film)
ON DELETE CASCADE
ON UPDATE CASCADE;
TP Pariscope sur les index
Index sur le titre du film
ALTER TABLE films ADD INDEX (titre);
Ou
CREATE INDEX i_films_titre ON films(titre);
Index sur le nom de l'acteur
CREATE INDEX i_acteurs_nom_acteur ON acteurs(nom_acteur);
Index unique sur le genre
CREATE UNIQUE INDEX i_genres_libelle_genre ON films(libelle_genre);
TP Pariscope sur les modifications de table
Ajouter une colonne à la table cinemas : acces_handicapes.
ALTER TABLE cinemas ADD acces_handicapes BOOL NOT NULL;
Modifier le type de l'année du film (INT(4) vers CHAR(4)) et rétablissez ensuite.
ALTER TABLE films CHANGE annee annee CHAR( 4 );
ALTER TABLE films CHANGE annee annee INT( 4 );
Passez la colonne annee du film de NOT NULL à NULL.
ALTER TABLE films CHANGE annee annee INT( 4 ) NULL;
ALTER TABLE films CHANGE annee annee INT( 4 ) NOT NULL DEFAULT 0;
Ajouter une contrainte sur l'année du film (entre 1900 et 2030).
ALTER TABLE films ADD CONSTRAINT films_annee_plage CHECK annee BETWEEN 1900 AND 2030;
Remarque : syntaxe acceptée mais sans aucun effet de contrainte avec MySQL !!! MySQL ne le supporte pas encore (Cf la Documentation officielle).
SQL Insertion des données dans Pariscope
USE pariscope;
-- Contenu de la table departements
INSERT INTO departements (id_departement, nom_departement) VALUES ('75', 'Paris'),
('77', 'Seine et Marne'),
('91', 'Essone'),
('92', 'Hauts-de-Seine'),
('93', 'Seine Saint Denis'),
('94', 'Val de Marne'),
('95', 'Val d''Oise');
-- Contenu de la table villes
INSERT INTO villes (cp, nom_ville, id_departement) VALUES ('75001', 'Paris 1', '75'),
('75011', 'Paris 11', '75'),
('75012', 'Paris 12', '75'),
('94100', 'St Mandé', '94'),
('94200', 'Vincennes', '94');
-- Contenu de la table arrondissements
INSERT INTO arrondissements (id_arrondissement, nom_arrondissement) VALUES ('0', 'Banlieue'),
('1', 'Châtelet Les Halles'),
('11', 'Bastille'),
('12', 'Nation'),
('19', 'Buttes Chaumont'),
('2', 'Opéra');
-- Contenu de la table cinemas
INSERT INTO cinemas (id_cinema, nom_cinema, id_arrondissement, cp, adresse, reseau, acces_handicapes) VALUES ('1', 'Victoria', '1', '75001', '', '', 0),
('111', 'MK 2 Nation', '12', '75012', '', '', 0),
('112', 'Oberkampf', '11', '75011', '', '', 0),
('1244', 'Socrate', '0', '94200', '', '', 0),
('1245', 'Sorano', '0', '94200', '', '', 0);
-- Contenu de la table acteurs
INSERT INTO acteurs (id_acteur, nom_acteur) VALUES (1, 'Robert De Niro'),
(2, 'Julia Roberts'),
(3, 'Hugh Grant'),
(4, 'Al Pacino'),
(5, 'Marlone Brando'),
(6, 'Woody Allen');
-- Contenu de la table realisateurs
INSERT INTO realisateurs (id_realisateur, nom_realisateur) VALUES (1, 'Coppola'),
(2, 'Woody Allen'),
(3, 'Martin Scorsese');
-- Contenu de la table genres
INSERT INTO genres (id_genre, libelle_genre) VALUES ('CD', 'Comédie Dramatique'),
('CM', 'Comédie Musicale'),
('CO', 'Comédie'),
('DR', 'Drame'),
('HI', 'Historique'),
('PO', 'Policier'),
('TH', 'Thriller');
-- Contenu de la table films
INSERT INTO films (id_film, titre, titre_original, annee, id_genre) VALUES (1, 'COUP DE FOUDRE A N', '', 2000, 'CM'),
(2, 'Tout le monde dit I Love You', 'Everyone says I love you', 2002, 'CO'),
(3, 'Guerre et paix', '', 1990, 'CO'),
(4, 'Le parrain', '', 1990, 'PO'),
(5, 'Le parrain 2', '', 2001, 'PO'),
(6, 'Taxi Driver', '', 2000, 'TH');
-- Contenu de la table jouer
INSERT INTO jouer (id_acteur, id_film) VALUES (2, 1),
(3, 1),
(2, 2),
(4, 4),
(5, 4),
(4, 5),
(1, 6);
-- Contenu de la table realiser
INSERT INTO realiser (id_realisateur, id_film) VALUES (2, 2),
(2, 3),
(1, 4),
(1, 5),
(3, 6);
-- Contenu de la table projeter
INSERT INTO projeter (id_cinema, id_film, version, semaine, annee) VALUES ('1', 1, 'VO', 0, 0),
('111', 1, 'VF', 0, 0),
('111', 4, '', 0, 0),
('112', 5, '', 0, 0),
('1245', 6, '', 0, 0);
Corrigés MAJ PARISCOPE
EnoncéCorrigéAjoutez le genre "Divers"INSERT INTO genres (id_genre , libelle_genre) VALUES (
'DI', 'Divers'
);Insérez un film de ce nouveau genreINSERT INTO films(titre,titre_original, annee,id_genre)
VALUES('Joueuse d échecs','','2009','DI');Passez ce film dans les policiersUPDATE films SET id_genre = 'PO' WHERE id_genre = 'DI';Supprimez le genre "divers"DELETE FROM genres WHERE id_genre 'DI';Archivez les films d'avant 2000
Créez la table films_archCREATE TABLE films_arch AS SELECT * FROM films WHERE annee < 2000;
Mettez les titres des films en majusculesUPDATE films SET titre = UPPER(titre);
TP Extraction des données
Corrigés
EnoncéCorrigéREQUETES SIMPLESListez les filmsSELECT * FROM films;Listez les titres et genres des filmsSELECT titre, id_genre FROM films;Listez les titres triésSELECT titre FROM films ORDER BY titre;Listez les policiersSELECT titre FROM films WHERE id_genre = 'PO';Listez les films dont le titre contient "parrain"SELECT * FROM films WHERE titre LIKE '%parrain%';Listez les départements qui contiennent "seine"SELECT * FROM departements WHERE nom_departement LIKE '%seine%';Listez les films sortis entre 2000 et 2002SELECT * FROM films WHERE annee BETWEEN 2000 AND 2002;Listez les films sortis depuis 2000SELECT * FROM films WHERE annee >= 2000;Listez les films ayant un titre originalSELECT * FROM films WHERE titre_original IS NOT NULL;Listez les films n'ayant pas de titre originalSELECT * FROM films WHERE titre_original IS NULL;Listez les films policiers et thrillerSELECT * FROM films WHERE id_genre IN('PO','TH');AGREGATSAffichez le nombre de filmsSELECT COUNT(*) FROM films; Affichez le nombre de projectionsSELECT COUNT(*) FROM projeter;Affichez le nombre de films sortis par annéeSELECT annee, COUNT(*) FROM films GROUP BY annee;Affichez le nombre de films sortis en 2000SELECT COUNT(*) FROM films WHERE annee = 2000 GROUP BY annee;Affichez le nombre de films sortis en 2000SELECT COUNT(*) FROM films GROUP BY annee HAVING annee = 2000;JOINTURESListez les films et leur genre (libelle)SELECT films.titre, genres.libelle_genre
FROM films INNER JOIN genres ON films.id_genre = genres.id_genre;Listez les films de Julia RobertsSELECT films.titre, acteurs.nom_acteur
FROM (films INNER JOIN jouer ON films.id_film = jouer.id_film) INNER JOIN acteurs ON jouer.id_acteur = acteurs.id_acteur
WHERE (((acteurs.nom_acteur)="julia roberts"));Listez les films de CoppolaSELECT films.titre, realisateurs.nom_realisateur
FROM (films INNER JOIN realiser ON films.id_film = realiser.id_film) INNER JOIN realisateurs ON realiser.id_realisateur = realisateurs.id_realisateur
WHERE (((realisateurs.nom_realisateur)="coppola"));Listez les films projetés actuellementSELECT DISTINCT films.titre
FROM films INNER JOIN projeter ON films.id_film = projeter.id_film;Listez les films de Julia Roberts projetés actuellementSELECT films.titre, acteurs.nom_acteur
FROM ((films INNER JOIN projeter ON films.id_film = projeter.id_film) INNER JOIN jouer ON films.id_film = jouer.id_film) INNER JOIN acteurs ON jouer.id_acteur = acteurs.id_acteur
WHERE (((acteurs.nom_acteur)="julia roberts"));Listez les films de Coppola projetés actuellementSELECT films.titre, realisateurs.nom_realisateur
FROM ((films INNER JOIN realiser ON films.id_film = realiser.id_film) INNER JOIN realisateurs ON realiser.id_realisateur = realisateurs.id_realisateur) INNER JOIN projeter ON films.id_film = projeter.id_film
WHERE (((realisateurs.nom_realisateur)="coppola"));JOINTURES ET AGREGATSAffichez le nombre de films de CoppolaSELECT DISTINCT COUNT(films.titre) AS CompteDetitre, realisateurs.nom_realisateur
FROM films INNER JOIN (realisateurs INNER JOIN realiser ON realisateurs.id_realisateur = realiser.id_realisateur) ON films.id_film = realiser.id_film
GROUP BY realisateurs.nom_realisateur
HAVING (((realisateurs.nom_realisateur)="coppola"));Affichez le nombre de films projetés actuellementSELECT DISTINCT COUNT(films.titre) AS CompteDetitre
FROM films INNER JOIN projeter ON films.id_film = projeter.id_film;Affichez le nombre de films projetés actuellement avec Julia RobertsSELECT DISTINCT COUNT(films.titre) AS CompteDetitre, acteurs.nom_acteur
FROM ((films INNER JOIN projeter ON films.id_film = projeter.id_film) INNER JOIN jouer ON films.id_film = jouer.id_film) INNER JOIN acteurs ON jouer.id_acteur = acteurs.id_acteur
GROUP BY acteurs.nom_acteur
HAVING (((acteurs.nom_acteur)="julia roberts"));Affichez le nombre d'acteurs par filmSELECT DISTINCT films.titre, COUNT(jouer.id_acteur) AS CompteDeid_acteur
FROM films INNER JOIN jouer ON films.id_film = jouer.id_film
GROUP BY films.titre;Affichez la liste des cinémas ouvertsSELECT DISTINCT cinemas.nom_cinema
FROM cinemas INNER JOIN projeter ON cinemas.id_cinema = projeter.id_cinema;Affichez la liste des cinémas fermésSELECT DISTINCT cinemas.nom_cinema, projeter.id_film
FROM cinemas LEFT JOIN projeter ON cinemas.id_cinema = projeter.id_cinema
WHERE (((projeter.id_film) Is Null));REQUETES ENSEMBLISTESLa liste des acteurs et des réalisateursSELECT nom_acteur FROM acteurs
UNION
SELECT nom_realisateur FROM realisateurs;IntersectSELECT nom_acteur FROM acteurs
INTERSECT
SELECT nom_realisateur FROM realisateurs;DifférenceSELECT nom_acteur FROM acteurs
EXCEPT
SELECT nom_realisateur FROM realisateurs;REQUETES IMBRIQUEESLes policiersSELECT * FROM films WHERE id_genre = (SELECT id_genre FROM genres WHERE libelle_genre = 'Policier');Les acteurs-réalisateursSELECT * FROM acteurs WHERE nom_acteur IN (SELECT nom_realisateur FROM realisateurs);Les acteurs seulement acteursSELECT * FROM acteurs WHERE nom_acteur NOT IN (SELECT nom_realisateur FROM realisateurs);Les films projetésSELECT * FROM FILMS WHERE id_film IN (SELECT id_film FROM projeter);Les cinémas ouvertsSELECT * FROM cinemas WHERE id_cinema IN (SELECT id_cinema FROM projeter);Les cinémas fermésSELECT * FROM cinemas WHERE id_cinema NOT IN (SELECT id_cinema FROM projeter);L'année où le plus grand nombre de films est sortiSELECT annee, count(*) FROM films GROUP BY annee HAVING COUNT(*) >= ALL
(SELECT COUNT(*) FROM films GROUP BY annee);
La BD Ingénieurs
Le schéma
La création du schéma et l'insertion des données
Cf les scripts :
bd_ingenieurs_innodb.sql,
bd_ingenieurs_myisam.sql,
bd_ingenieurs_inserts.sql.
La BD Ingénieurs Light
Schéma
EMBED MSPhotoEd.3
EMBED MSPhotoEd.3
Script de création et d'insertions dans BD_INGENIEURS_LIGHT
-- Base de données: bd_ingenieurs_light
DROP DATABASE IF EXISTS bd_ingenieurs_light;
CREATE DATABASE bd_ingenieurs_light DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE bd_ingenieurs_light;
-- --------------------------------------------------------
-- Structure de la table competences
DROP TABLE IF EXISTS competences;
CREATE TABLE IF NOT EXISTS competences (
id_competence int(10) unsigned NOT NULL auto_increment,
libelle varchar(45) NOT NULL default '',
PRIMARY KEY (id_competence)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Contenu de la table competences
INSERT INTO competences (id_competence, libelle) VALUES
(1, 'ASP'),
(2, 'JSP'),
(3, 'PHP');
-- --------------------------------------------------------
-- Structure de la table ingenieurs
DROP TABLE IF EXISTS ingenieurs;
CREATE TABLE IF NOT EXISTS ingenieurs (
id_ingenieur int(10) unsigned NOT NULL auto_increment,
nom varchar(45) NOT NULL default '',
PRIMARY KEY (id_ingenieur)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Contenu de la table ingenieurs
INSERT INTO ingenieurs (id_ingenieur, nom) VALUES
(1, 'CASTA'),
(2, 'DUPOND'),
(3, 'TINTIN');
-- --------------------------------------------------------
-- Structure de la table ingenieurs_competences
DROP TABLE IF EXISTS ingenieurs_competences;
CREATE TABLE IF NOT EXISTS ingenieurs_competences (
id_ingenieur int(10) unsigned NOT NULL ,
id_competence int(10) unsigned NOT NULL default '0',
PRIMARY KEY (id_ingenieur,id_competence)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Contenu de la table ingenieurs_competences
INSERT INTO ingenieurs_competences (id_ingenieur, id_competence) VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 1),
(3, 3);
-- --------------------------------------------------------
-- Structure de la table ingenieurs_projets
DROP TABLE IF EXISTS ingenieurs_projets;
CREATE TABLE IF NOT EXISTS ingenieurs_projets (
id_ingenieur int(10) unsigned NOT NULL default '0',
id_projet int(10) unsigned NOT NULL default '0',
PRIMARY KEY (id_ingenieur,id_projet)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Contenu de la table ingenieurs_projets
INSERT INTO ingenieurs_projets (id_ingenieur, id_projet) VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 3);
-- --------------------------------------------------------
-- Structure de la table projets
DROP TABLE IF EXISTS projets;
CREATE TABLE IF NOT EXISTS projets (
id_projet int(10) unsigned NOT NULL auto_increment,
libelle varchar(45) character set utf8 NOT NULL default '',
date_debut date NOT NULL default '0000-00-00',
date_fin date NOT NULL default '0000-00-00',
id_competence int(10) unsigned NOT NULL default '0',
PRIMARY KEY (id_projet)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
-- Contenu de la table projets
INSERT INTO projets (id_projet, libelle, date_debut, date_fin, id_competence)
VALUES
(1, 'Web PHP', '2008-02-10', '2008-02-20', 3),
(2, 'Web JSP', '2008-02-10', '2008-02-20', 2),
(3, 'Web ASP', '2008-02-15', '2008-03-10', 1);
Bibliographie
MySQL 5 - Guide officiel
De Paul DuBois , Stefan Hinz , Carsten Pedersen
Editions MySQL Press, juillet 2006
700 pages, 1285 g
La référenceMySQL 5
Installation, mise en uvre, administration et programmation
de Cyril THIBAUD
Editions ENI, Février 2006
468 pages
ISBN: 2-7460-3004-7.
Apprendre SQL avec MySQL
de Christian Soutou
Editions Eyrolles, Mars 2006,
398 pages, 835 g, . Format : 19 x 23
ISBN: 2-212-11915-1
Quelques corrigés
Les subalternes du Boss
SELECT v1.id_vendeur, v1.nom, v1.chef, v2.nom "Nom du chef"
FROM vendeurs v1 JOIN vendeurs v2
ON v1.chef = v2.id_vendeur
AND v2.chef = 0;
Buveurs d'évian
SELECT DISTINCT c.id_client, nom
FROM clients c, cdes cd, ligcdes l, produits p
WHERE c.id_client = cd.id_client
AND cd.id_cde = l.id_cde
AND l.id_produit = p.id_produit
AND designation = 'Evian';
MYSQL 5 - SQL
© Pascal Buguet Imprimé le DATE \@"'d 'MMMM' yyyy'" d avril yyyy Page PAGE 114
Advanded Toolbar