Introduction
Dans ce laboratoire (lab), nous explorerons les bases du travail avec plusieurs tables dans MySQL. Comprendre comment les tables sont liées les unes aux autres et comment combiner des données issues de plusieurs tables est essentiel pour développer des applications réelles. Nous apprendrons les relations entre les tables, les différents types d'opérations de jointure (JOIN) et comment maintenir l'intégrité des données à l'aide de contraintes de clé étrangère (foreign key constraints). À la fin de ce laboratoire, vous aurez acquis une expérience pratique en matière de création de tables liées, d'interrogation de données entre les tables et de gestion des relations entre les tables.
Comprendre les relations entre les tables
Dans cette étape, nous explorerons le concept des relations entre les tables et examinerons comment nos tables sont connectées. Comprendre les relations entre les tables est essentiel pour travailler avec des bases de données relationnelles.
Tout d'abord, connectons-nous à MySQL :
sudo mysql -u root
Une fois connecté, sélectionnons notre base de données :
USE bookstore;
Examinons la structure de nos tables et leurs relations :
SHOW CREATE TABLE books;
Vous verrez une sortie qui inclut les contraintes de clé étrangère (foreign key constraints) :
| books | CREATE TABLE `books` (
`book_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`author_id` int(11) DEFAULT NULL,
`publisher_id` int(11) DEFAULT NULL,
`publication_year` int(11) DEFAULT NULL,
`price` decimal(10,2) NOT NULL,
PRIMARY KEY (`book_id`),
KEY `author_id` (`author_id`),
KEY `publisher_id` (`publisher_id`),
CONSTRAINT `books_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `authors` (`author_id`),
CONSTRAINT `books_ibfk_2` FOREIGN KEY (`publisher_id`) REFERENCES `publishers` (`publisher_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci |
Décortiquons les relations dans notre base de données :
Chaque livre a un seul auteur (relation plusieurs-à-un, many-to-one relationship)
- Le
author_iddans la tablebooksfait référence auauthor_iddans la tableauthors. Cela signifie que leauthor_iddans la tablebooksdoit exister en tant queauthor_iddans la tableauthors. - Plusieurs livres peuvent avoir le même auteur.
- Le
Chaque livre a un seul éditeur (relation plusieurs-à-un, many-to-one relationship)
- Le
publisher_iddans la tablebooksfait référence aupublisher_iddans la tablepublishers. - Plusieurs livres peuvent avoir le même éditeur.
- Le
Pour voir ces relations en action, essayons une requête simple pour voir combien de livres chaque auteur a écrit :
SELECT author_id, COUNT(*) as book_count
FROM books
GROUP BY author_id;
La sortie ressemblera à ceci :
+-----------+------------+
| author_id | book_count |
+-----------+------------+
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
+-----------+------------+
Cela nous indique que l'auteur avec author_id 1 a 2 livres, et les auteurs 2, 3 et 4 ont chacun 1 livre. Cela illustre la relation plusieurs-à-un : plusieurs enregistrements de livres peuvent pointer vers un seul enregistrement d'auteur.
Opérations de base avec INNER JOIN
Dans cette étape, nous apprendrons à utiliser le INNER JOIN, un type d'opération de jointure crucial. Un INNER JOIN ne retourne que les lignes pour lesquelles il y a une correspondance dans les deux tables jointes. Imaginez-le comme un diagramme de Venn où le INNER JOIN vous donne l'intersection des deux tables. Si un enregistrement dans une table n'a pas de correspondance dans l'autre, il est exclu du résultat.
Commençons par un simple INNER JOIN pour obtenir les titres des livres ainsi que les noms de leurs auteurs :
SELECT
books.title,
authors.first_name,
authors.last_name
FROM books
INNER JOIN authors ON books.author_id = authors.author_id;
Cette requête :
- Commence par la table
books(FROM books). - La joint à la table
authors(INNER JOIN authors). - Spécifie la condition de jointure avec
ON books.author_id = authors.author_id. C'est ainsi que la base de données sait quelles lignes debookscorrespondent à quelles lignes deauthors: elle recherche les enregistrements où les valeurs deauthor_idsont égales dans les deux tables. - Sélectionne les colonnes que nous souhaitons voir :
books.title,authors.first_nameetauthors.last_name.
Vous devriez voir une sortie comme celle-ci :
+----------------------------+------------+-----------+
| title | first_name | last_name |
+----------------------------+------------+-----------+
| The MySQL Guide | John | Smith |
| Data Design Patterns | Emma | Wilson |
| Database Fundamentals | Michael | Brown |
| SQL for Beginners | Sarah | Johnson |
| Advanced Database Concepts | John | Smith |
+----------------------------+------------+-----------+
Dans la déclaration SELECT, vous voyez que nous utilisons books.title, authors.first_name et authors.last_name. Cela indique explicitement à MySQL de quelle table chaque colonne provient. Si les noms de colonnes sont uniques dans les tables, vous pouvez omettre le préfixe de table (par exemple, utiliser simplement title). Cependant, il est recommandé de toujours spécifier le préfixe de table pour éviter toute ambiguïté, surtout lors de jointures multiples.
Nous pouvons également joindre la table publishers :
SELECT
books.title,
publishers.name as publisher_name,
books.publication_year,
books.price
FROM books
INNER JOIN publishers ON books.publisher_id = publishers.publisher_id;
Dans ce cas, publishers.name as publisher_name signifie que nous sélectionnons la colonne name de la table publishers et la renommons en publisher_name dans la sortie. Cela rend plus clair ce que représente la colonne.
+----------------------------+--------------------+------------------+-------+
| title | publisher_name | publication_year | price |
+----------------------------+--------------------+------------------+-------+
| The MySQL Guide | Tech Books Pro | 2023 | 45.99 |
| Data Design Patterns | Tech Books Pro | 2022 | 39.99 |
| Database Fundamentals | Database Press | 2021 | 29.99 |
| SQL for Beginners | Database Press | 2023 | 34.99 |
| Advanced Database Concepts | Query Publications | 2023 | 54.99 |
+----------------------------+--------------------+------------------+-------+
Opérations avec LEFT JOIN
Dans cette étape, nous explorerons les opérations de LEFT JOIN. Une LEFT JOIN (parfois appelée LEFT OUTER JOIN) retourne tous les enregistrements de la table "de gauche" (la première table mentionnée dans la clause FROM) et les enregistrements correspondants de la table "de droite". La principale différence avec le INNER JOIN est que même s'il n'y a pas de correspondance dans la table de droite, les enregistrements de la table de gauche sont toujours inclus dans le résultat, avec des valeurs NULL là où il n'y a pas de correspondance dans la table de droite.
Ajoutons un auteur qui n'a pas encore publié de livres :
INSERT INTO authors (first_name, last_name, email)
VALUES ('David', 'Clark', 'david.clark@email.com');
Maintenant, utilisons une LEFT JOIN pour voir tous les auteurs, y compris ceux qui n'ont pas publié de livres :
SELECT
authors.first_name,
authors.last_name,
COUNT(books.book_id) as book_count
FROM authors
LEFT JOIN books ON authors.author_id = books.author_id
GROUP BY authors.author_id;
Vous devriez voir une sortie comme celle-ci :
+------------+-----------+------------+
| first_name | last_name | book_count |
+------------+-----------+------------+
| John | Smith | 2 |
| Emma | Wilson | 1 |
| Michael | Brown | 1 |
| Sarah | Johnson | 1 |
| David | Clark | 0 |
+------------+-----------+------------+
Notez que David Clark apparaît dans les résultats avec un nombre de livres égal à 0, même s'il n'a pas publié de livres. Cela se produit car la LEFT JOIN inclut toutes les lignes de la table authors et pour David, il n'y a pas de livres correspondants dans la table books, donc COUNT(books.book_id) donne 0, et non NULL. Cela illustre la différence cruciale : la LEFT JOIN garantit que toutes les lignes de la table de gauche apparaîtront dans le résultat, tandis que le INNER JOIN n'inclut que les lignes correspondantes dans les deux tables. S'il y a un livre, le compte sera un entier, sinon il sera égal à 0 en raison de COUNT().
Jointures de plusieurs tables
Dans cette étape, nous apprendrons à joindre plus de deux tables ensemble. Cela est souvent nécessaire lorsque vous devez combiner des données issues de plusieurs tables liées pour avoir une vision plus globale de vos données.
Créons une requête qui combine les informations des trois tables :
SELECT
b.title,
CONCAT(a.first_name, ' ', a.last_name) as author_name,
p.name as publisher_name,
b.publication_year,
b.price
FROM books b
INNER JOIN authors a ON b.author_id = a.author_id
INNER JOIN publishers p ON b.publisher_id = p.publisher_id
ORDER BY b.title;
Analysons ce que fait cette requête :
FROM books b: Cela indique que nous commençons avec la tablebookset que nous lui donnons un aliasb. Utiliser des alias (b,a,p) est une bonne pratique qui rend la requête plus courte et plus facile à lire.INNER JOIN authors a ON b.author_id = a.author_id: Cela joint la tablebooksavec la tableauthorsen fonction de l'author_id. Les lignes ne seront retournées que s'il y a unauthor_idcorrespondant dans les deux tables.aest l'alias de la tableauthors.INNER JOIN publishers p ON b.publisher_id = p.publisher_id: Cela joint le résultat de la jointure précédente avec la tablepublishersen fonction depublisher_id. Les lignes sont retournées uniquement s'il y a une correspondance surpublisher_iddans les deux tables.pest l'alias de la tablepublishers.SELECT b.title, CONCAT(a.first_name, ' ', a.last_name) as author_name, p.name as publisher_name, b.publication_year, b.price: Nous sélectionnons le titre de la tablebooks, combinons le prénom et le nom de l'auteur dans une colonneauthor_nameen utilisantCONCAT, utilisons la colonne du nom de l'éditeur et la renommons enpublisher_name, ainsi que l'année de publication et le prix de leurs tables respectives.ORDER BY b.title: Cela trie la sortie par le titre du livre par ordre croissant.
+----------------------------+---------------+--------------------+------------------+-------+
| title | author_name | publisher_name | publication_year | price |
+----------------------------+---------------+--------------------+------------------+-------+
| Advanced Database Concepts | John Smith | Query Publications | 2023 | 54.99 |
| Data Design Patterns | Emma Wilson | Tech Books Pro | 2022 | 39.99 |
| Database Fundamentals | Michael Brown | Database Press | 2021 | 29.99 |
| SQL for Beginners | Sarah Johnson | Database Press | 2023 | 34.99 |
| The MySQL Guide | John Smith | Tech Books Pro | 2023 | 45.99 |
+----------------------------+---------------+--------------------+------------------+-------+
Cette requête montre comment vous pouvez rassembler des données de différentes tables pour obtenir une image plus complète. Chaque entrée de livre est associée aux informations sur l'auteur et l'éditeur.
Essayons un autre exemple qui montre les livres et leurs auteurs, y compris les auteurs sans livres, ainsi que les informations sur l'éditeur lorsque disponibles :
SELECT
CONCAT(a.first_name, ' ', a.last_name) as author_name,
b.title,
p.name as publisher_name
FROM authors a
LEFT JOIN books b ON a.author_id = b.author_id
LEFT JOIN publishers p ON b.publisher_id = p.publisher_id
ORDER BY author_name;
Dans cet exemple, nous utilisons une LEFT JOIN. Cela garantit que tous les auteurs sont affichés, qu'ils aient publié un livre ou non. La sortie pour un auteur sans livre affichera NULL pour le titre et le nom de l'éditeur.
+---------------+----------------------------+--------------------+
| author_name | title | publisher_name |
+---------------+----------------------------+--------------------+
| David Clark | NULL | NULL |
| Emma Wilson | Data Design Patterns | Tech Books Pro |
| John Smith | The MySQL Guide | Tech Books Pro |
| John Smith | Advanced Database Concepts | Query Publications |
| Michael Brown | Database Fundamentals | Database Press |
| Sarah Johnson | SQL for Beginners | Database Press |
+---------------+----------------------------+--------------------+
Utilisation des contraintes de clé étrangère
Dans cette étape finale, nous explorerons comment les contraintes de clé étrangère (foreign key constraints) contribuent à maintenir l'intégrité des données entre les tables liées. Les contraintes de clé étrangère garantissent que les relations entre les tables restent valides en empêchant les opérations qui créeraient des enregistrements orphelins ou des données incohérentes.
Comprenons comment fonctionnent les contraintes de clé étrangère grâce à quelques exemples :
Tout d'abord, essayons d'ajouter un livre avec un author_id invalide :
-- Cette requête échouera en raison de la contrainte de clé étrangère
INSERT INTO books (title, author_id, publisher_id, publication_year, price)
VALUES ('Failed Book', 999, 1, 2023, 29.99);
Vous verrez un message d'erreur car l'author_id 999 n'existe pas dans la table authors :
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`bookstore`.`books`, CONSTRAINT `books_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `authors` (`author_id`))
Ce message d'erreur indique que la contrainte de clé étrangère sur la colonne author_id dans la table books nous empêche d'ajouter un livre qui fait référence à un author_id qui n'existe pas dans la table authors.
De même, nous ne pouvons pas supprimer un auteur qui a publié des livres sans traiter d'abord ses livres :
-- Cette requête échouera en raison de la contrainte de clé étrangère
DELETE FROM authors WHERE author_id = 1;
Tenter de supprimer directement l'auteur avec author_id = 1 entraîne une erreur de clé étrangère car il existe des livres qui font référence à cet author_id. C'est ainsi que MySQL s'assure que vos données restent cohérentes.
Pour supprimer en toute sécurité un auteur et ses livres, nous devons soit :
- Supprimer d'abord les livres, puis l'auteur. Cela garantit que nous n'aurons pas d'enregistrements orphelins.
- Utiliser
CASCADE DELETE(que nous explorerons dans les laboratoires avancés).
Voyons comment supprimer correctement un livre et son auteur en supprimant d'abord le livre :
-- Tout d'abord, supprimez les livres de cet auteur
DELETE FROM books WHERE author_id = 1;
-- Maintenant, nous pouvons supprimer en toute sécurité l'auteur
DELETE FROM authors WHERE author_id = 1;
En supprimant d'abord le(s) livre(s), vous supprimez les références de clé étrangère, permettant ainsi de supprimer l'auteur sans violer les contraintes.
Résumé
Dans ce laboratoire, nous avons couvert les aspects essentiels de la manipulation de plusieurs tables dans MySQL :
- Comprendre les relations entre les tables et la manière dont elles sont implémentées à l'aide de clés primaires (primary keys) et de clés étrangères (foreign keys).
- Utiliser le
INNER JOINpour combiner les enregistrements correspondants de plusieurs tables, en montrant comment sélectionner les colonnes pertinentes à l'aide de préfixes et d'alias. - Utiliser le
LEFT JOINpour inclure tous les enregistrements d'une table, y compris ceux qui n'ont pas d'enregistrements correspondants dans l'autre, et comprendre comment interpréter les valeursNULL. - Combiner les données de plusieurs tables à l'aide de jointures multiples, en illustrant comment obtenir des données de trois tables à la fois.
- Travailler avec les contraintes de clé étrangère pour maintenir l'intégrité des données, empêcher les enregistrements orphelins et démontrer comment MySQL gère les relations entre les tables.
Ces compétences constituent la base pour travailler efficacement avec les bases de données relationnelles. Comprendre comment combiner et relier des données entre plusieurs tables est essentiel pour construire des applications de base de données robustes.



