398 Chapitre 10. Récapitulatif SQL
En résumé, le NULL est une source de problèmes : dans la mesure du possible il faut
l’éviter au moment où on définit la table en spécifiant la contrainte NOT NULL ou en
imposant une valeur par défaut. Si la valeur par défaut n’est pas fixée à la création
de la table, on peut en donner une au moment de l’exécution de la requête avec la
fonction IFNULL() qui remplace une valeur NULL par son deuxième argument.
mysql> SELECT IFNULL(annee_naissance, ’Pas de date de naissance !?’)
-> FROM Artiste;
+ +
| IFNULL(annee_naissance, ’Pas de date de naissance !?’) |
+ +
| 1930 |
| 1930 |
| 1925 |
| Pas de date de naissance !? |
| 1910 |
+ +
10.1.7 Clauses spécifiques à MySQL
La clause LIMIT peut être placée à la fin de toute requête SQL, et indique le nombre
maximal de lignes dans le résultat.
mysql> SELECT *
-> FROM Film
-> LIMIT 3;
+ + + + +
| titre | annee | id_realisateur | genre |
+ + + + +
| Impitoyable | 1992 | 20 | Western |
| Van Gogh | 1990 | 29 | Drame |
| Kagemusha | 1980 | 68 | Drame |
+ + + + +
Si on utilise deux chiffres comme, par exemple, LIMIT 1,3, le premier indique le
numéro de la ligne à partir de laquelle la limite s’applique, les lignes étant numérotées
à partir de 0.
mysql> SELECT *
-> FROM Film
-> LIMIT 1,3;
+ + + + +
| titre | annee | id_realisateur | genre |
+ + + + +
| Van Gogh | 1990 | 29 | Drame |
| Kagemusha | 1980 | 68 | Drame |
| Les pleins pouvoirs | 1997 | 20 | Policier |
+ + + + +
10.2 Jointures 399
Au lieu d’afficher à l’écran, on peut placer le résultat d’un ordre SELECT dans un
fichier :
SELECT *
INTO OUTFILE ’./svfilm.txt’
FROM Film
Il faut disposer du privilège file pour utiliser INTO OUTFILE. On obtient alors
tous les droits d’accès du serveur mysqld.
Par défaut, le fichier est créé dans le répertoire contenant les bases de données.
On peut indiquer explicitement le chemin d’accès, à condition que le programme
client mysql ait le droit d’écriture.
Les lignes de la table sont écrites en séparant chaque valeur par une tabulation,
ce qui permet de recharger le fichier par la suite avec la commande LOAD DATA
(voir la section présentant cette commande, page 29). On peut indiquer, après le
nom du fichier, les options de séparation des lignes et des attributs, avec une syntaxe
identique à celle utilisée pour LOAD DATA : voir annexe B.
10.2 JOINTURES
La jointure est une des opérations les plus utiles (et l’une des plus courantes)
puisqu’elle permet d’exprimer des requêtes portant sur des données réparties dans
plusieurs tables. La syntaxe pour exprimer des jointures avec SQL est une extension
directe de celle étudiée précédemment dans le cas des sélections simples : on donne
la liste des tables concernées dans la clause FROM, et on exprime les critères de
rapprochement entre ces tables dans la clause WHERE.
10.2.1 Interprétation d’une jointure
Prenons l’exemple de la requête donnant le titre des films avec le nom et le prénom
de leur metteur en scène.
mysql> SELECT titre, prenom, nom
-> FROM Film, Artiste
-> WHERE id_realisateur = id;
+ + + +
| titre | prenom | nom |
+ + + +
| Impitoyable | Clint | Eastwood |
| Les pleins pouvoirs | Clint | Eastwood |
| Van Gogh | Maurice | Pialat |
| Kagemusha | Akira | Kurosawa |
+ + + +
Pour bien comprendre ce que signifie une jointure, ce qui est parfois difficile
quand on commence à utiliser SQL, on peut généraliser l’interprétation donnée
400 Chapitre 10. Récapitulatif SQL
dans le cas d’une seule table. La clause FROM, dans les deux cas, définit un « espace
de recherche» qui, quand il y a une seule table, correspond à toutes les lignes de
celle-ci. Quand il y a deux tables, cet espace de recherche est constitué de toutes les
combinaisons possibles des lignes des deux tables.
La figure 10.2 montre toutes ces combinaisons sous la forme d’une table, compre-
nant 4 × 5 = 20 lignes construites à partir des 4 lignes de Film et des cinq lignes de
Artiste. Appelons-la FilmXArtiste : elle peut être obtenue avec la requête.
SELECT titre, prenom, nom
FROM Film, Artiste
Dans cette table, beaucoup de lignes ne nous intéressent pas, comme celles qui
associent Pialat et Impitoyable,ouVan Gogh et Kurosawa. En fait on ne veut garder
que celles pour lesquelles l’attribut id_realisateur est égal à l’attribut id,soit4
lignes.
titre annee id_real. genre id nom prenom annee_naiss.
Impitoyable 1992 20 Western 20 Eastwood Clint 1930
Impitoyable 1992 20 Western 21 Hackman Gene 1930
Impitoyable 1992 20 Western 29 Pialat Maurice 1925
Impitoyable 1992 20 Western 30 Dutronc Jacques
Impitoyable 1992 20 Western 68 Kurosawa Akira 1910
Van Gogh 1990 29 Drame 20 Eastwood Clint 1930
Van Gogh 1990 29 Drame 21 Hackman Gene 1930
Van Gogh 1990 29 Drame 29 Pialat Maurice 1925
Van Gogh 1990 29 Drame 30 Dutronc Jacques
Van Gogh 1990 29 Drame 68 Kurosawa Akira 1910
Kagemusha 1980 68 Drame 20 Eastwood Clint 1930
Kagemusha 1980 68 Drame 21 Hackman Gene 1930
Kagemusha 1980 68 Drame 29 Pialat Maurice 1925
Kagemusha 1980 68 Drame 30 Dutronc Jacques
Kagemusha 1980 68 Drame 68 Kurosawa Akira 1910
Les pleins pouvoirs 1997 20 Policier 20 Eastwood Clint 1930
Les pleins pouvoirs 1997 20 Policier 21 Hackman Gene 1930
Les pleins pouvoirs 1997 20 Policier 29 Pialat Maurice 1925
Les pleins pouvoirs 1997 20 Policier 30 Dutronc Jacques
Les pleins pouvoirs 1997 20 Policier 68 Kurosawa Akira 1910
Figure 10.2 —TableFilmXArtiste, définie par la clause FROM Film, Artiste.
La jointure est simplement une sélection sur cette table FilmXArtiste, que l’on
pourrait exprimer de la manière suivante si cette table existait.
SELECT titre, prenom, nom
FROM FilmXArtiste
WHERE id_realisateur = id
10.2 Jointures 401
L’interprétation d’une jointure est donc une généralisation de l’interprétation
d’un ordre SQL portant sur une seule table. On parcourt toutes les lignes définies par
la clause FROM, et on leur applique la condition exprimée dans le WHERE. Finalement,
on ne garde que les attributs spécifiés dans la clause SELECT. C’est vrai quel que soit
le nombre de tables utilisées dans le FROM.
Une remarque importante pour finir : la jointure est une opération qui consiste
à reconstituer une association entre entités (voir chapitre 4), dans notre exemple
l’association entre un film et son metteur en scène. Comme nous avons vu que cette
association était représentée dans un schéma relationnel par le mécanisme de clés
primaires et clés étrangères, la plupart des jointures s’expriment par une égalité entre
la clé primaire d’une table et la clé étrangère correspondante dans l’autre table. C’est
le cas dans l’exemple ci-dessus, où id_realisateur est la clé étrangère, dans Film,
correspondant à la clé primaire id dans Artiste.
10.2.2 Gestion des ambiguïtés
Dans l’exemple précédent, il n’y a pas d’ambiguïté sur les noms des attributs : titre
et id_realisateur viennent de la table Film, tandis que nom, prenom et id
viennent de la table Artiste. Il peut arriver (il arrive de fait fréquemment) qu’un
même nom d’attribut soit partagé par plusieurs tables impliquées dans une jointure.
Dans ce cas, on résout l’ambiguïté en préfixant l’attribut par le nom de sa table.
Exemple : afficher, pour chaque film, les rôles du film.
mysql> SELECT Film.titre, nom_role
-> FROM Film, Role
-> WHERE Film.titre = Role.titre;
+ + +
| titre | nom_role |
+ + +
| Impitoyable | William Munny |
| Impitoyable | Little Bill Dagget |
| Van Gogh | Van Gogh |
| Les pleins pouvoirs | Le pr´esident |
+ + +
Il n’y a pas ici de problème pour nom_role qui désigne sans ambiguïté possible un
attribut de la table Role. Si, en revanche, on ne préfixe pas titre par la table dont il
provient, MySQL ne sait pas évaluer la requête.
mysql> SELECT titre, nom_role
-> FROM Film, Role
-> WHERE titre = titre;
ERROR 1052: Column: ’titre’ in field list is ambiguous
Comme il peut être fastidieux de répéter intégralement le nom d’une table, on
peut lui associer un synonyme et utiliser ce synonyme en tant que préfixe. La requête
précédente devient par exemple :
402 Chapitre 10. Récapitulatif SQL
SELECT f.titre, nom_role
FROM Film AS f, Role AS r
WHERE f.titre = r.titre
Pour obtenir le nom de l’acteur qui a joué le rôle, il faut effectuer une jointure
supplémentaire avec la table Artiste.
mysql> SELECT f.titre, prenom, nom, nom_role
-> FROM Film AS f, Role AS r, Artiste
-> WHERE f.titre = r.titre
-> AND id_acteur = id;
+ + + + +
| titre | prenom | nom | nom_role |
+ + + + +
| Impitoyable | Clint | Eastwood | William Munny |
| Impitoyable | Gene | Hackman | Little Bill Dagget |
| Van Gogh | Jacques | Dutronc | Van Gogh |
| Les pleins pouvoirs | Gene | Hackman | Le pr´esident |
+ + + + +
On a une jointure entre Film et Role, une autre entre Role et Artiste. En ajoutant
une jointure entre Artiste et Film, on obtient les metteurs en scène qui ont joué dans
leur propre film.
mysql> SELECT f.titre, prenom, nom, nom_role
-> FROM Film AS f, Role AS r, Artiste
-> WHERE f.titre = r.titre
-> AND id_acteur = id
-> AND id = id_realisateur;
+ + + + +
| titre | prenom | nom | nom_role |
+ + + + +
| Impitoyable | Clint | Eastwood | William Munny |
+ + + + +
Il n’y a pas d’ambiguïté sur les noms d’attributs, à part pour titre, donc il est
inutile en l’occurrence d’employer des synonymes. Il existe en revanche une situation
où l’utilisation des synonymes est indispensable : celle ou l’on souhaite effectuer une
jointure d’une table avec elle-même.
Considérons la requête suivante : Donner les paires d’artistes qui sont nés la même
année. Ici toutes les informations nécessaires sont dans la seule table Artiste,
mais on construit une ligne dans le résultat avec deux lignes de la table. Tout se
passe comme si on devait faire la jointure entre deux versions distinctes de la
table Artiste. On résout le problème en utilisant deux synonymes distincts (nous
omettons le mot-clé AS qui est optionnel).