Exercice 1 : QCM
Pour chaque question, une seule réponse est correcte.
1. Dans le modèle relationnel, comment appelle-t-on une colonne d’une table ?
- A. Un enregistrement
- B. Une relation
- C. Un attribut
- D. Une clé
Correction
C. Un attribut est le nom donné à une colonne dans le modèle relationnel. A (enregistrement) désigne une ligne, aussi appelée tuple ou n-uplet. B (relation) désigne la table elle-même. D (clé) désigne un attribut particulier servant à identifier ou relier des lignes.
2. Quel est le rôle d’une clé primaire ?
- A. Chiffrer les données de la table
- B. Trier automatiquement les enregistrements
- C. Relier deux tables entre elles
- D. Identifier de manière unique chaque enregistrement
Correction
D. La clé primaire garantit l’unicité de chaque ligne : deux lignes ne peuvent pas avoir la même valeur de clé primaire. A est faux (le chiffrement relève de la sécurité). B est faux (le tri se fait avec ORDER BY). C décrit le rôle d’une clé étrangère.
3. Quelle requête SQL permet de sélectionner tous les employés dont le salaire est supérieur à 3000 ?
- A.
SELECT * FROM employes WHERE salaire > 3000 - B.
SELECT * FROM employes IF salaire > 3000 - C.
SELECT * WHERE salaire > 3000 FROM employes - D.
SELECT salaire > 3000 FROM employes
Correction
A. La syntaxe correcte est SELECT ... FROM ... WHERE condition. B est faux (IF n’existe pas en SQL standard pour les requêtes). C a un ordre de clauses incorrect (WHERE doit suivre FROM). D confond la condition de filtrage avec la liste des colonnes à afficher.
4. Parmi ces ordres SQL, lequel est un ordre LDD (langage de définition des données) ?
- A.
SELECT * FROM employes - B.
INSERT INTO employes VALUES (...) - C.
CREATE TABLE employes (...) - D.
UPDATE employes SET salaire = 2000
Correction
C. CREATE TABLE modifie la structure de la base : c’est du LDD. Les ordres A, B et D modifient ou consultent le contenu de la base : ce sont des ordres LMD (langage de manipulation des données).
5. Dans le modèle relationnel, qu’est-ce qu’une clé étrangère ?
- A. Un attribut qui ne peut jamais être
NULL - B. Un attribut qui identifie de manière unique un enregistrement dans sa propre table
- C. Un attribut qui contient des données chiffrées
- D. Un attribut qui référence la clé primaire d’une autre table
Correction
D. Une clé étrangère est un attribut qui fait référence à la clé primaire d’une autre table, créant un lien entre les deux tables. C’est le mécanisme fondamental pour relier les données dans le modèle relationnel. B décrit une clé primaire, pas une clé étrangère.
Exercice 2 : lire et comprendre un schéma relationnel (exercice guidé)
Une médiathèque utilise la base de données suivante :
- Livres(id_livre, titre, auteur, annee)
- Adherents(num_adherent, nom, prenom)
- Emprunts(id_emprunt, #id_livre, #num_adherent, date_emprunt, date_retour)
Les attributs soulignés sont les clés primaires. Les attributs précédés de # sont les clés étrangères.
a) Combien de tables comporte ce schéma ? Pour chaque table, donnez le nombre d’attributs.
b) Quelle est la clé primaire de la table Emprunts ? Quelles sont ses clés étrangères ?
c) Un adhérent dont le num_adherent est 42 souhaite emprunter un livre dont le id_livre est 7. Quel attribut de la table Emprunts contiendra la valeur 42 ? Quel attribut contiendra 7 ?
d) Est-il possible d’insérer dans Emprunts une ligne avec id_livre = 999 si aucun livre n’a cet identifiant dans la table Livres ? Justifiez en citant la contrainte concernée.
e) Deux emprunts peuvent-ils avoir le même id_emprunt ? Justifiez.
Correction
a) Le schéma comporte trois tables. Livres a quatre attributs (id_livre, titre, auteur, annee). Adherents a trois attributs (num_adherent, nom, prenom). Emprunts a cinq attributs (id_emprunt, id_livre, num_adherent, date_emprunt, date_retour).
b) La clé primaire de Emprunts est id_emprunt. Ses clés étrangères sont id_livre (qui référence Livres.id_livre) et num_adherent (qui référence Adherents.num_adherent).
c) L’attribut num_adherent de la table Emprunts contiendra 42 et l’attribut id_livre contiendra 7. Ces deux attributs sont les clés étrangères qui font le lien entre l’emprunt, l’adhérent et le livre.
d) Non, c’est interdit. La contrainte d’intégrité référentielle impose que la valeur d’une clé étrangère doit correspondre à une valeur existante de la clé primaire qu’elle référence. Puisque id_livre dans Emprunts référence Livres.id_livre, il faut que le livre 999 existe dans la table Livres.
e) Non, deux emprunts ne peuvent pas avoir le même id_emprunt car c’est la clé primaire de la table Emprunts. La contrainte d’unicité de la clé primaire interdit les doublons.
Exercice 3 : requêtes SELECT (WHERE, ORDER BY, DISTINCT, agrégation)
On considère la table Produits suivante :
| id | nom | categorie | prix | stock |
|---|---|---|---|---|
| 1 | Cahier A4 | Papeterie | 2.50 | 150 |
| 2 | Stylo bleu | Papeterie | 1.20 | 300 |
| 3 | Clé USB 32 Go | Informatique | 8.90 | 45 |
| 4 | Cartouche encre | Informatique | 25.00 | 20 |
| 5 | Classeur | Papeterie | 3.80 | 80 |
| 6 | Souris sans fil | Informatique | 15.50 | 60 |
| 7 | Colle | Papeterie | 1.50 | 200 |
| 8 | Casque audio | Informatique | 35.00 | 15 |
Écrivez les requêtes SQL pour chacune des questions suivantes.
a) Afficher le nom et le prix de tous les produits de la catégorie « Informatique ».
b) Afficher les noms et prix des produits dont le prix est inférieur à 5 euros, triés par prix croissant.
c) Afficher les différentes catégories présentes dans la table (chaque catégorie ne doit apparaître qu’une seule fois).
d) Combien de produits ont un stock inférieur à 50 ?
e) Quel est le prix moyen de tous les produits de la table ?
f) Afficher le nom et le prix du produit le plus cher.
Correction
a)
SELECT nom, prix
FROM Produits
WHERE categorie = 'Informatique';
Résultat : Clé USB 32 Go (8.90), Cartouche encre (25.00), Souris sans fil (15.50), Casque audio (35.00).
b)
SELECT nom, prix
FROM Produits
WHERE prix < 5
ORDER BY prix;
Résultat : Stylo bleu (1.20), Colle (1.50), Cahier A4 (2.50), Classeur (3.80). Par défaut, ORDER BY trie en ordre croissant (ASC).
c)
SELECT DISTINCT categorie
FROM Produits;
Résultat : Papeterie, Informatique. Le mot-clé DISTINCT élimine les doublons dans le résultat.
d)
SELECT COUNT(*)
FROM Produits
WHERE stock < 50;
Résultat : 3. Les produits concernés sont : Clé USB 32 Go (45), Cartouche encre (20), Casque audio (15).
e)
SELECT AVG(prix)
FROM Produits;
Résultat : $(2.50 + 1.20 + 8.90 + 25.00 + 3.80 + 15.50 + 1.50 + 35.00) / 8 = 93.40 / 8 = 11.675$.
f)
SELECT nom, prix
FROM Produits
WHERE prix = (SELECT MAX(prix) FROM Produits);
Résultat : Casque audio (35.00). On utilise une sous-requête (SELECT MAX(prix) FROM Produits) pour obtenir le prix maximal, puis on filtre avec WHERE pour trouver le produit correspondant.
Exercice 4 : comprendre les jointures (exercice guidé)
On considère deux petites tables :
Eleves :
| id_eleve | nom | prenom | id_classe |
|---|---|---|---|
| 1 | Dupont | Marie | 101 |
| 2 | Martin | Lucas | 102 |
| 3 | Leroy | Emma | 101 |
Classes :
| id_classe | nom_classe | salle |
|---|---|---|
| 101 | Terminale A | B204 |
| 102 | Terminale B | C112 |
On souhaite afficher, pour chaque élève, son nom et le nom de sa classe. Il faut donc combiner les informations des deux tables : c’est une jointure.
a) Quel attribut est commun aux deux tables et permet de les relier ?
b) Pour l’élève Marie Dupont, son id_classe vaut 101. Dans la table Classes, quelle ligne correspond à id_classe = 101 ? Quel est le nom de sa classe ?
c) Faites le même travail pour les deux autres élèves : recopiez et complétez le tableau suivant.
| nom | prenom | nom_classe | salle |
|---|---|---|---|
| Dupont | Marie | … | … |
| Martin | Lucas | … | … |
| Leroy | Emma | … | … |
d) Voici la requête SQL qui réalise cette jointure :
SELECT Eleves.nom, Eleves.prenom, Classes.nom_classe
FROM Eleves
JOIN Classes ON Eleves.id_classe = Classes.id_classe;
Identifiez dans cette requête : la clause qui combine les deux tables ; la condition qui établit la correspondance.
e) Écrivez une requête qui affiche le prénom des élèves de la salle B204.
f) Combien d’élèves sont en Terminale A ? Écrivez la requête.
Correction
a) L’attribut id_classe est présent dans les deux tables. Dans Eleves, c’est une clé étrangère ; dans Classes, c’est la clé primaire. C’est cet attribut qui permet de relier chaque élève à sa classe.
b) L’élève Marie Dupont a id_classe = 101. Dans la table Classes, la ligne id_classe = 101 correspond à « Terminale A », salle B204. Sa classe est donc « Terminale A ».
c) Tableau complété :
| nom | prenom | nom_classe | salle |
|---|---|---|---|
| Dupont | Marie | Terminale A | B204 |
| Martin | Lucas | Terminale B | C112 |
| Leroy | Emma | Terminale A | B204 |
On a associé chaque élève à la ligne de Classes ayant le même id_classe.
d) La clause JOIN Classes indique que l’on combine la table Eleves avec la table Classes. La condition ON Eleves.id_classe = Classes.id_classe précise comment établir la correspondance : on relie les lignes dont la valeur de id_classe est identique dans les deux tables.
e)
SELECT Eleves.prenom
FROM Eleves
JOIN Classes ON Eleves.id_classe = Classes.id_classe
WHERE Classes.salle = 'B204';
Résultat : Marie, Emma.
f)
SELECT COUNT(*)
FROM Eleves
JOIN Classes ON Eleves.id_classe = Classes.id_classe
WHERE Classes.nom_classe = 'Terminale A';
Résultat : 2 (Dupont Marie et Leroy Emma).
Exercice 5 : insertion, modification, suppression et contraintes
On reprend les tables de l’exercice 4 (Eleves et Classes).
a) Écrivez l’ordre SQL pour insérer une nouvelle classe : Terminale C, salle A308, identifiant 103.
b) Écrivez l’ordre SQL pour inscrire un nouvel élève : Paul Petit, identifiant 4, dans la classe 103.
c) Lucas Martin change de classe : il passe en Terminale A (id_classe = 101). Écrivez la requête de modification.
d) On souhaite supprimer la classe « Terminale B » (id_classe = 102). Après la modification de la question c), est-ce possible sans violer de contrainte ? Justifiez.
e) Que se passerait-il si l’on tentait d’insérer un élève avec id_classe = 999, sachant qu’aucune classe n’a cet identifiant ? Quelle contrainte serait violée ?
Correction
a)
INSERT INTO Classes (id_classe, nom_classe, salle)
VALUES (103, 'Terminale C', 'A308');
b)
INSERT INTO Eleves (id_eleve, nom, prenom, id_classe)
VALUES (4, 'Petit', 'Paul', 103);
La classe 103 existe bien (insérée en a), donc la contrainte d’intégrité référentielle est respectée.
c)
UPDATE Eleves
SET id_classe = 101
WHERE nom = 'Martin' AND prenom = 'Lucas';
Après cette modification, Lucas Martin est en Terminale A.
d) Après la modification de c), plus aucun élève n’a id_classe = 102. On peut donc supprimer cette classe sans violer la contrainte d’intégrité référentielle :
DELETE FROM Classes
WHERE id_classe = 102;
Si un élève avait encore id_classe = 102, la suppression aurait été refusée (ou aurait causé une incohérence) car la clé étrangère de cet élève référencerait une classe inexistante.
e) L’insertion serait refusée par le SGBD. La contrainte d’intégrité référentielle impose que la valeur de id_classe dans Eleves doit correspondre à une valeur existante de id_classe dans Classes. Puisque la classe 999 n’existe pas, l’insertion viole cette contrainte.
Exercice 6 : anomalies dans une base mal conçue
Un magasin de vélos stocke toutes ses informations dans une seule table :
| id_vente | client | telephone_client | velo | marque | prix | date_vente |
|---|---|---|---|---|---|---|
| 1 | Alice Dupont | 0612345678 | VTT Sport 27.5 | Trek | 899 | 2025-09-15 |
| 2 | Bob Martin | 0698765432 | Vélo ville 28 | B’Twin | 349 | 2025-09-16 |
| 3 | Alice Dupont | 0612345678 | Vélo route carbone | Trek | 2499 | 2025-09-20 |
| 4 | Alice Dupont | 0612340000 | Casque urbain | B’Twin | 45 | 2025-10-01 |
a) Alice Dupont apparaît dans trois lignes. Son numéro de téléphone est-il le même partout ? Quel problème cela pose-t-il ?
b) Supposons que le magasin cesse de vendre le modèle « Vélo ville 28 ». Si l’on supprime la ligne 2, quelles informations perd-on en plus du vélo ? Pourquoi est-ce problématique ?
c) Le magasin souhaite ajouter un nouveau vélo (VTT Enfant 24) qu’il n’a encore jamais vendu. Peut-on ajouter ce vélo dans la table sans créer de vente fictive ? Pourquoi ?
d) Comment appelle-t-on chacun de ces trois problèmes dans le vocabulaire des bases de données ?
e) Proposez un schéma relationnel avec plusieurs tables qui résout ces anomalies. Précisez les clés primaires et les clés étrangères.
Correction
a) Non : dans les lignes 1 et 3, le téléphone d’Alice Dupont est 0612345678, mais dans la ligne 4, il est 0612340000. C’est une anomalie de mise à jour (ou incohérence) : les mêmes informations client sont dupliquées dans plusieurs lignes, et lors d’une modification (changement de numéro), toutes les occurrences n’ont pas été mises à jour.
b) En supprimant la ligne 2, on perd non seulement la vente du « Vélo ville 28 », mais aussi les informations sur le client Bob Martin (nom, téléphone). Si Bob Martin n’a fait aucun autre achat, il disparaît complètement de la base. C’est une anomalie de suppression : supprimer un fait (la vente) entraîne la perte d’un autre fait indépendant (l’existence du client).
c) Non, on ne peut pas ajouter un vélo sans vente. La table exige un id_vente, un client et une date, or on n’a ni client ni date pour un vélo simplement référencé au catalogue. C’est une anomalie d’insertion : on ne peut pas enregistrer un fait (l’existence d’un produit) sans enregistrer simultanément un fait indépendant (une vente).
d) Les trois problèmes sont : l’anomalie de mise à jour (a), l’anomalie de suppression (b) et l’anomalie d’insertion (c). Ces anomalies sont causées par la redondance des données dans une table unique mal conçue.
e) Schéma relationnel corrigé :
- Clients(id_client, nom, telephone)
- Velos(id_velo, modele, marque, prix)
- Ventes(id_vente, #id_client, #id_velo, date_vente)
Les clés étrangères id_client et id_velo dans Ventes référencent respectivement Clients.id_client et Velos.id_velo. Chaque information est stockée une seule fois : le téléphone d’Alice n’apparaît que dans une seule ligne de Clients, et le vélo « VTT Enfant 24 » peut exister dans Velos sans nécessiter de vente.
Exercice 7 : synthèse – gestion d’une association sportive
Une association sportive gère ses adhérents et les activités proposées. Voici le schéma relationnel :
- Adherents(id_adh, nom, prenom, annee_naissance)
- Activites(id_act, nom_activite, jour, creneau, places_max)
- Inscriptions(id_insc, #id_adh, #id_act, date_inscription)
On dispose des données suivantes.
Adherents :
| id_adh | nom | prenom | annee_naissance |
|---|---|---|---|
| 1 | Dupont | Marie | 2007 |
| 2 | Martin | Lucas | 2006 |
| 3 | Leroy | Emma | 2008 |
| 4 | Petit | Hugo | 2007 |
| 5 | Bernard | Léa | 2006 |
Activites :
| id_act | nom_activite | jour | creneau | places_max |
|---|---|---|---|---|
| 10 | Natation | Mercredi | 14h-16h | 20 |
| 20 | Badminton | Samedi | 10h-12h | 15 |
| 30 | Escalade | Mercredi | 16h-18h | 12 |
Inscriptions :
| id_insc | id_adh | id_act | date_inscription |
|---|---|---|---|
| 1 | 1 | 10 | 2025-09-01 |
| 2 | 1 | 20 | 2025-09-01 |
| 3 | 2 | 10 | 2025-09-03 |
| 4 | 3 | 30 | 2025-09-05 |
| 5 | 4 | 10 | 2025-09-06 |
| 6 | 4 | 30 | 2025-09-06 |
| 7 | 5 | 20 | 2025-09-10 |
a) Écrivez une requête affichant les noms et prénoms des adhérents nés en 2007, triés par nom.
b) Combien d’inscriptions ont été enregistrées en tout ? Écrivez la requête.
c) Écrivez une requête affichant le nom et le prénom de chaque adhérent inscrit à « Natation ».
d) Écrivez une requête affichant le nombre total d’inscrits à l’activité « Natation ».
e) L’adhérent Hugo Petit souhaite se désinscrire de l’escalade. Écrivez la requête appropriée.
f) Une nouvelle activité « Yoga » est proposée le vendredi de 17h à 18h30, avec 25 places. Attribuez-lui l’identifiant 40. Écrivez la requête d’insertion.
g) Léa Bernard souhaite s’inscrire à l’escalade (id_insc = 8, date : 2025-10-01). Écrivez la requête. La contrainte d’intégrité référentielle est-elle respectée ? Justifiez.
h) Un adhérent peut-il s’inscrire à une activité qui n’existe pas (par exemple id_act = 99) ? Expliquez pourquoi en citant la contrainte.
Correction
a)
SELECT nom, prenom
FROM Adherents
WHERE annee_naissance = 2007
ORDER BY nom;
Résultat : Dupont Marie, Petit Hugo.
b)
SELECT COUNT(*)
FROM Inscriptions;
Résultat : 7 inscriptions au total.
c)
SELECT Adherents.nom, Adherents.prenom
FROM Adherents
JOIN Inscriptions ON Adherents.id_adh = Inscriptions.id_adh
JOIN Activites ON Inscriptions.id_act = Activites.id_act
WHERE Activites.nom_activite = 'Natation';
Résultat : Dupont Marie, Martin Lucas, Petit Hugo.
d)
SELECT COUNT(*)
FROM Inscriptions
JOIN Activites ON Inscriptions.id_act = Activites.id_act
WHERE Activites.nom_activite = 'Natation';
Résultat : 3 inscrits (inscriptions 1, 3 et 5).
e)
DELETE FROM Inscriptions
WHERE id_adh = 4 AND id_act = 30;
On identifie Hugo Petit par id_adh = 4 et l’escalade par id_act = 30. On pourrait aussi écrire WHERE id_insc = 6, puisque c’est l’identifiant de cette inscription.
f)
INSERT INTO Activites (id_act, nom_activite, jour, creneau, places_max)
VALUES (40, 'Yoga', 'Vendredi', '17h-18h30', 25);
g)
INSERT INTO Inscriptions (id_insc, id_adh, id_act, date_inscription)
VALUES (8, 5, 30, '2025-10-01');
La contrainte d’intégrité référentielle est respectée : id_adh = 5 (Léa Bernard) existe dans Adherents et id_act = 30 (Escalade) existe dans Activites. Les deux clés étrangères pointent vers des valeurs existantes.
h) Non, l’insertion serait refusée. L’attribut id_act dans Inscriptions est une clé étrangère qui référence Activites.id_act. La contrainte d’intégrité référentielle impose que toute valeur de cette clé étrangère corresponde à une valeur existante de la clé primaire de Activites. L’activité 99 n’existant pas, l’insertion viole cette contrainte.