Corrigé bac NSI 2025 Métropole jour 1 — Exercice 1 : Collection de guitares de Slash : schéma relationnel et requêtes SQL
Sujet officiel du baccalauréat, spécialité numérique et sciences informatiques, session 2025. Corrigé rédigé par Ibrahim Alame.
Travailler ce sujet sur Adloun Sujet officiel (PDF) Corrigé complet (PDF)
Énoncé
Cet exercice porte sur les bases de données relationnelles et les requêtes SQL.
Dans cet exercice, on pourra utiliser les clauses du langage SQL pour :
- construire des requêtes d'interrogation à l'aide de
SELECT,FROM,WHERE(avec les opérateurs logiquesAND,OR),JOIN ... ON; - construire des requêtes d'insertion et de mise à jour à l'aide de
UPDATE,INSERT,DELETE; - affiner les recherches à l'aide de
DISTINCT,ORDER BY.
Dans un schéma relationnel, on utilisera les conventions suivantes :
- la clé primaire d'une relation est définie par son attribut souligné ;
- les attributs précédés de # sont les clés étrangères.
Le guitariste Slash possède une incroyable collection de guitares. Maud est une grande fan de Slash. Elle décide de faire un inventaire de la collection de guitares sous la forme d'une base de données relationnelle.
Partie A
Dans cette partie, Maud utilise la relation suivante :
inventaire (<u>id, marque, modele, annee, num_ser, prix)</u>
num_ser représente le numéro de série d'une guitare. Il est unique pour chaque guitare d'une même marque. Le prix est en euro.
Voici un extrait de la table inventaire.
inventaire
| `id` | `marque` | `modele` | `annee` | `num_ser` | `prix` |
|---|---|---|---|---|---|
| 1 | Gibson | Les Paul Goldtop | 1956 | @70562 | 100000 |
| 2 | Gibson | Les Paul Goldtop | 1988 | 81738349 | 20000 |
| 3 | Gibson | Les Paul Standard | 1959 | @90663 | 250000 |
| 4 | Gibson | Les Paul Standard | 1987 | 81757532 | 25000 |
| 5 | Fender | Telecaster | 1952 | 000230 | 150000 |
| 6 | Fender | Telecaster | 1965 | 81345673 | 10000 |
| 7 | Fender | Stratocaster | 1956 | 001359 | 200000 |
| 8 | Fender | Stratocaster | 1965 | 81757532 | 15000 |
1. Expliquer pourquoi l'attribut num_ser ne peut pas être une clé primaire de la relation inventaire.
2. Donner, sous forme de tableau, le résultat de la requête suivante appliquée à l'extrait de table précédent.
SELECT marque, modele
FROM inventaire
WHERE annee = 1956
3. Écrire une requête SQL permettant d'obtenir toutes les années du modèle Les Paul Standard dans la collection.
4. Écrire une requête SQL permettant d'obtenir tous les modèles de guitares de la marque Gibson par ordre croissant de l'année dans la collection.
5. Maud a fait une erreur de saisie pour la guitare d'identifiant id=1. L'année est en réalité 1957. Écrire une requête SQL permettant de corriger cette erreur de saisie.
Partie B
Maud change de représentation pour l'inventaire de la collection. Dans cette partie, Maud utilise maintenant les trois relations suivantes :
marque (<u>id, nom)</u>
modele (<u>id, nom, #id_marque)</u>
guitare (<u>id, #id_modele, annee, num_ser, prix)</u>
Dans la relation modele, #id_marque est une clé étrangère reliée à la clé primaire id de la relation marque. Dans la relation guitare, #id_modele est une clé étrangère reliée à la clé primaire id de la relation modele.
Voici des extraits des trois tables marque, modele, guitare.
marque
| `id` | `nom` |
|---|---|
| 1 | Gibson |
| 2 | Fender |
modele
| `id` | `nom` | `id_marque` |
|---|---|---|
| 1 | Les Paul Goldtop | 1 |
| 2 | Les Paul Standard | 1 |
| 3 | Telecaster | 2 |
| 4 | Stratocaster | 2 |
guitare
| `id` | `id_modele` | `annee` | `num_ser` | `prix` |
|---|---|---|---|---|
| 1 | 1 | 1956 | @70562 | 100000 |
| 2 | 1 | 1988 | 81738349 | 20000 |
| 3 | 2 | 1959 | @90663 | 250000 |
| 4 | 2 | 1987 | 81757532 | 25000 |
| 5 | 3 | 1952 | 000230 | 150000 |
| 6 | 3 | 1965 | 81345673 | 10000 |
| 7 | 4 | 1956 | 001359 | 200000 |
| 8 | 4 | 1965 | 81757532 | 15000 |
6. Expliquer brièvement, en justifiant, dans quel ordre les trois tables doivent être créées.
7. Écrire une requête SQL permettant d'obtenir le numéro de série et l'année de toutes les guitares Les Paul Standard de la collection.
Maud vient d'apprendre que Slash a fait cadeau d'une de ses guitares à un ami. Elle doit donc la retirer de sa base de données.
8. Écrire une requête SQL permettant de retirer de la collection la guitare d'identifiant id=3.
Slash a aussi acheté une guitare d'une marque qu'il n'avait pas encore dans sa collection. Maud décide de la rajouter.
9. Écrire l'ensemble des requêtes SQL permettant d'ajouter la guitare suivante :
- [–] marque : BC Rich
- [–] modèle : Mockingbird
- [–] année : 1992
- [–] numéro de série : 92R
- [–] prix : 5000.
On supposera que l'on peut attribuer la valeur 3 pour l'attribut id dans la table marque pour la marque BC Rich, que l'on peut attribuer la valeur 5 pour l'attribut id dans la table modele pour le modèle Mockingbird et que l'on peut attribuer la valeur 9 pour l'attribut id dans la table guitare pour cette guitare.
Maud souhaite connaître la valeur totale des modèles Stratocaster de la collection. Son ami David lui conseille de regarder la fonction SUM. La syntaxe pour utiliser cette fonction SQL peut être similaire à celle-ci :
SELECT SUM(nom_colonne)
FROM tab
Cette requête SQL permet de calculer la somme des valeurs contenues dans la colonne nom_colonne de la table tab.
10. Écrire une requête SQL permettant de calculer la valeur totale des modèles Stratocaster de la collection de Slash.
Corrigé
Partie A
1. Une clé primaire doit identifier de façon unique chaque enregistrement de la relation : deux lignes ne peuvent jamais porter la même valeur de clé (c'est la contrainte d'intégrité d'entité). Or l'énoncé précise que num_ser n'est unique qu'au sein d'une même marque : deux guitares de marques différentes peuvent porter le même numéro de série. L'extrait le montre d'ailleurs : la Gibson Les Paul Standard d'identifiant 4 et la Fender Stratocaster d'identifiant 8 ont toutes deux le numéro de série 81757532. La valeur 81757532 désignerait deux guitares, ce qu'une clé primaire interdit. En revanche, le couple (marque, num_ser) pourrait servir de clé, et c'est pourquoi Maud a créé l'identifiant artificiel id.
2. La clause WHERE annee = 1956 ne conserve que les lignes 1 et 7, et la projection SELECT marque, modele n'en garde que deux colonnes :
| `marque` | `modele` |
|---|---|
| Gibson | Les Paul Goldtop |
| Fender | Stratocaster |
3. On filtre sur le modèle et on ne projette que l'année :
SELECT annee
FROM inventaire
WHERE modele = 'Les Paul Standard';
Sur l'extrait, la requête renvoie 1959 et 1987. La chaîne de caractères est entre apostrophes simples, avec exactement l'orthographe de la table (majuscules comprises).
4. On filtre sur la marque et on trie avec ORDER BY, croissant par défaut (on peut préciser ASC) :
SELECT modele
FROM inventaire
WHERE marque = 'Gibson'
ORDER BY annee ASC;
Sur l'extrait, le résultat est, dans l'ordre : Les Paul Goldtop (1956), Les Paul Standard (1959), Les Paul Standard (1987), Les Paul Goldtop (1988). On peut ajouter annee dans le SELECT pour rendre le tri lisible ; on n'utilise pas DISTINCT, qui ferait perdre la correspondance entre un modèle et chacune de ses années.
5. On modifie une ligne existante avec UPDATE, en ciblant la guitare par sa clé primaire :
UPDATE inventaire
SET annee = 1957
WHERE id = 1;
Ce que le correcteur attend : la clause WHERE est indispensable ; sans elle, toutes les guitares de la table passeraient à l'année 1957.
Partie B
6. Une clé étrangère doit référencer la clé primaire d'une table qui existe déjà : le SGBD refuse de créer une contrainte référentielle vers une table absente (contrainte d'intégrité référentielle). Il faut donc créer les tables dans l'ordre des dépendances :
marque, qui ne dépend d'aucune autre table ;modele, dont l'attributid_marqueréférencemarque.id;guitare, dont l'attributid_modeleréférencemodele.id.
Le même ordre s'impose pour insérer des données (question 9) : une marque avant ses modèles, un modèle avant ses guitares.
7. Le nom du modèle est dans la table modele, le numéro de série et l'année dans la table guitare : il faut une jointure sur la clé étrangère id_modele :
SELECT guitare.num_ser, guitare.annee
FROM guitare
JOIN modele ON guitare.id_modele = modele.id
WHERE modele.nom = 'Les Paul Standard';
Sur l'extrait, la requête renvoie (@90663, 1959) et (81757532, 1987) : les guitares 3 et 4, seules à porter id_modele = 2.
Ce que le correcteur attend : sans la jointure, on ne peut pas filtrer sur nom, absent de guitare ; la condition de jointure relie bien la clé étrangère guitare.id_modele à la clé primaire modele.id, et non les deux attributs id.
8. On supprime la ligne par sa clé primaire :
DELETE FROM guitare
WHERE id = 3;
Seule la table guitare est touchée : le modèle Les Paul Standard et la marque Gibson restent dans la base, car d'autres guitares (ici la guitare 4) y font encore référence. Ici encore, oublier le WHERE viderait toute la table.
9. La marque BC Rich n'existe pas encore, pas plus que le modèle Mockingbird : il faut trois insertions, dans l'ordre imposé par les clés étrangères (marque, puis modèle, puis guitare), avec les identifiants fournis par l'énoncé :
INSERT INTO marque (id, nom)
VALUES (3, 'BC Rich');
INSERT INTO modele (id, nom, id_marque)
VALUES (5, 'Mockingbird', 3);
INSERT INTO guitare (id, id_modele, annee, num_ser, prix)
VALUES (9, 5, 1992, '92R', 5000);
Chaque clé étrangère pointe vers une ligne qui vient d'être créée : id_marque = 3 est l'identifiant de BC Rich, id_modele = 5 celui de Mockingbird. Le numéro de série '92R' contient une lettre : c'est une chaîne de caractères, entre apostrophes.
Ce que le correcteur attend : insérer la guitare avant son modèle (ou le modèle avant sa marque) violerait l'intégrité référentielle et serait refusé par le SGBD.
10. Le prix est dans guitare, le nom du modèle dans modele : on joint les deux tables, on filtre sur le modèle, puis on somme les prix avec la fonction d'agrégation SUM :
SELECT SUM(guitare.prix)
FROM guitare
JOIN modele ON guitare.id_modele = modele.id
WHERE modele.nom = 'Stratocaster';
Sur l'extrait, les Stratocaster sont les guitares 7 et 8 (id_modele = 4) ; la requête renvoie (euros). La fonction SUM s'applique après le filtrage : elle n'additionne que les lignes retenues par le WHERE, et renvoie une seule ligne.