Terminale
Bases de données
Ce chapitre étudie comment structurer des données dans une base de données relationnelle, et comment les interroger avec le langage SQL. Il prolonge le travail sur les tableaux de données mené en Première (voir Traitement de données en tables), en organisant cette fois l'information en plusieurs tables reliées entre elles.
Modèle relationnel et SGBD
Le modèle relationnel
Une base de données relationnelle organise les données en tables (ou relations). Chaque table est composée de lignes (ou enregistrements) et de colonnes (ou attributs). Chaque attribut est associé à un domaine, c'est-à-dire l'ensemble des valeurs qu'il peut prendre (entiers, texte, dates...).
Exemple. Une table Auteurs recensant des écrivains :
| id_auteur | nom | nationalite |
|---|---|---|
| 1 | Hugo | Française |
| 2 | Christie | Britannique |
| 3 | Senghor | Sénégalaise |
Clé primaire
Une clé primaire est un attribut (ou un groupe d'attributs) qui permet d'identifier de façon unique chaque enregistrement d'une table. Ici, id_auteur est la clé primaire de Auteurs : deux auteurs distincts ont toujours des id_auteur différents. Une clé primaire ne doit jamais être nulle, et ses valeurs ne peuvent pas se répéter.
Il arrive qu'aucun attribut « naturel » ne convienne (deux auteurs peuvent porter le même nom) : on ajoute alors une clé primaire artificielle, le plus souvent un identifiant entier auto-incrémenté.
Clé étrangère et schéma relationnel
Le schéma relationnel d'une base de données décrit l'ensemble de ses tables et de leurs relations. Pour relier deux tables entre elles, on utilise une clé étrangère : un attribut d'une table qui référence la clé primaire d'une autre table.
Exemple. Une table Livres, où chaque livre est écrit par un auteur de la table Auteurs :
| id_livre | titre | annee | id_auteur |
|---|---|---|---|
| 1 | Les Misérables | 1862 | 1 |
| 2 | Le Crime de l'Orient-Express | 1934 | 2 |
| 3 | Chants d'ombre | 1945 | 3 |
Ici, id_auteur est une clé étrangère dans Livres : elle référence la clé primaire id_auteur de la table Auteurs. Cela évite de dupliquer le nom et la nationalité de l'auteur à chaque ligne de Livres — on distingue ainsi la structure de la base (le schéma) de son contenu (les données qu'elle stocke à un instant donné).
Une base de données mal conçue peut présenter des anomalies : redondance d'information (le même nom d'auteur recopié partout), risque d'incohérence lors d'une mise à jour (si on modifie le nom dans une ligne mais pas dans les autres), ou impossibilité d'enregistrer une donnée isolée. Séparer les données en plusieurs tables reliées par des clés étrangères, comme ci-dessus, permet d'éviter ces anomalies.
Le rôle d'un système de gestion de bases de données (SGBD)
Un SGBD (Système de Gestion de Bases de Données) est le logiciel qui gère une base de données. Il rend notamment les services suivants :
- la persistance des données : elles restent stockées durablement, même après l'arrêt du programme ou de la machine ;
- la gestion des accès concurrents : plusieurs utilisateurs ou programmes peuvent lire et modifier la base en même temps sans la corrompre ;
- l'efficacité du traitement des requêtes, y compris sur de très grands volumes de données ;
- la sécurisation des accès, en contrôlant qui a le droit de lire ou modifier quelles données.
La plupart des SGBD (PostgreSQL, MySQL, SQLite...) reposent sur le modèle relationnel décrit ci-dessus, et se pilotent avec le langage SQL.
Exercice — Identifier clés primaires et clés étrangères
On souhaite modéliser une médiathèque avec deux tables :
Adherents(id_adherent, nom, email)
Emprunts(id_emprunt, id_adherent, titre_livre, date_emprunt)
Un emprunt est toujours associé à un unique adhérent, mais un adhérent peut faire plusieurs emprunts.
- Quelle est la clé primaire de la table
Adherents? Et celle de la tableEmprunts? - Quel attribut de la table
Empruntsest une clé étrangère ? Vers quelle table et quel attribut fait-elle référence ? - Pourquoi est-il préférable de séparer les emprunts dans une table distincte plutôt que d'ajouter des colonnes
emprunt1,emprunt2, ... directement dans la tableAdherents?
Exercice — Corriger une anomalie de redondance dans un schéma relationnel
Un club de tennis enregistre les inscriptions de ses licenciés aux tournois dans une seule table :
Inscriptions(id_inscription, nom_joueur, ville_joueur, nom_tournoi, date_tournoi)
Chaque ligne correspond à l'inscription d'un joueur à un tournoi. Un même joueur, inscrit à plusieurs tournois, apparaît donc sur plusieurs lignes (avec sa ville recopiée à chaque fois) ; de même, un tournoi accueillant de nombreux joueurs voit son nom et sa date recopiés sur autant de lignes que d'inscrits.
- Quelle anomalie ce schéma présente-t-il ? Donner un exemple concret de problème que cela peut causer lors d'une mise à jour.
- Proposer un nouveau schéma relationnel avec trois tables
Joueurs,TournoisetInscriptions, qui corrige cette anomalie. Préciser, pour chaque table, sa clé primaire, et pour la tableInscriptions, ses éventuelles clés étrangères. - Avec ce nouveau schéma, un tournoi accueillant 100 joueurs n'occupe-t-il plus qu'une seule ligne dans la table qui le décrit ? Justifier.
Exercice — D'un fichier tableur partagé à une base de données relationnelle
Une petite entreprise gère actuellement la liste de ses clients et de leurs commandes dans un unique fichier tableur, stocké sur un dossier partagé. Plusieurs employés du service commercial ouvrent et modifient ce fichier en même temps depuis leurs postes. L'entreprise envisage de migrer vers une base de données relationnelle pilotée par un SGBD.
Le cours identifie quatre services rendus par un SGBD : la persistance, la gestion des accès concurrents, l'efficacité du traitement des requêtes, et la sécurisation des accès.
- Pour chacun de ces quatre services, décrire un problème concret que peut rencontrer l'entreprise avec son fichier tableur actuel, et expliquer en quoi un SGBD résoudrait ce problème.
- Au-delà de ces quatre services, en quoi le fait de structurer les données en tables reliées par des clés primaires et étrangères (plutôt que de tout regrouper dans un seul tableau, comme dans le fichier actuel) contribue-t-il, lui aussi, à la fiabilité de la base de données de l'entreprise ?
QCM — Modèle relationnel
Langage SQL : interrogation et mise à jour
Créer une table et insérer des données
Le langage SQL (Structured Query Language) permet de créer, interroger et modifier une base de données relationnelle. On crée une table avec CREATE TABLE, en précisant le nom et le type de chaque colonne, ainsi que la clé primaire :
CREATE TABLE Auteurs (
id_auteur INTEGER PRIMARY KEY,
nom TEXT,
nationalite TEXT
);
CREATE TABLE Livres (
id_livre INTEGER PRIMARY KEY,
titre TEXT,
annee INTEGER,
id_auteur INTEGER
);On insère des enregistrements avec INSERT INTO :
INSERT INTO Auteurs (id_auteur, nom, nationalite)
VALUES (1, 'Hugo', 'Française'), (2, 'Christie', 'Britannique');
INSERT INTO Livres (id_livre, titre, annee, id_auteur)
VALUES (1, 'Les Misérables', 1862, 1), (2, 'Le Crime de l Orient-Express', 1934, 2);Interroger une table : SELECT, FROM, WHERE
La commande SELECT sélectionne des colonnes ; FROM précise la table ; WHERE filtre les lignes selon une condition.
-- toutes les colonnes de tous les livres
SELECT * FROM Livres;
-- seulement le titre des livres parus apres 1900
SELECT titre FROM Livres WHERE annee > 1900;On peut combiner plusieurs conditions avec AND / OR, et trier le résultat avec ORDER BY :
SELECT titre, annee FROM Livres
WHERE annee > 1900 AND annee < 2000
ORDER BY annee ASC;Croiser plusieurs tables : JOIN
Une jointure (JOIN ... ON ...) permet de combiner les lignes de deux tables lorsqu'une condition (souvent une égalité entre clé étrangère et clé primaire) est vérifiée. Pour afficher, pour chaque livre, le nom de son auteur :
SELECT Livres.titre, Auteurs.nom
FROM Livres
JOIN Auteurs ON Livres.id_auteur = Auteurs.id_auteur;Mettre à jour une base : UPDATE, INSERT, DELETE
UPDATE ... SET ... WHERE ...modifie des enregistrements existants ;INSERT INTO ... VALUES ...(vu plus haut) ajoute un enregistrement ;DELETE FROM ... WHERE ...supprime des enregistrements.
-- corriger l'annee de parution d'un livre
UPDATE Livres SET annee = 1863 WHERE id_livre = 1;
-- supprimer les livres parus avant 1900
DELETE FROM Livres WHERE annee < 1900;Attention : sans clause
WHERE,UPDATEetDELETEs'appliquent à toutes les lignes de la table.
Exercice — Écrire des requêtes SQL
On reprend les deux tables du cours :
Auteurs(id_auteur, nom, nationalite)
Livres(id_livre, titre, annee, id_auteur)
- Écrire une requête SQL qui affiche le titre et l'année de tous les livres parus après 1940, triés par année croissante.
- Écrire une requête SQL qui affiche le titre de chaque livre accompagné du nom de son auteur (utiliser une jointure).
- Écrire une requête SQL qui met à jour la nationalité de l'auteur d'
id_auteurégal à 3 en'Sénégalaise'.
Exercice — Bac NSI — Sujet zéro 2021 (exercice 4)
Exercice tiré du sujet zéro officiel du bac NSI (2021), sur les bases de données relationnelles et le SQL.
Table seconde : num_eleve (INT, clé primaire), langue1, langue2, option, classe. Extrait de données :
| num_eleve | nom | prenom | langue1 | langue2 | option | classe |
|---|---|---|---|---|---|---|
| 101 | MARTIN | Léa | anglais | espagnol | — | 2A |
| 102 | BERNARD | Yanis | allemand | anglais | théâtre | 2D |
| 103 | ROBERT | Chloé | allemand | anglais | — | 2A |
| 104 | PETIT | Hugo | anglais | allemand | — | 2B |
| 105 | DURAND | Nina | anglais | espagnol | cinéma | 2D |
| 106 | LEROY | Malo | espagnol | allemand | — | 2B |
1. Intérêt de num_eleve comme clé primaire ? Écrire l'insertion SQL de MARTIN Léa dans seconde.
2. Que renvoie SELECT num_eleve FROM seconde; ? Et SELECT COUNT(num_eleve) FROM seconde; ? Écrire la requête comptant les élèves ayant l'allemand en langue1 ou langue2.
3. On crée eleve (num_eleve clé primaire et clé étrangère vers seconde, nom, prenom, datenaissance). Qu'apporte cette clé étrangère ? Écrire la jointure listant nom/prénom/date de naissance des élèves de 2A.
4. Proposer la structure d'une table coordonnees (adresse, code postal, ville, e-mail par élève), avec sa clé primaire et sa clé étrangère.
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — Sujet « 2 annulé » 2021 (exercice 2)
Exercice tiré du sujet NSI 2021 dit « 2 annulé », sur les bases de données relationnelles.
Base restaurant : Plat(idPlat, nom, categorie, description, prix), Client(idClient, email, passwd, nom, avis), Reservation(idReservation, #idClient, jour, heure, numTable), Commande(#idPlat, #idReservation).
1. Parmi SELECT nom, prix FROM Plat WHERE categorie='entrée', SELECT * FROM Plat WHERE categorie='entrée' et UPDATE Plat SET categorie='entrée' WHERE 1, laquelle renvoie tous les attributs des plats de catégorie 'entrée' ?
2. Écrire les requêtes : a) noms et avis des clients ayant réservé le '2021-06-05' à '19:30:00' ; b) noms des plats 'plat principal' ou 'dessert' commandés le '2021-04-12'.
3. Que fait INSERT INTO Plat VALUES(58,'Pêche Melba','dessert','Pêches et glace vanille',6.5); ?
4. Écrire : a) suppression des commandes d'idReservation 2047 ; b) augmentation de 5% des prix strictement inférieurs à 20,00.
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — Asie/Pacifique 2022 J2 (exercice 4)
Exercice tiré du bac NSI 2022 (Asie/Pacifique, Jour 2), sur une base de données SQL pour un club de tennis.
joueurs(id_joueur, nom_joueur, prenom_joueur, login, mdp) : (1,Dupont,Alice,alice,1234), (2,Durand,Belina,belina,5694), (3,Caron,Camilia,camilia,9478), (4,Dupont,Dorine,dorine,1347).
matchs(id_match, date, id_creneau, id_terrain, id_joueur1, id_joueur2) : (1,2020-08-01,2,1,1,4), (2,2020-08-01,3,1,2,3), (3,2020-08-02,6,2,1,3), (4,2020-08-02,7,2,2,4), (5,2020-08-08,3,3,1,2), (6,2020-08-08,5,2,3,4).
terrains(id_terrain, nom_terrain, surface) : (1,stade,terre battue), (2,gymnase,synthétique), (3,hangar,terre battue). creneaux(id_creneau, plage_horaire) : 12 créneaux d'une heure, de 8h à 20h (id_creneau=3 → 10h-11h).
1. Clé primaire de matchs ? Ses clés étrangères ?
2. Jour et créneau du match entre Durand Belina et Caron Camilia ? Quels sont les deux seuls joueurs à avoir joué dans le hangar (terrain 3) ?
3. Requête donnant les prénoms des joueurs de nom 'Dupont'. Requête mettant à jour le mot de passe de Dorine Dupont à '1976'.
4. Requête ajoutant Zora MAGID (login 'zora', mot de passe '2021').
5. Requête donnant les jours où Alice joue.
Exercice — Bac NSI — La Réunion 2022 (exercice 3)
Exercice tiré du bac NSI La Réunion 2022 (Jour 1), sur les bases de données relationnelles et SQL (QCM en ligne).
Base QCM_NSI : eleves(ideleve, nom, prenom), qcm(idqcm, titre, date), questions(idquestion, #idqcm, question, bonnereponse), lien_eleve_qcm(#ideleve, #idqcm, note) de clé primaire (ideleve, idqcm).
eleves : (2,Dubois,Thomas), (3,Dupont,Cassandra), (4,Marty,Mael), (5,Bikila,Abebe).
qcm : (1,"Base de données",2021-09-20), (2,"POO",2022-04-08), (3,"Arbre Binaire",2022-01-09), (4,"Arbre Parcours",2022-02-15), (5,"Piles-Files",2021-12-05).
lien_eleve_qcm : (2,1,12), (2,3,18), (2,4,13), (2,5,15), (3,1,20), (3,2,9), (3,3,18), (3,5,13), (4,4,15), (4,5,20), (5,4,15).
1.a. Que renvoie SELECT titre FROM qcm WHERE date > '2022-01-10'; ?
1.b. Requête donnant les notes de l'élève d'identifiant 4.
2.a. La clé primaire de lien_eleve_qcm est (ideleve, idqcm). Pourquoi un élève ne peut-il pas faire deux fois le même QCM ?
2.b. Marty Mael fait le QCM POO, note 18 : comment la base est-elle modifiée (sans SQL) ?
2.c. Nouvel élève (Lefèvre, Kevin) : requête d'enregistrement.
2.d. Dubois Thomas (ideleve=2) part : requête supprimant ses lignes de lien_eleve_qcm.
3.a. Compléter pour afficher noms/prénoms des élèves ayant fait le QCM d'idqcm=4 :
SELECT .............................. FROM eleves
JOIN lien_eleve_qcm ON eleves.ideleve = ..............................
WHERE .............................. ;3.b. Résultat de cette requête.
4. Requête (3 tables) affichant nom, prénom, note des élèves ayant fait "Arbre Binaire".
Exercice — Bac NSI — Métropole 2022 (exercice 2)
Exercice tiré du bac NSI Métropole 2022 (Jour 1), sur les bases de données relationnelles (cinéma).
Schéma : individu(id_ind, nom, prenom, naissance), realisation(id_rea, titre, annee, type), emploi(id_emp, description, #id_ind, #id_rea).
individu : (105,Hulka,Daniel,01-06-1968), (403,Travis,Daniel,10-03-1968), (688,Crog,Daniel,07-07-1968), (695,Pollock,Daniel,24-08-1968).
realisation : (105,"Casino Imperial",2006,action), (325,"Ciel tombant",2012,action), (655,"Fantôme",2015,action), (950,"Mourir pour attendre",2021,action).
1.a. Que renvoie SELECT nom, prenom, naissance FROM individu WHERE nom = 'Crog'; ?
1.b. Requête donnant titre et id_rea de chaque film sorti strictement après 2020.
2.a. Pour corriger la naissance de Daniel Crog, UPDATE ou INSERT ? Justifier :
UPDATE individu SET naissance = '02-03-1968'
WHERE id_ind = 688 AND nom = 'Crog' AND prenom = 'Daniel';
-- ou --
INSERT INTO individu VALUES (688, 'Crog', 'Daniel', '02-03-1968');2.b. individu peut-elle accepter deux lignes de même nom, prénom et naissance ?
3.a. Compléter pour ajouter les rôles de Daniel Crog (James Bond) dans "Casino Impérial"(105) puis "Ciel tombant"(325) :
INSERT INTO emploi VALUES (5400, 'Acteur(James Bond)', ...);
INSERT INTO emploi VALUES (5401, 'Acteur(James Bond)', ...);3.b. Nouveau rôle dans "Docteur Yes" (film pas encore enregistré) : créer d'abord le film ou le rôle ? Pourquoi ?
4.a. Compléter pour obtenir nom, titre, année de chaque rôle 'Acteur(James Bond)' :
SELECT ...
FROM emploi
JOIN individu ON ...
JOIN realisation ON ...
WHERE emploi.description = 'Acteur(James Bond)';4.b. Requête donnant les descriptions des emplois de Denis Johnson (seulement les descriptions).
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — Métropole session de remplacement 2022 (exercice 3)
Exercice tiré du bac NSI Métropole (session de remplacement) 2022, sur les bases de données relationnelles (catalogue Gaia).
Table Gaia(Num_Objet: Int, Num_Systeme: Int, Nom_Systeme: String, #Type_Objet: String, Nom_Objet: String, Ascension_Droite: Real, Declinaison: Real, Parallaxe: Real, Nom_SIMBAD: String). Extrait de 14 objets (Proxima Cen, alf Cen A/B, Barnard's Star, Luhman 16 A/B, Wolf 359, HD 95735, Lalande 21185 b, alf CMa A/B, G 272-61 A/B, Ross 154, Ross 248), de types LM, Planet, *, BD, WD, avec parallaxes de 316 à 768 mas.
1. Pourquoi Num_Objet peut-il être clé primaire de Gaia ?
Table Type(Type_Objet, Libelle_Objet) : LM→"Etoile de faible masse", Planet→"Planète", *→"Etoile", BD→"Naine Brune", WD→"Naine Blanche".
2. Proposer le schéma relationnel de Type, clé primaire soulignée.
3. Laquelle de ces requêtes ne provoque pas d'erreur ?
a. INSERT INTO Gaia VALUES ('8', 4, 'WISEA J085510', 'Naine Brune', 'WISEA J085510', 133.781,-7.244, 439.000, 'WISEA J085510');
b. INSERT INTO Gaia VALUES (8, 4, 'WISEA J085510', 'Naine Brune', 'WISEA J085510', 133.781,-7.244, 439.000, 'WISEA J085510');
c. INSERT INTO Gaia VALUES (8, 4, WISEA J085510, 'Naine Brune', WISEA J085510, 133.781,-7.244, 439.000, WISEA J085510);
d. INSERT INTO Gaia VALUES (8, 4, 'WISEA J085510', 'Naine Brune', 'WISEA J085510', '133.781',-7.244, 439.000, 'WISEA J085510')
4. Pourquoi INSERT INTO Type VALUES ('BD', 'Trou Noir'); échoue ?
5. Résultat de SELECT Nom_Objet, Parallaxe FROM Gaia WHERE Type_Objet = 'Planet'; ?
6. Requête donnant nom du système, nom de l'objet, libellé du type pour parallaxe > 400 mas et type '*'.
7.a. Requête insérant un type 'ST' de libellé "Etoile".
7.b. Démarche complète pour remplacer '*' par 'ST'.
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — Nouvelle-Calédonie 2022 J2 (exercice 3)
Exercice tiré du bac NSI Nouvelle-Calédonie 2022 (jour 2), sur les bases de données relationnelles et SQL : les chevaliers de la table ronde.
Table Personnage(Idperso, nom, frere_de, points, Idqualite), table Qualite(Idqualite, nom_qualite) (1 apprenti chevalier, 2 magicien, 3 preux chevalier, 4 espion, 5 seigneur, 6 sage, 7 grand chevalier). Extrait de Personnage : Merlin (NC, 40, qualité 2), Galehaut (NC, 40, 5), Lancelot (Hector, 50, 1), Perceval (Lamorak, 35, 3), Keud (Arthur, 80, 7), etc.
1. Écrire une requête affichant le nom et les points de tous les personnages.
2. Le frère d'Arthur ne s'appelle pas Keud mais Antor : écrire la requête de correction.
3. Écrire une requête ajoutant le nom_qualite « roi » à Qualite, d'Idqualite 8.
4. Écrire une requête créant un quatorzième personnage : le roi Arthur, 100 points.
5. Écrire une requête affichant le nom et le nom de qualité des personnages ayant 40 points.
6. On applique UPDATE Personnage SET points = points + 10 WHERE points < 40;. Indiquer les points d'Arthur, Perceval et Merlin après cette mise à jour.
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — Session 2021 (exercice 3)
Exercice tiré d'un bac NSI de la session 2021 (centre d'examen non confirmé), sur les bases de données relationnelles et SQL : la gestion d'une gare.
Schéma : Train(numT, provenance, destination, horaireArrivee, horaireDepart), Reservation(numR, nomClient, prenomClient, prix, #numT) (numT clé étrangère vers Train.numT).
1. Nom générique des logiciels assurant la persistance des données, l'efficacité des requêtes et la sécurisation des accès ?
2. a) DELETE FROM Train WHERE numT = 1241; puis DELETE FROM Reservation WHERE numT = 1241; : pourquoi la première instruction échoue-t-elle si des réservations existent pour ce train ? b) Citer un cas où l'insertion dans Reservation est impossible.
3. Écrire les requêtes : a) tous les numéros de train de destination « Lyon » ; b) réservation n°1307, 33 €, M. Alan Turing, train n°654 ; c) mise à jour de l'horaire d'arrivée du train n°7869 à 08h11.
4. Que détermine SELECT COUNT(*) FROM Reservation WHERE nomClient = "Hopper" AND prenomClient = "Grace"; ?
5. Écrire la requête renvoyant les destinations et les prix des réservations de Grace Hopper.
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — Amérique du Nord 2024 J2 (exercice 2)
Exercice tiré du bac NSI Amérique du Nord 2024 (jour 2), sur SQL : la base de données d'un pharmacien.
client(id_client, nom_client, prenom_client, num_secu_sociale) : (1, Martin, Sophie, 202103812326129), (2, Dufour, Marc, 105073817009595).
1. Résultat de SELECT nom_client, prenom_client FROM client ORDER BY nom_client; ?
medicament(id_medic, nom_medic, categorie, conditionnement, quantite, prix) : (1, Paracétamol 1g CP, antalgique, 8, 50, 3.50), (2, Acide acétylsalicylique, antalgique, 8, 20, 2.30), (3, Gel hydroalcoolique 100ml, désinfectant, 1, 300, 2.30), (4, Acide ascorbique, vitamine, 10, 450, 5.50).
2. Requête affichant les noms des médicaments de prix strictement inférieur à 3 €.
Ordonnance de Sophie Martin : Paracétamol 1g CP (boîte de 8), max 3cp/jour pendant 2 jours ; Acide ascorbique (boîte de 10), 1cp/jour pendant 4 semaines. ordonnance(id_ordo, id_client, date_ordo, id_medic, nb_boites) : (6, 2, 2023-11-29, 2, 2), (7, 1, 2023-12-13, 1, ?), (8, 1, 2023-12-13, 4, ?).
3. Requête ajoutant la cliente Nathalie Durand (id_client=3, carte Vitale 2 69 05 49 588 157 80).
4. Attributs clés étrangères de ordonnance, et leur utilité.
5. Nombre de boîtes des lignes 7 et 8, en justifiant à partir du conditionnement et de la posologie.
6. Requête mettant à jour le stock d'Acide ascorbique.
7. Coût total des médicaments fournis à Mme Martin (calcul justifié, sans requête).
8. Requête affichant le nom du médicament de l'ordonnance n°6.
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — Amérique du Nord 2024 J1 (exercice 3)
Exercice tiré du bac NSI Amérique du Nord 2024 (jour 1), sur les flashcards et la base de données des boîtes de Leitner.
Partie A. Une étudiante stocke ses flashcards dans flashcards.csv (colonnes discipline, chapitre, question, réponse), avec un séparateur qui n'est pas la virgule.
- Donner ce séparateur. 2. Justifier ce choix (indice : certaines réponses contiennent elles-mêmes des virgules).
Code (voir le corrigé pour le détail) : charger(nom_fichier) lit le CSV via csv.DictReader et renvoie une liste de dictionnaires ; choix_discipline/choix_chapitre proposent un choix interactif ; entrainement affiche question puis, après une pause, réponse.
- Compléter
charger(nom_fichier). 4. Quelle méthode du moduletimeest utilisée ? 5. Type dedonnees[i]? 6. Compléter les lignes finales (chargement puis appel des trois fonctions).
Partie B. Boîtes de Leitner : 5 boîtes, fréquences 1, 2, 4, 8, 15 jours. Base à 4 tables discipline, chapitre, boite(id, lib, frequence), flashcard(id, id_ch, id_boite, question, reponse, date_interro). La table boite contient déjà les boîtes 1 à 4.
- Requête ajoutant la boîte 5 ('tous les quinze jours', fréquence 15).
Une requête sur flashcard affiche : 5, 2, 1, Pearl Harbor - date, 6 decembre 1941 (id, id_ch, id_boite, question, reponse) — la réponse comporte une erreur, la bonne date étant le 7 décembre 1941.
- Requête corrigeant cette réponse. 9. Requête donnant les libellés des disciplines. 10. Requête donnant les libellés des chapitres de la discipline 'histoire'. 11. Requête donnant les identifiants des flashcards de la discipline 'histoire'. 12. Requête supprimant toutes les flashcards de la boîte d'identifiant 3.
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — Amérique du Nord 2025 (exercice 3, partie SQL)
Exercice 3 (8 points, partie base de données) du sujet de bac NSI Amérique du Nord 2025, jour 1.
Une association d'enfants (0-18 ans) veut former des groupes d'enfants qui s'entendent durant les activités, à partir d'une base de données à trois tables :
- parent :
nom,tel(numéro de téléphone),codep(code postal) ; - enfant :
id,prenom,num_parent(téléphone du parent référent, un seul par enfant),annee(année de naissance) ; - mesentente :
enfant1,enfant2— deux identifiants d'enfants qui ne peuvent pas sortir ensemble.
num_parent de enfant est une clé étrangère référençant tel de parent.
Extrait de la table enfant :
| id | prenom | num_parent | annee |
|---|---|---|---|
| 2 | 'Hawa' | 33619911212 | 2012 |
| 3 | 'Adrien' | 33619861232 | 2013 |
| 6 | 'Kian' | 33619834521 | 2012 |
| 8 | 'Gabin' | 33619847852 | 2014 |
| 12 | 'Nakamura' | 33619732453 | 2009 |
| 14 | 'Maya' | 33600782153 | 2017 |
| 17 | 'Olivier' | 33619868564 | 2017 |
| 21 | 'Tess' | 33619835876 | 2016 |
| 23 | 'Rachelle' | 33600785482 | 2023 |
- Donner le type de l'attribut
annee. - Quelle contrainte de domaine supplémentaire serait pertinente pour
annee? - Donner un attribut de enfant qui suit une contrainte de référence.
- Proposer, en justifiant, une clé primaire pour parent.
Suite à une erreur de saisie, le vrai téléphone d'un parent (33619782812) a été transformé en 33600782812. On tente de corriger avec UPDATE parent SET tel = 33619782812 WHERE tel = 33600782812; — cette requête lève une erreur.
- Expliquer pourquoi.
- Recopier et compléter cette suite de commandes, qui corrige le téléphone du parent nommé
'Bauges'(code postal 73340, téléphone erroné 33600782812, vrai téléphone 33619782812) :
INSERT INTO parent VALUES ('Bauges', 33619782812, 73340);
UPDATE enfant SET num_parent = ... WHERE num_parent = ...;
DELETE FROM parent WHERE tel = ...;- D'après la table enfant fournie, donner le résultat de
SELECT prenom FROM enfant WHERE annee < 2014 ORDER BY annee; - Proposer une requête donnant, par ordre alphabétique, les prénoms des enfants du parent de téléphone 3619861122.
- Proposer une requête donnant les identifiants et prénoms des enfants dont le parent habite au code postal 38520.
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — 25-NSIPE2 (exercice 3, partie SQL)
Exercice 3 (8 points, partie base de données) du sujet de bac NSI 25-NSIPE2, session 2025.
Les visiteurs volontaires reçoivent un bracelet magnétique permettant de les identifier et de les photographier à des points clés du parc ; les photos leur sont proposées à la vente. Les données personnelles sont stockées en France, avec droit de consultation, retrait et rectification.
Trois relations : visiteur(id : int, nom : text, prenom : text, date : text) — date au format 'AAAA-MM-JJ' ; photo(id : int, #id_visiteur : int, #id_attraction : int, heure : text, prix : float) — heure au format 'HH:MM' ; attraction(id : int, nom : text, duree : int).
Les opérateurs de comparaison classiques s'appliquent aussi aux chaînes de caractères (ex. '2025-01-01' > '2024-01-01' est vrai). SUM(prix) renvoie la somme des valeurs de prix.
- Expliquer ce qu'est une clé primaire, puis ce qu'est une clé étrangère.
- Écrire une requête donnant les noms et prénoms (sans doublons) des visiteurs présents le 11 janvier 2025.
Un visiteur, Alan TURING, est venu plusieurs fois en 2024 et a, à chaque fois, acheté toutes les photos proposées.
- Écrire une requête donnant la somme totale payée par Alan TURING pour des photos au parc en 2024.
Suite à un problème technique, les gérants ont utilisé :
SELECT visiteur.nom, prenom
FROM visiteur JOIN photo ON visiteur.id = photo.id_visiteur
JOIN attraction ON attraction.id = photo.id_attraction
WHERE attraction.nom = 'Grande roue'
AND heure = '12:34'
AND date = '2024-07-26';- Expliquer ce qu'ils voulaient savoir.
- Le parc veut proposer, pour un même cliché, plusieurs formats et supports (A5, A6, poster, porte-clé…). Proposer des modifications de la base de données pour prendre en charge cette nouvelle offre.
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — Centres étrangers 2024 J1 (exercice 3, partie SQL)
Exercice 3 (8 points, partie base de données) du sujet de bac NSI Centres étrangers (groupe 1) 2024, jour 1.
L'objectif est de faciliter la gestion du système d'information d'un camping municipal, dont les informations sont stockées dans une base de données relationnelle à trois relations.
Client(id_client, nom, prenom, adresse, ville, pays, telephone)
Reservation(id_reservation, #id_client, #id_emplacement, nombre_personne, date_arrivee, date_depart)
La troisième relation, Emplacement, contient tous les emplacements du camping. Extrait :
| id_emplacement | nom | localisation | tarif_journalier |
|---|---|---|---|
| 1 | myrtille | A4 | 25 |
| 2 | mirabelle | D1 | 35 |
| 3 | mangue | B2 | 29.90 |
| 4 | mandarine | B1 | 25 |
| 5 | mûre | C3 | 29.90 |
| 6 | melon | A2 | 25 |
- Citer deux avantages à utiliser une base de données relationnelle plutôt qu'un fichier texte ou tableur.
- Quelle doit être la caractéristique d'un attribut pour pouvoir être utilisé comme clé primaire ?
- Dans
Reservation, quel est le rôle des clés étrangèresid_clientetid_emplacement? - Donner le schéma relationnel de
Emplacement, en précisant la clé primaire et le type de chaque attribut. - À partir de l'extrait donné, donner le résultat de :
SELECT id_emplacement, nom, localisation
FROM Emplacement
WHERE tarif_journalier = 25;- Écrire une requête donnant le nom et le prénom de tous les clients habitant à 'Strasbourg'.
- Écrire une requête ajoutant un nouveau client :
id_client42, nom 'CODD', prénom 'Edgar', adresse '28 rue des Capucines', ville 'Lyon', pays 'France', téléphone '0555555555'. - Écrire une requête SQL récupérant, pour la réservation
id_reservation = 18:Client.nom,Client.prenom,Reservation.nombre_personne,Reservation.date_arrivee,Reservation.date_depart,Emplacement.tarif_journalier.
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — Polynésie 2023 J2 (exercice 2)
Exercice 2 (4 points) du sujet de bac NSI Polynésie 2023, jour 2.
Un site permet à ses membres de proposer et de louer du matériel. Modèle relationnel : Membre(id_membre, nom, prenom, cp), Objet(id_objet, description, tarif), Reservation(id_reservation, id_objet, id_membre, date_location, date_retour), Possede(id_membre, id_objet) — clé primaire de Possede : le couple (id_membre, id_objet).
Contenu : Membre : (1, "Ali", "Mohamed", "69110") ; (2, "Alonso", "Fernando", "69005") ; (3, "Dupont", "Antoine", "69003") ; (4, "Ferrand", "Pauline", "69160") ; (5, "Kane", "Harry", "69003"). Possede : (1,4), (1,6), (2,4), (3,3), (3,5), (4,1), (4,2). Objet : (1, "Nettoyeur haute pression", 20) ; (2, "Taille-haie", 15) ; (3, "Perforatrice", 15) ; (4, "Appareil à raclette", 10) ; (5, "Scie circulaire", 15) ; (6, "Appareil à gaufre", 10). Reservation : (1,4,5,2022-02-18,2022-02-19) ; (2,1,2,2022-05-05,2022-05-06) ; (3,3,1,2022-07-10,2022-07-12) ; (4,3,1,2022-08-12,2022-08-14) ; (5,2,2,2022-10-20,2022-10-22) ; (6,2,2,2022-10-20,2022-10-22).
- Sans écrire de requête SQL, en étudiant les tables : a. Indiquer les prénoms et noms du ou des membres qui proposent la location d'un appareil à raclette. b. Donner le prénom et le nom du membre qui ne propose aucun objet à la location.
- a. Donner le résultat de
SELECT nom, prenom FROM Membre WHERE cp = "69003";b. Écrire une requête donnant le tarif de location d'une scie circulaire. c. Écrire une requête modifiant le tarif de location d'un nettoyeur à haute pression, désormais 15 € par jour. d. Écrire une requête ajoutant Wendie Renard, habitant à Villeurbanne (code postal 69100), dans Membre, avecid_membre6. - a. Expliquer la limitation importante que poserait le couple (
id_objet,id_membre) comme clé primaire de Reservation. b. Mohamed Ali quitte le site. On tenteDELETE FROM Membre WHERE nom = "Ali" AND prenom ="Mohamed";: cette requête produit une erreur. Expliquer pourquoi. c. Proposer une suite de requêtes utilisantDELETE, précédant la requête ci-dessus, pour supprimer correctement Mohamed Ali (id_membre1) de la base. - Ces requêtes utilisent des jointures (
id_membreetid_objetsupposés non connus) : a. Écrire une requête comptant le nombre de réservations réalisées par Fernando Alonso. b. Écrire une requête donnant les noms et prénoms des membres possédant un appareil à raclette.
Créez un compte gratuit : votre première correction est offerte.
Exercice — Bac NSI — Polynésie 2023 J1, extrait partiel (SQL)
Extrait partiel du sujet de bac NSI Polynésie 2023, jour 1 (23-NSIJ1PO1) — Exercice 1 uniquement (bases de données relationnelles et SQL), reconstitué à partir de 4 photos de téléphone couvrant les pages 2 à 4 sur 11 du sujet complet. Les 4 autres exercices du sujet ne sont pas couverts par ces photos et ne sont donc pas retranscrits ici.
La ligue féminine de basket-ball publie les données de chaque saison sur son site web : équipes participantes, calendriers, résultats des matchs, statistiques des joueuses. On s'intéresse à la base relationnelle LFB_2021_2022, qui stocke les données de la saison régulière 2021-2022.
1. La table Equipe
Contenu intégral de la table Equipe (extrait) :
| id_equipe | nom | telephone |
|---|---|---|
| 1 | Saint-Amand | 03 04 05 06 07 |
| 2 | Basket Landes | 05 06 07 08 09 |
| 3 | Villeneuve d'Ascq | 03 02 01 00 01 |
| 4 | Tarbe | 05 04 03 02 02 |
| 5 | Lyon | 04 05 06 07 08 |
| 6 | Bourges | 02 03 04 05 06 |
| 7 | Charleville-Mézières | 03 05 07 09 01 |
| 8 | Landerneau | 02 04 06 08 00 |
| 9 | Angers | 02 00 08 06 04 |
| 10 | Lattes Montpellier | 04 03 02 01 00 |
| 11 | Charnay | 03 01 09 07 05 |
| 12 | Roche Vendée | 02 05 08 01 04 |
(la colonne adresse, également présente dans la table, est omise ici par souci de concision — elle n'intervient dans aucune des questions ci-dessous)
Schéma relationnel de Equipe (attribut souligné = clé primaire) :
Equipe(id_equipe INT, nom VARCHAR(50), adresse VARCHAR(100), telephone VARCHAR(20)), clé primaire id_equipe.
a. Après le chargement de la table Equipe, expliquer pourquoi la requête suivante produit une erreur :
INSERT INTO Equipe
VALUES (11, "Toulouse", "2 rue du Nord,40100 Dax", "05 04 03 02 01");b. Expliquer le choix du domaine (type) pour l'attribut telephone.
c. Donner le résultat de la requête suivante :
SELECT nom, adresse, telephone FROM Equipe WHERE id_equipe = 5;d. Donner et expliquer le résultat de la requête suivante :
SELECT COUNT(*) FROM Equipe;e. Écrire la requête SQL permettant d'afficher les noms des équipes par ordre alphabétique.
f. Écrire la requête SQL permettant de corriger le nom de l'équipe dont l'id_equipe est égal à 4. Le nom correct est "Tarbes".
2. La table Joueuse
Sur le site web de la fédération, une page « Fiche Joueuse » présente, pour chaque joueuse, son nom, sa date de naissance, sa taille et son poste. Extrait de la table Joueuse :
| id_joueuse | nom | prenom | id_equipe |
|---|---|---|---|
| 1 | Berkani | Lisa | 7 |
| 2 | Alexander | Kayla | 5 |
| 6 | Sigmundova | Jodie Cornelie | 9 |
| 7 | Dumerc | Céline | 2 |
| 8 | Slonjsak | Iva | 9 |
| 9 | Michel | Sarah | 6 |
| 10 | Lithard | Pauline | 1 |
(colonnes date_naissance, taille, poste omises ici, non nécessaires aux questions ci-dessous)
Schéma relationnel de Joueuse (# = clé étrangère) : Joueuse(id_joueuse INT, nom VARCHAR(50), prenom VARCHAR(50), date_naissance DATE, taille INT, poste INT, #id_equipe INT), clé primaire id_joueuse. La clé étrangère Joueuse.id_equipe référence la clé primaire Equipe.id_equipe.
a. Expliquer pourquoi l'attribut id_equipe a été déclaré clé étrangère.
b. On souhaite supprimer toutes les informations relatives à une équipe. Expliquer pourquoi on ne peut pas directement supprimer cette équipe dans la table Equipe.
c. Écrire la requête SQL qui permet d'afficher les noms et prénoms des joueuses de l'équipe d'Angers, par ordre alphabétique des noms. On suppose que l'utilisateur qui écrit cette requête ne connaît pas l'identifiant de l'équipe d'Angers.
3. La table Match
Les résultats des matchs sont aussi publiés sur le site de la ligue. Exemple, pour le match n°10, qui a opposé Villeneuve d'Ascq à Bourges le 23/10/2021 : Villeneuve d'Ascq (à domicile) 73 points, Bourges (en déplacement) 78 points.
a. À partir de cet exemple, proposer un schéma relationnel pour la table Match. Si des clés étrangères sont définies, préciser quelles tables et quels attributs elles référencent.
b. Écrire la requête SQL qui permet l'insertion dans la table Match de l'enregistrement correspondant à cet exemple.
4. Statistiques des joueuses par match
En plus du score final, la page web affiche des statistiques par joueuse pour chaque match, restreintes à 3 critères : points marqués, rebonds, passes décisives. Extrait pour le match n°53 (Landerneau 56 − 64 Charleville-Mézières, le 16/04/2022) :
| Equipe | Nom | Prenom | Points | Rebonds | Passes décisives |
|---|---|---|---|---|---|
| Charleville-Mézières | Pouye | Tima | 18 | 6 | 2 |
| Charleville-Mézières | Akhator | Evelyn | 15 | 17 | 0 |
| Landerneau | Mane | Marie | 18 | 2 | 3 |
| Landerneau | Amukamara | Promise | 12 | 2 | 5 |
a. Proposer un schéma relationnel pour stocker, dans la base de données, les informations de statistiques des joueuses telles que présentées ci-dessus.
b. Écrire la requête SQL qui a été utilisée pour afficher la partie « Extrait des statistiques » de l'exemple ci-dessus.
Exercice — Requêtes sur la base d'un service hospitalier
D'après une fiche d'exercices de NSI Terminale.
Un service hospitalier gère sa base avec trois tables :
Patients(idINT,nomTEXT,prenomTEXT,genreTEXT,annee_naissanceINT) ;Medecins(matriculeINT,nom_prenomTEXT,specialiteTEXT,telephoneTEXT) ;Ordonnances(codeINT,id_patientINT,matricule_medecinINT,date_ordTEXT,medicamentsTEXT).
Une ordonnance est rédigée par un médecin pour un patient. Les dates sont écrites sous la forme jj-mm-aaaa.
- Écrire le schéma relationnel de la table
Ordonnances, en soulignant la clé primaire et en marquant les clés étrangères d'un #. - Écrire les requêtes de création des trois tables.
- Enregistrer la patiente Inès Benali, née en 2005, sous le numéro 1. L'accueil voudrait aussi enregistrer son adresse : est-ce possible ?
- Le patient numéro 100 a changé de prénom : il s'appelle désormais Alix. Écrire la requête correspondante.
- Le service se sépare des médecins spécialisés en épidémiologie. Écrire la requête qui supprime leurs fiches. Que risque-t-il de se passer, et comment y remédier ?
- Donner la requête qui liste les patients (nom et prénom, sans doublon) qui ont reçu une ordonnance d'un psychiatre en avril 2020.
Exercice — Requêtes sur le stock d'un supermarché
D'après une fiche d'exercices de NSI Terminale.
Le stock d'un supermarché est géré avec trois tables :
Fournisseurs(id,nom,adresse,cp,ville,telephone,courriel,responsable) ;Produits(id,nom_court,nom,prix_achat,prix_vente,fournisseur), oùfournisseurfait référence àFournisseurs.id;Stocks(id,produit,quantite,date_peremption), oùproduitfait référence àProduits.id; les dates sont au formataaaa-mm-jj.
Écrire les requêtes qui donnent :
- le prix d'achat du produit dont le nom court est
Liq_Vaiss_1L; - l'adresse, le code postal et la ville du fournisseur nommé
Avenir_confiseur; - le nom des produits en rupture de stock ;
- le nom de toutes les ampoules vendues (leur nom contient le mot « ampoule ») ;
- le prix de vente moyen de ces ampoules ;
- le nom du produit le plus cher du magasin ;
- le nom des produits dont la date de péremption est dépassée.
Exercice — Épreuve pratique NSI 2026 — Sujet 15 : rappels de vaccination d'un cabinet vétérinaire
Banque nationale de sujets 2026 de l'épreuve pratique, sujet n°15 (situation d'évaluation d'une heure).
Rappels de vaccination d'un cabinet vétérinaire
Cadre. Un cabinet vétérinaire utilise une base de données pour assurer le suivi et la gestion des clients et animaux qui y sont suivis, dans le but d'améliorer la qualité des soins et de fournir des services utiles, que ce soit pour le vétérinaire ou pour ses clients.
Objectif. La vaccination régulière des chats (une fois par an) étant importante mais souvent oubliée par les propriétaires, le vétérinaire souhaiterait pouvoir envoyer des messages de rappel de vaccination par SMS, deux mois avant l'échéance (la date à laquelle la vaccination devrait avoir lieu). Il dispose pour cela d'une plateforme d'envoi de SMS, mais il est nécessaire de préparer les données et les messages à envoyer.
Description de la base de données
Le logiciel mis en œuvre par le cabinet utilise 3 tables pour enregistrer les animaux, leur propriétaire et les consultations. Schéma de la base de données :
- consultation (id : int, id_animal : int, date : str (AAAAMMJJ), motif : str) — clé primaire
id, clé étrangèreid_animal; - animal (id : int, espece : str, nom : str, date_naissance : str (AAAAMMJJ), id_proprietaire : int) — clé primaire
id, clé étrangèreid_proprietaire; - proprietaire (id : int, nom : str, prenom : str, telephone : str) — clé primaire
id.
consultation.id_animal fait référence à animal.id, et animal.id_proprietaire à proprietaire.id.
Extraits de la base de données :
| id | nom | prenom | telephone |
|---|---|---|---|
| 1 | Duhamel | François | 06-57-84-52-41 |
| 2 | Dumont | Marcelle | 0648747223 |
| 3 | Joubert | Anouk | 0 4 76 33 78 15 |
| id | id_animal | date | motif |
|---|---|---|---|
| 1 | 1 | 20171229 | vaccination |
| 25 | 4 | 20050621 | bilan |
| 34 | 5 | 20131106 | maladie |
| id | espece | nom | date_naissance | id_proprietaire |
|---|---|---|---|---|
| 1 | oiseau | Flocon | 20171111 | 1 |
| 2 | lapin | Roudoudou | 20210901 | 2 |
| 3 | chat | Mistral | 20251206 | 2 |
Le système de gestion de base de données utilisé est SQLite, et il est possible d'interagir avec la base de données en utilisant le module sqlite3, disponible dans la bibliothèque standard Python.
Rappels techniques
La connexion à la base de données se fait en précisant l'emplacement du fichier de la base de données. Par exemple, si le fichier cabinet.sqlite se trouve dans le répertoire courant, on écrit :
DB_PATH = "cabinet.sqlite"
conn = sqlite3.connect(DB_PATH)Une fois que l'on dispose d'une connexion (variable conn), on utilise un curseur (variable cursor) pour exécuter des requêtes sur la base de données et éventuellement récupérer les résultats de la requête.
cursor = conn.cursor()
resultats = cursor.execute(
"SELECT id, nom FROM animal ORDER BY nom LIMIT 10"
)
# resultats permet de récupérer les lignes de manière
# progressive, sous forme d'une liste itérable de tuples
# correspondant aux champs demandés
# Pour accéder aux champs sélectionnés
for r in resultats:
# les valeurs renvoyées par le SELECT sont
# accessibles par leur position
print("id:", r[0], ", nom:", r[1])Lorsqu'un paramètre doit être donné dans une requête SQL, il est fourni sous forme d'un ? dans le texte de la requête SQL, et passé en argument à la fonction execute sous forme d'un tuple (chaque ? correspond à un élément du tuple, dans l'ordre). Par exemple, pour récupérer les chats du propriétaire d'id 2 :
resultat = cursor.execute(
"""SELECT nom FROM animal
WHERE espece = 'chat' AND id_proprietaire = ?""",
(2,)
)Les clauses du langage SQL à utiliser sont : SELECT, FROM, JOIN, ON, WHERE, ORDER BY.
Numéros de téléphone
La plateforme d'envoi de SMS requiert un numéro de téléphone au format 06XXXXXXXX ou 07XXXXXXXX, 10 chiffres au total, sans espace, ni point, ni autre caractère. Malheureusement, les téléphones ont été enregistrés dans la base sans distinguer les téléphones mobiles des téléphones fixes, et en utilisant différents styles comme « (0)6 12 34 56 78 » ou « 01.23.45.67.89 ».
Rappel : on peut utiliser la méthode isdigit de la classe str pour déterminer si un caractère est un chiffre.
>>> '2'.isdigit()
True
>>> 'C'.isdigit()
FalseQuestion 1. Écrire une fonction Python normalisation_tel qui prend un numéro de téléphone tel de type str en argument et qui renvoie le numéro de téléphone nettoyé en ne gardant que les chiffres. Exemples :
normalisation_tel("(0)2 12 99 90 12") # renvoie "0212999012"
normalisation_tel("0.6.12.99.90.12") # renvoie "0612999012"
normalisation_tel("0-6-12-9-90-1") # renvoie "06129901"Une fonction test_normalisation_tel est fournie.
Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.
Validation des numéros de téléphone
La fonction validation_tel(tel) prend comme argument un numéro de téléphone nettoyé, et renvoie un booléen selon que ce numéro est un numéro de téléphone portable valide ou non.
Question 2. Écrire un jeu de tests permettant de vérifier le bon fonctionnement de la fonction.
Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.
Détermination de la liste des chats à vacciner
La vaccination se faisant tous les ans, le vétérinaire souhaite envoyer trois rappels aux propriétaires. Chaque rappel sera donc envoyé aux propriétaires des chats ayant été vaccinés pour la dernière fois il y a entre 10 et 13 mois. Pour cela on commencera par déterminer quels chats ont été vaccinés il y a moins de 13 mois, à l'aide de la fonction consultation_vaccination_chat(date). Puis à l'aide de la fonction derniere_vaccination(consultations), on déterminera la date de dernière vaccination de ces chats. Enfin, dans la dernière étape du projet, se fera le filtrage des chats ayant été vaccinés pour la dernière fois il y a plus de 10 mois.
Interrogation de la base de données. Pour interroger la base de données, on utilise la fonction consultation_vaccination_chat(date) qui doit récupérer toutes les consultations de motif vaccination des chats (espèce : chat) du cabinet, pour des dates supérieures à une date date exprimée au format AAAAMMJJ (ce format permet de comparer des dates en utilisant l'ordre alphabétique). On souhaite récupérer les champs suivants : id de l'animal, nom de l'animal, téléphone du propriétaire, date de la consultation, triés par le champ id d'animal puis date de consultation croissants.
Question 3. En vous inspirant de la fonction proprietaires_animaux_nes_apres(date), écrire la fonction consultation_vaccination_chat(date). Des tests sont fournis dans la fonction test_consultation_vaccination_chat ; votre fonction doit les passer.
Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.
Détermination de la date de dernière vaccination. Pour déterminer la date de dernière vaccination, on utilise la fonction derniere_vaccination qui prend en paramètre une liste de consultations avec les champs précédents (id de l'animal, nom de l'animal, téléphone du propriétaire, date de la consultation). Elle renvoie un dictionnaire associant comme clé l'id de chaque chat avec les informations de sa dernière (plus récente) consultation.
Exemple : pour Plume et Gollum,
(16, 'Plume', '0.6.36.96.89.83', '20241024'),
(16, 'Plume', '0.6.36.96.89.83', '20251125'),
(17, 'Gollum', '0.6.36.96.89.83', '20250113'),la dernière consultation de Plume est le 20251125, et pour Gollum, c'est le 20250113 : derniere_vaccination doit donc renvoyer le dictionnaire
{
16: (16, 'Plume', '0.6.36.96.89.83', '20251125'),
17: (17, 'Gollum', '0.6.36.96.89.83', '20250113')
}Cependant, la fonction ne produit pas les résultats attendus : les tests fournis dans la fonction test_derniere_vaccination échouent.
Question 4. Expliquer le problème rencontré, puis comment corriger cette fonction pour qu'elle passe les tests avec succès.
Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.
Fichiers fournis
Le dossier comporte une version PDF de l'énoncé, le code source de départ veto.py et la base de données cabinet.sqlite (400 propriétaires, 411 animaux, 4 457 consultations). Le module sqlite3 doit être disponible.
veto.py
# -----------------------------------------------------------------------------
# Numéros de téléphones
# Question 1 : nettoyage des numéros de téléphone
# Écrire la fonction normalisation_tel ici
import sqlite3
def test_normalisation_tel():
"""
Tous les tests doivent passer...
"""
assert normalisation_tel("06 12 99 90 12") == "0612999012"
assert normalisation_tel("02 12 99 90 12") == "0212999012"
assert normalisation_tel("02.12.99.90.12") == "0212999012"
assert normalisation_tel("0.6.12.99.90.12") == "0612999012"
assert normalisation_tel("06-12-99-90-12") == "0612999012"
assert normalisation_tel("(0)6.12.99-90-12 gilbert") == "0612999012"
assert normalisation_tel("061299901") == "061299901"
assert normalisation_tel("06129990123") == "06129990123"
print('Les tests de la fonction normalisation_tel sont passés')
# -----------------------------------------------------------------------------
# Question 2 : validation des numéros de téléphone
def validation_tel(tel):
"""
Validation des numéros de téléphone portable français
selon les conditions spécifiées.
:param tel: numéro de téléphone
:return: True si le numéro est valide, False sinon
"""
if len(tel) != 10:
return False
if tel[0] != "0":
return False
if tel[1] != "6" and tel[1] != "7":
return False
return True
# Ecrire votre jeu de tests permettant
# de vérifier le bon fonctionnement de la fonction.
# -----------------------------------------------------------------------------
# Détermination de la liste des chats à vacciner
# Question 3 : interrogation de la base de données
DB_PATH = "cabinet.sqlite"
def proprietaires_animaux_nes_apres(date):
"""
Renvoie les noms et prénoms des propriétaires d'animaux nés après la date `date`,
triés par ordre alphabétique de noms puis prénoms
:param: date: date de naissance minimale
:return: liste [(nom_proprietaire, prenom_ proprietaire)]
"""
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
resultat = cursor.execute(
"""
SELECT proprietaire.nom, proprietaire.prenom
FROM proprietaire
JOIN animal ON proprietaire.id = animal.id_proprietaire
WHERE animal.date_naissance > ?
ORDER BY proprietaire.nom, proprietaire.prenom;
""",
(date,),
)
return list(resultat)
def consultation_vaccination_chat(date):
"""
Renvoie les consultations de vaccination de chats dont la date
est supérieure à la date `date`.
:param: date: date minimale
:return: liste [(id_animal, nom_animal, tel_proprietaire, date_consultation)]
"""
pass
def test_consultation_vaccination_chat():
vaccinations = consultation_vaccination_chat("20240923")
assert len(vaccinations) == 118
assert vaccinations[0] == (16, "Plume", "0.6.36.96.89.83", "20241024")
assert vaccinations[1] == (16, "Plume", "0.6.36.96.89.83", "20251125")
assert vaccinations[2] == (17, "Gollum", "0.6.36.96.89.83", "20250113")
assert vaccinations[3] == (26, "Olympe", "(0)4 73 98 01 23", "20250109")
assert vaccinations[4] == (32, "Chopin", "06.37.97.66.64", "20241201")
assert vaccinations[5] == (32, "Chopin", "06.37.97.66.64", "20251119")
assert vaccinations[6] == (34, "Jazz", "0.6.37.51.65.52", "20250801")
assert vaccinations[7] == (35, "Tango", "0324182", "20250706")
assert vaccinations[8] == (38, "Loulou", "05-35-95-87-54", "20250209")
# Vérification stricte du tri (ORDER BY id_animal, date_consultation)
assert vaccinations == sorted(vaccinations, key=lambda x: (x[0], x[3]))
print('Les tests de la fonction consultation_vaccination_chat sont passés')
# test_consultation_vaccination_chat()
# -----------------------------------------------------------------------------
# Question 4 : détermination de la date de dernière vaccination
def derniere_vaccination(consultations):
"""
Renvoie un dictionnaire ayant pour clef l'identifiant de l'animal,
et dont la valeur associée est la dernière consultation de cet animal.
Chaque consultation est un tuple :
(id_animal, nom_animal, tel_proprietaire, date_consultation)
"""
derniere = {}
for consult in consultations:
id_animal = consult[0]
date = consult[3]
if id_animal not in derniere:
derniere[id_animal] = consult
elif date < derniere[id_animal][3]:
derniere[id_animal] = consult
return derniere
def test_derniere_vaccination():
consultations_pour_test = [
(16, "Plume", "0.6.36.96.89.83", "20241024"),
(16, "Plume", "0.6.36.96.89.83", "20251125"),
(17, "Gollum", "0.6.36.96.89.83", "20250113"),
(26, "Olympe", "(0)4 73 98 01 23", "20250109"),
(32, "Chopin", "06.37.97.66.64", "20241201"),
(32, "Chopin", "06.37.97.66.64", "20251119"),
(34, "Jazz", "0.6.37.51.65.52", "20250801"),
(35, "Tango", "0324182", "20250706"),
(38, "Loulou", "05-35-95-87-54", "20250209"),
(39, "Tango", "07.45.48.02.42", "20250329"),
(40, "Sésame", "07.45.48.02.42", "20250228"),
(41, "Pixel", "0130709285", "20241204"),
(41, "Pixel", "0130709285", "20251222"),
]
resultat = derniere_vaccination(consultations_pour_test)
# Affichage des résultats, décommenter si besoin
# for a,r in resultat.items():
# print(a, ":", r)
assert derniere_vaccination(consultations_pour_test) == {
16: (16, "Plume", "0.6.36.96.89.83", "20251125"),
17: (17, "Gollum", "0.6.36.96.89.83", "20250113"),
26: (26, "Olympe", "(0)4 73 98 01 23", "20250109"),
32: (32, "Chopin", "06.37.97.66.64", "20251119"),
34: (34, "Jazz", "0.6.37.51.65.52", "20250801"),
35: (35, "Tango", "0324182", "20250706"),
38: (38, "Loulou", "05-35-95-87-54", "20250209"),
39: (39, "Tango", "07.45.48.02.42", "20250329"),
40: (40, "Sésame", "07.45.48.02.42", "20250228"),
41: (41, "Pixel", "0130709285", "20251222"),
}
print('Les tests de la fonction derniere_vaccination sont passés')Créez un compte gratuit : votre première correction est offerte.
QCM — Langage SQL
Exercices bilan
Lire le schéma relationnel d'une médiathèque
La médiathèque d'un lycée gère son fonds et ses prêts dans une base de données relationnelle composée de quatre tables. On donne ci-dessous un extrait de leur contenu.
Table Auteurs
| id_auteur | nom | nationalite |
|---|---|---|
| 1 | Hugo | Française |
| 2 | Christie | Britannique |
| 3 | Senghor | Sénégalaise |
| 4 | Verne | Française |
| 5 | Orwell | Britannique |
Table Livres
| id_livre | titre | annee | id_auteur |
|---|---|---|---|
| 1 | Les Misérables | 1862 | 1 |
| 2 | Notre-Dame de Paris | 1831 | 1 |
| 3 | Mort sur le Nil | 1937 | 2 |
| 4 | Le Crime de Roger Ackroyd | 1926 | 2 |
| 5 | Éthiopiques | 1956 | 3 |
| 6 | Vingt mille lieues sous les mers | 1870 | 4 |
| 7 | Le Tour du monde en quatre-vingts jours | 1873 | 4 |
| 8 | 1984 | 1949 | 5 |
Table Adherents
| id_adherent | nom | classe |
|---|---|---|
| 1 | Amina | 1G1 |
| 2 | Karim | TG2 |
| 3 | Lina | TG2 |
| 4 | Youssef | 2D |
Table Emprunts
| id_emprunt | id_adherent | id_livre | date_emprunt | date_retour |
|---|---|---|---|---|
| 1 | 1 | 3 | 2025-09-08 | 2025-09-22 |
| 2 | 2 | 1 | 2025-09-09 | (vide) |
| 3 | 1 | 8 | 2025-09-15 | (vide) |
Questions.
- Donner la clé primaire de chacune des quatre tables. Pour la table
Adherents, expliquer pourquoi l'attributnomne conviendrait pas comme clé primaire. - Citer toutes les clés étrangères de ce schéma, en précisant à chaque fois quelle table et quel attribut elles référencent.
- Donner un domaine plausible pour chacun des attributs de la table
Livres. - Le SGBD refuse chacune des trois insertions suivantes. Expliquer la raison du refus dans chaque cas.
INSERT INTO Livres (id_livre, titre, annee, id_auteur)
VALUES (3, 'Dix petits soldats', 1939, 2);
INSERT INTO Livres (id_livre, titre, annee, id_auteur)
VALUES (9, 'Sur la route', 1957, 12);
INSERT INTO Emprunts (id_emprunt, id_adherent, id_livre, date_emprunt, date_retour)
VALUES (4, 7, 5, '2025-09-20', NULL);- Un élève propose de tout regrouper dans une unique table
Pretcomportant les attributsnom_adherent,classe,titre,annee,nom_auteur,nationalite,date_emprunt. Donner deux anomalies concrètes que ce choix provoquerait sur cette médiathèque. - Deux services rendus par un SGBD sont particulièrement utiles ici. Les citer et illustrer chacun par une situation de la vie de la médiathèque.
Interroger le catalogue avec SELECT, WHERE et ORDER BY
On reprend les deux tables du catalogue de la médiathèque.
Table Auteurs
| id_auteur | nom | nationalite |
|---|---|---|
| 1 | Hugo | Française |
| 2 | Christie | Britannique |
| 3 | Senghor | Sénégalaise |
| 4 | Verne | Française |
| 5 | Orwell | Britannique |
Table Livres
| id_livre | titre | annee | id_auteur |
|---|---|---|---|
| 1 | Les Misérables | 1862 | 1 |
| 2 | Notre-Dame de Paris | 1831 | 1 |
| 3 | Mort sur le Nil | 1937 | 2 |
| 4 | Le Crime de Roger Ackroyd | 1926 | 2 |
| 5 | Éthiopiques | 1956 | 3 |
| 6 | Vingt mille lieues sous les mers | 1870 | 4 |
| 7 | Le Tour du monde en quatre-vingts jours | 1873 | 4 |
| 8 | 1984 | 1949 | 5 |
Partie 1 — lire une requête. Donner le résultat exact de chacune des requêtes suivantes, sous forme de tableau.
-- requete 1
SELECT titre FROM Livres WHERE annee < 1900;
-- requete 2
SELECT titre, annee FROM Livres
WHERE annee >= 1900 AND annee <= 1999
ORDER BY annee ASC;
-- requete 3
SELECT nom FROM Auteurs WHERE nationalite = 'Française';
-- requete 4
SELECT * FROM Livres WHERE annee = 1945;Partie 2 — écrire une requête. Rédiger la requête SQL qui renvoie :
- le titre et l'année des livres écrits par l'auteur d'identifiant , du plus ancien au plus récent ;
- le titre des livres parus avant ou après ;
- la nationalité des auteurs, sans afficher deux fois la même (chercher le mot-clé qui convient dans la documentation d'un SGBD, ou justifier pourquoi une simple projection ne suffit pas).
Partie 3 — comprendre.
- Expliquer la différence entre
SELECT *etSELECT titre. Comment appelle-t-on l'opération réalisée parSELECT titre, et celle réalisée par la clauseWHERE? - La requête 1 a été exécutée sans
ORDER BY. Peut-on garantir l'ordre dans lequel les lignes seront affichées ? Que faut-il écrire pour en être sûr ?
Créez un compte gratuit : votre première correction est offerte.
Croiser livres et auteurs à l'aide d'une jointure
On travaille toujours sur le catalogue de la médiathèque.
Table Auteurs
| id_auteur | nom | nationalite |
|---|---|---|
| 1 | Hugo | Française |
| 2 | Christie | Britannique |
| 3 | Senghor | Sénégalaise |
| 4 | Verne | Française |
| 5 | Orwell | Britannique |
Table Livres
| id_livre | titre | annee | id_auteur |
|---|---|---|---|
| 1 | Les Misérables | 1862 | 1 |
| 2 | Notre-Dame de Paris | 1831 | 1 |
| 3 | Mort sur le Nil | 1937 | 2 |
| 4 | Le Crime de Roger Ackroyd | 1926 | 2 |
| 5 | Éthiopiques | 1956 | 3 |
| 6 | Vingt mille lieues sous les mers | 1870 | 4 |
| 7 | Le Tour du monde en quatre-vingts jours | 1873 | 4 |
| 8 | 1984 | 1949 | 5 |
- Expliquer pourquoi la requête
SELECT titre, nom FROM Livres;ne peut pas fonctionner, alors que les deux colonnes demandées existent bien dans la base. - Donner le résultat exact de la requête suivante.
SELECT Livres.titre, Auteurs.nom
FROM Livres
JOIN Auteurs ON Livres.id_auteur = Auteurs.id_auteur;- Écrire la requête qui affiche le titre et le nom de l'auteur des livres écrits par un auteur de nationalité française, du plus ancien au plus récent. Donner son résultat.
- Écrire la requête qui affiche le nom de l'auteur, le titre et l'année des livres parus après et écrits par un auteur britannique, triés par année croissante. Donner son résultat.
- Un élève oublie la clause
ONet écritSELECT Livres.titre, Auteurs.nom FROM Livres, Auteurs;. La requête ne provoque pas d'erreur. Combien de lignes renvoie-t-elle, et pourquoi ce résultat n'a-t-il aucun sens ? - La médiathèque acquiert un ouvrage médiéval dont l'auteur est inconnu. On l'enregistre ainsi :
INSERT INTO Livres (id_livre, titre, annee, id_auteur)
VALUES (9, 'Le Roman de Renart', 1175, NULL);Cette insertion est acceptée par le SGBD, bien que id_auteur soit une clé étrangère. Après cette insertion, combien de lignes renvoie la requête de la question 2 ? Qu'en conclure sur le comportement d'une jointure vis-à-vis des valeurs manquantes ?
Mettre à jour le catalogue sans le casser
La médiathèque a été créée par les instructions suivantes, qui déclarent explicitement la contrainte de clé étrangère.
CREATE TABLE Auteurs (
id_auteur INTEGER PRIMARY KEY,
nom TEXT,
nationalite TEXT
);
CREATE TABLE Livres (
id_livre INTEGER PRIMARY KEY,
titre TEXT,
annee INTEGER,
id_auteur INTEGER,
FOREIGN KEY (id_auteur) REFERENCES Auteurs(id_auteur)
);Elle contient les auteurs et les livres des exercices précédents :
| id_livre | titre | annee | id_auteur |
|---|---|---|---|
| 1 | Les Misérables | 1862 | 1 |
| 2 | Notre-Dame de Paris | 1831 | 1 |
| 3 | Mort sur le Nil | 1937 | 2 |
| 4 | Le Crime de Roger Ackroyd | 1926 | 2 |
| 5 | Éthiopiques | 1956 | 3 |
| 6 | Vingt mille lieues sous les mers | 1870 | 4 |
| 7 | Le Tour du monde en quatre-vingts jours | 1873 | 4 |
| 8 | 1984 | 1949 | 5 |
(auteurs : 1 Hugo, 2 Christie, 3 Senghor, 4 Verne, 5 Orwell)
- La médiathèque acquiert Un barrage contre le Pacifique, paru en , de Marguerite Duras, de nationalité française, jusqu'ici absente de la base. Écrire les instructions SQL nécessaires. Préciser dans quel ordre elles doivent être exécutées et pourquoi.
- Une erreur de saisie s'est glissée : Les Misérables est paru en , mais la fiche indique . Écrire l'instruction qui corrige cette seule ligne.
- Le documentaliste veut supprimer du catalogue tous les livres parus avant . Écrire l'instruction, puis donner la liste des livres restants (en tenant compte de l'acquisition de la question 1).
- Expliquer précisément ce que fait l'instruction
UPDATE Livres SET annee = 1862;et pourquoi elle est redoutable. - On tente ensuite d'exécuter
DELETE FROM Auteurs WHERE id_auteur = 3;alors que Éthiopiques est toujours au catalogue. Le SGBD refuse. Expliquer pourquoi, puis proposer deux façons différentes de résoudre la situation. - Le documentaliste souhaite retirer un livre du catalogue mais garder la trace qu'il a existé. Expliquer pourquoi
DELETEne convient pas, et proposer une modification du schéma qui répond au besoin.
Créez un compte gratuit : votre première correction est offerte.
Compter les livres de chaque auteur avec GROUP BY
Jusqu'ici, nos requêtes renvoyaient des lignes de la base. On veut maintenant calculer des statistiques : un nombre de livres, une année minimale, une moyenne.
Rappel de cours. SQL propose des fonctions d'agrégation, qui résument plusieurs lignes en une seule valeur : COUNT(*) compte les lignes, MIN, MAX, SUM et AVG donnent respectivement le minimum, le maximum, la somme et la moyenne d'une colonne. La clause GROUP BY forme des paquets de lignes, et la fonction d'agrégation est alors appliquée à chaque paquet séparément. Enfin, HAVING filtre ces paquets, là où WHERE filtre les lignes avant le regroupement.
SELECT nationalite, COUNT(*) AS nombre
FROM Auteurs
GROUP BY nationalite;On travaille sur le catalogue habituel :
Table Auteurs
| id_auteur | nom | nationalite |
|---|---|---|
| 1 | Hugo | Française |
| 2 | Christie | Britannique |
| 3 | Senghor | Sénégalaise |
| 4 | Verne | Française |
| 5 | Orwell | Britannique |
Table Livres
| id_livre | titre | annee | id_auteur |
|---|---|---|---|
| 1 | Les Misérables | 1862 | 1 |
| 2 | Notre-Dame de Paris | 1831 | 1 |
| 3 | Mort sur le Nil | 1937 | 2 |
| 4 | Le Crime de Roger Ackroyd | 1926 | 2 |
| 5 | Éthiopiques | 1956 | 3 |
| 6 | Vingt mille lieues sous les mers | 1870 | 4 |
| 7 | Le Tour du monde en quatre-vingts jours | 1873 | 4 |
| 8 | 1984 | 1949 | 5 |
- Donner le résultat de la requête du rappel de cours ci-dessus.
- Donner le résultat de la requête suivante, puis expliquer ce que représente chaque ligne.
SELECT id_auteur, COUNT(*) AS nombre
FROM Livres
GROUP BY id_auteur;- Le résultat précédent est peu lisible : on veut le nom de l'auteur plutôt que son identifiant, et un classement du plus prolifique au moins prolifique. Écrire la requête et donner son résultat.
- Écrire la requête qui affiche le nom des auteurs ayant au moins deux livres au catalogue. Donner son résultat.
- Donner le résultat de la requête suivante, et expliquer en quoi elle diffère de celle de la question 4.
SELECT Auteurs.nom, COUNT(*) AS nombre
FROM Livres
JOIN Auteurs ON Livres.id_auteur = Auteurs.id_auteur
WHERE Livres.annee < 1900
GROUP BY Auteurs.id_auteur, Auteurs.nom;- Dans les requêtes ci-dessus, le regroupement est écrit
GROUP BY Auteurs.id_auteur, Auteurs.nomet non simplementGROUP BY Auteurs.nom. Justifier ce choix. - Écrire la requête qui donne, pour chaque auteur, l'année de parution de son livre le plus ancien, classée de la plus ancienne à la plus récente. Donner son résultat.
Créez un compte gratuit : votre première correction est offerte.
Suivre les emprunts en cours de la médiathèque
On complète la base de la médiathèque par deux tables qui décrivent les prêts.
CREATE TABLE Adherents (
id_adherent INTEGER PRIMARY KEY,
nom TEXT,
classe TEXT
);
CREATE TABLE Emprunts (
id_emprunt INTEGER PRIMARY KEY,
id_adherent INTEGER,
id_livre INTEGER,
date_emprunt TEXT,
date_retour TEXT,
FOREIGN KEY (id_adherent) REFERENCES Adherents(id_adherent),
FOREIGN KEY (id_livre) REFERENCES Livres(id_livre)
);Table Adherents
| id_adherent | nom | classe |
|---|---|---|
| 1 | Amina | 1G1 |
| 2 | Karim | TG2 |
| 3 | Lina | TG2 |
| 4 | Youssef | 2D |
Table Emprunts — la date de retour vaut NULL tant que le livre n'a pas été rendu.
| id_emprunt | id_adherent | id_livre | date_emprunt | date_retour |
|---|---|---|---|---|
| 1 | 1 | 3 | 2025-09-08 | 2025-09-22 |
| 2 | 2 | 1 | 2025-09-09 | NULL |
| 3 | 1 | 8 | 2025-09-15 | NULL |
| 4 | 3 | 3 | 2025-09-16 | 2025-09-30 |
| 5 | 4 | 6 | 2025-09-18 | NULL |
| 6 | 2 | 8 | 2025-10-02 | NULL |
On rappelle le contenu utile de la table Livres : Les Misérables, Mort sur le Nil, Vingt mille lieues sous les mers, 1984.
- Un élève propose de supprimer la table
Empruntset d'ajouter à la place une colonneid_adherentdans la tableLivres. Expliquer précisément ce que ce schéma rendrait impossible. - Écrire la requête qui affiche, pour chaque emprunt en cours, le nom de l'adhérent, le titre du livre et la date d'emprunt, du plus ancien au plus récent. Donner son résultat.
- Écrire la requête qui affiche le nom des adhérents ayant emprunté le livre intitulé 1984. Donner son résultat.
- Donner le résultat de la requête suivante et expliquer ce qui ne va pas.
SELECT COUNT(*) FROM Emprunts WHERE date_retour = NULL;- Écrire la requête qui donne, pour chaque livre effectivement emprunté au moins une fois, son titre et son nombre total d'emprunts, du plus emprunté au moins emprunté. Donner son résultat. (On rappelle que
COUNT(*)compte les lignes d'un groupe formé parGROUP BY.) - Karim rapporte Les Misérables le 10 octobre 2025. Écrire l'instruction SQL qui enregistre ce retour, en veillant à ne modifier que la ligne concernée.
- Expliquer pourquoi l'attribut
id_empruntest utile, alors qu'on aurait pu songer à utiliser le couple(id_adherent, id_livre)comme clé primaire de la tableEmprunts.
Créez un compte gratuit : votre première correction est offerte.
La base de données d'un festival de cinéma
Cet exercice, composé de deux parties A et B, porte sur les bases de données relationnelles et le langage SQL.
Un festival de cinéma programme des films dans deux salles pendant trois jours. Son organisation repose sur la base de données définie ci-dessous.
CREATE TABLE Realisateurs (
id_realisateur INTEGER PRIMARY KEY,
nom TEXT,
pays TEXT
);
CREATE TABLE Films (
id_film INTEGER PRIMARY KEY,
titre TEXT,
annee INTEGER,
duree INTEGER,
id_realisateur INTEGER,
FOREIGN KEY (id_realisateur) REFERENCES Realisateurs(id_realisateur)
);
CREATE TABLE Projections (
id_projection INTEGER PRIMARY KEY,
id_film INTEGER,
salle TEXT,
jour TEXT,
spectateurs INTEGER,
FOREIGN KEY (id_film) REFERENCES Films(id_film)
);Table Realisateurs
| id_realisateur | nom | pays |
|---|---|---|
| 1 | Varda | France |
| 2 | Kurosawa | Japon |
| 3 | Sissako | Mauritanie |
| 4 | Campion | Nouvelle-Zélande |
Table Films — la durée est exprimée en minutes.
| id_film | titre | annee | duree | id_realisateur |
|---|---|---|---|---|
| 1 | Cléo de 5 à 7 | 1962 | 90 | 1 |
| 2 | Les Glaneurs et la glaneuse | 2000 | 82 | 1 |
| 3 | Rashomon | 1950 | 88 | 2 |
| 4 | Les Sept Samouraïs | 1954 | 207 | 2 |
| 5 | Timbuktu | 2014 | 97 | 3 |
| 6 | La Leçon de piano | 1993 | 121 | 4 |
Table Projections
| id_projection | id_film | salle | jour | spectateurs |
|---|---|---|---|---|
| 1 | 3 | Lumiere | vendredi | 210 |
| 2 | 1 | Melies | vendredi | 95 |
| 3 | 5 | Lumiere | samedi | 180 |
| 4 | 3 | Melies | samedi | 130 |
| 5 | 6 | Lumiere | dimanche | 240 |
| 6 | 4 | Lumiere | samedi | 75 |
| 7 | 2 | Melies | dimanche | 60 |
Partie A : le modèle relationnel
A.1. Donner la clé primaire et, s'il y en a, la ou les clés étrangères de chacune des trois tables.
A.2. L'organisateur affirme : « puisque chaque film a un seul réalisateur, on aurait pu se contenter d'écrire son nom et son pays directement dans la table Films ». Donner deux arguments précis contre cette proposition.
A.3. Expliquer pourquoi une table Projections distincte est nécessaire, en s'appuyant sur le contenu de la base.
A.4. L'attribut duree a pour domaine les entiers. Proposer un domaine plus précis et expliquer l'intérêt de restreindre un domaine.
A.5. Le festival est géré simultanément depuis la caisse des deux salles. Citer deux services rendus par le SGBD dans cette situation.
Partie B : le langage SQL
On rappelle que COUNT(*) compte les lignes d'un groupe, et que SUM(colonne) en additionne les valeurs ; les groupes sont formés par la clause GROUP BY, et filtrés par la clause HAVING.
B.1. Écrire la requête qui affiche le titre et la durée des films durant plus de minutes, du plus long au plus court. Donner son résultat.
B.2. Écrire la requête qui affiche le titre et l'année des films réalisés par un cinéaste japonais, par année croissante. Donner son résultat.
B.3. Écrire la requête qui affiche, pour chaque projection du samedi, le titre du film, la salle et le nombre de spectateurs, par affluence décroissante. Donner son résultat.
B.4. Écrire la requête qui donne, pour chaque film projeté, le nombre total de spectateurs qu'il a réunis sur l'ensemble du festival, du plus vu au moins vu. Donner son résultat.
B.5. Écrire la requête qui n'affiche que les films ayant réuni plus de spectateurs au total. Donner son résultat.
B.6. Une projection supplémentaire de Timbuktu est ajoutée le dimanche en salle Melies ; elle réunit spectateurs. Écrire l'instruction SQL correspondante, puis donner le nouveau classement de la question B.4.
B.7. Un stagiaire souhaite retirer Rashomon de la base et exécute DELETE FROM Films WHERE id_film = 3;. Le SGBD refuse. Expliquer pourquoi, et indiquer la marche à suivre.
Créez un compte gratuit : votre première correction est offerte.