Programme en vigueur — arrêtés du 19 juillet 2019, applicable en Terminale depuis la rentrée 2020. Voir le texte
Modèle entité-relation. Clé primaire, clé étrangère, contrainte d'intégrité. SQL : SELECT, WHERE, JOIN, GROUP BY, HAVING, ORDER BY. Requêtes imbriquées. Injection SQL et sécurité.
La règle d'or
Une jointure sans condition de rapprochement ne relie rien : elle associe chaque ligne de la première table à toutes les lignes de la seconde.
L'erreur que tout le monde fait
Interroger deux tables ensemble en oubliant la condition qui relie la clé étrangère de l'une à la clé primaire de l'autre.
La requête aboutit et renvoie des lignes, ce qui la fait passer pour correcte : elle produit en réalité toutes les combinaisons possibles, dont l'immense majorité n'a aucun sens. L'erreur se repère au nombre de résultats, égal au produit des tailles des deux tables.
Compter les lignes attendues avant d'exécuter : un résultat anormalement grand signale une condition de jointure manquante.
Interroger deux tables de mille lignes chacune en oubliant la condition qui les relie ne produit pas une erreur : cela produit un million de lignes. La requête est valide, elle s'exécute, et son résultat n'a aucun sens. C'est la faute la plus fréquente du chapitre, et la plus silencieuse.
1Le modèle relationnel
Définition
Clé primaire et clé étrangère — Une clé primaire identifie de façon unique chaque ligne d'une table : deux lignes ne peuvent pas la partager, et elle ne peut pas être vide. Une clé étrangère est une colonne qui référence la clé primaire d'une autre table : c'est elle qui établit le lien entre deux tables. La contrainte d'intégrité référentielle garantit qu'une clé étrangère pointe toujours vers une ligne qui existe.
L'intérêt de cette organisation est d'éviter la redondance : une information n'est stockée qu'à un seul endroit, et les autres tables y renvoient. Sans cela, modifier une donnée obligerait à la corriger partout où elle figure, et la moindre omission produirait deux versions contradictoires dans la même base.
2Interroger une table
Propriété
Une requête SQL se lit dans un ordre précis. SELECT indique les colonnes à afficher, FROM la table, WHERE la condition de filtrage des lignes. GROUP BY regroupe les lignes partageant une valeur, ce qui permet d'appliquer une fonction d'agrégat — compte, somme, moyenne. HAVING filtre ensuite ces groupes, là où WHERE filtre les lignes. ORDER BY trie le résultat.
WHEREfiltreleslignes⋅HAVINGfiltrelesgroupes
La distinction entre WHERE et HAVING découle de l'ordre d'exécution : les lignes sont d'abord filtrées, puis regroupées, puis les groupes filtrés. Une condition portant sur un agrégat — « les clients ayant passé plus de trois commandes » — ne peut donc pas figurer dans un WHERE : au moment où il s'applique, les groupes n'existent pas encore.
3Joindre deux tables
Règle
Une JOIN rapproche deux tables selon une condition qui relie la clé étrangère de l'une à la clé primaire de l'autre. Sans cette condition, la requête n'échoue pas : elle associe chaque ligne de la première table à toutes les lignes de la seconde, produisant un nombre de lignes égal au produit des deux tailles. Le résultat est volumineux, dénué de sens, et parfaitement valide du point de vue du moteur.
sansconditiondejointure,n×mlignes
Piège
Interroger deux tables ensemble en oubliant la condition qui relie la clé étrangère de l'une à la clé primaire de l'autre.
Pourquoi — Le moteur n'a aucun moyen de deviner quelles colonnes doivent se correspondre : il exécute ce qu'on lui demande, c'est-à-dire toutes les combinaisons possibles. Sur de petites tables de test, le résultat contient quelques dizaines de lignes et l'anomalie passe inaperçue ; sur les données réelles, elle produit des millions de lignes et un résultat faux. Le symptôme apparaît donc après la mise en production.
Le réflexe — Compter les tables jointes : il faut une condition de moins que de tables.
4L'injection SQL
Propriété
Une injection SQL consiste à faire interpréter comme du code ce qui était censé être une donnée. Elle survient dès qu'une requête est construite en concaténant une saisie d'utilisateur : la saisie peut alors contenir des caractères qui referment la chaîne attendue et ajoutent une condition, un opérateur ou une instruction entière. La faille ne vient pas du langage : elle vient du mélange entre la structure de la requête et les valeurs qu'on y place.
La parade est structurelle, non cosmétique : les requêtes préparées déclarent d'abord la structure de la requête, puis y passent les valeurs séparément. Le moteur sait alors que ces valeurs sont des données et ne les interprète jamais comme du code, quel que soit leur contenu. Filtrer les caractères « dangereux » est une parade partielle — elle suppose qu'on a pensé à tous les cas, ce qui n'est jamais démontrable.
Construire une requête sur plusieurs tables
Identifier les tables nécessaires et, pour chacune, ce qu'on en attend.
Repérer les clé étrangères qui les relient : ce sont elles qui donnent les conditions de JOIN.
Écrire la jointure avec sa condition, et vérifier qu'il y a une condition de moins que de tables.Trois tables jointes demandent deux conditions de rapprochement.
Ajouter le filtrage : WHERE pour les lignes, HAVING pour les groupes après GROUP BY.
Vérifier le nombre de lignes obtenu : un résultat anormalement volumineux signale une condition manquante.
▢Chaque JOIN a-t-elle sa condition de rapprochement ?
▢Ai-je une condition de moins que de tables jointes ?
▢Mon filtre porte-t-il sur des lignes (WHERE) ou des groupes (HAVING) ?
▢Ai-je vérifié le nombre de lignes du résultat ?
▢Mes requêtes construites avec une saisie utilisateur sont-elles préparées ?
▢Ai-je évité de concaténer une saisie dans une requête ?
L'essentiel en 11 points
·Clé primaire : identifie de façon unique. Clé étrangère : référence une autre table.
·L'intégrité référentielle garantit que la référence pointe vers une ligne existante.
·Éviter la redondance : une information à un seul endroit.
·SELECT les colonnes, FROM la table, WHERE la condition sur les lignes.
·GROUP BY regroupe ; HAVING filtre les groupes, WHERE filtre les lignes.
·WHERE s'applique avant le regroupement : d'où l'impossibilité d'y mettre un agrégat.
·Une JOIN exige une condition reliant clé étrangère et clé primaire.
·Sans condition : n × m lignes, résultat valide et dénué de sens.
·Une condition de moins que de tables jointes.
·Injection SQL : faire interpréter une donnée comme du code.
·Parade : requêtes préparées, jamais la concaténation.
2
Imprimer
Fiche PDF — Bases de données relationnelles — SQL
Gratuit · sans compte
Trois documents à imprimer, 6 pages en tout : le cours, les exercices avec la place pour écrire, et le corrigé détaillé avec son barème.
a.Qu'est-ce qu'une clé primaire ? Une clé étrangère ?
b.Qu'est-ce que l'intégrité référentielle ?
c.Quel est l'intérêt d'éviter la redondance ?
d.Différencier WHERE et HAVING.
e.Qu'est-ce qu'une injection SQL ?
›Voir le corrigéMasquer le corrigé
a. La clé primaire identifie de façon unique chaque ligne ; la clé étrangèreréférence la clé primaire d'une autre table.
b. La garantie qu'une clé étrangère pointe toujours vers une ligne qui existe.
c. Une information n'est stockée qu'à un seul endroit : la modifier ne demande qu'une correction, et deux versions contradictoires ne peuvent pas coexister.
d. WHERE filtre les lignes ; HAVING filtre les groupes, après GROUP BY.
e. Le fait de faire interpréter comme du code ce qui était censé être une donnée.
2
Une table Clients compte 1 000 lignes, une table Commandes 5 000 lignes. Une requête les joint sans condition de rapprochement.
Calculer
a.Combien de lignes la requête renvoie-t-elle ?
b.Combien en renverrait-elle avec la bonne condition, au maximum ?
c.Calculer le rapport entre les deux.
d.Pourquoi le moteur n'émet-il aucune erreur ?
e.Pourquoi l'anomalie peut-elle passer les tests et apparaître en production ?
›Voir le corrigéMasquer le corrigé
a. Le produit des deux tailles :1000×5000=5000000
Soit cinq millions de lignes.
b. Au plus 5 000 : chaque commande est rattachée à un client.
c. Rapport :5000000÷5000=1000
Soit mille fois plus de lignes que nécessaire.
d. Parce que la requête est syntaxiquement valide : le moteur n'a aucun moyen de deviner quelles colonnes devaient se correspondre. Il exécute ce qu'on lui demande — toutes les combinaisons.
e. Parce que sur de petites tables de test, le produit reste modeste et le résultat paraît plausible. C'est sur les données réelles que le volume explose — donc après la mise en production.
3
Construire des requêtes. Décrire en français ce que chacune doit faire, puis sa structure.
Appliquer
a.Afficher les clients dont la ville est Lyon.
b.Afficher chaque client et le nombre de ses commandes.
c.Afficher les seuls clients ayant passé plus de trois commandes.
d.Pourquoi la condition de c ne peut-elle pas figurer dans un WHERE ?
›Voir le corrigéMasquer le corrigé
a. SELECT des colonnes voulues, FROM Clients, WHERE sur la colonne ville. Aucun JOIN : une seule table suffit.
b. SELECT le client et un agrégat de comptage, FROM Clients, JOIN Commandes sur la condition reliant la clé étrangère à la clé primaire, puis GROUP BY le client.
c. La même requête, complétée d'un HAVING portant sur le comptage supérieur à trois.
d. Parce que WHERE s'applique avant le regroupement : au moment où il est évalué, les groupes n'existent pas encore, donc le comptage non plus. C'est l'ordre d'exécution qui impose HAVING.
4
Injection SQL. Analyser.
Analyser
a.D'où vient la faille : du langage SQL ou de la façon d'écrire la requête ?
b.Que permet d'obtenir une injection réussie ?
c.En quoi consiste une requête préparée ?
d.Pourquoi filtrer les caractères dangereux est-il une parade partielle ?
e.Quel principe général cette faille illustre-t-elle ?
›Voir le corrigéMasquer le corrigé
a. De la façon d'écrire la requête : de la concaténation d'une saisie d'utilisateur dans une chaîne qui sera interprétée. Le langage n'y est pour rien.
b. La lecture de données auxquelles l'utilisateur n'a pas droit, leur modification, leur suppression, ou le contournement d'une authentification.
c. À déclarer d'abord la structure de la requête, puis à y passer les valeurs séparément. Le moteur sait alors que ces valeurs sont des données et ne les interprète jamais comme du code.
d. Parce qu'elle suppose qu'on a pensé à tous les cas — tous les caractères, tous les encodages, toutes les variantes. C'est une hypothèse qu'on ne peut pas démontrer, et il suffit d'un oubli.
e. Qu'il ne faut jamais mélanger ce qui relève de la structure d'une instruction et ce qui relève des données. Le même principe vaut hors des bases : c'est lui qui fonde l'échappement en HTML, la séparation des arguments dans un appel système, et le rejet des formats interprétés.
Ce qui rapporte des points, ce qui en coûte
Définir clés primaire et étrangère3 ptsPerdu si : Confondre les deux rôles
Écrire une jointure avec sa condition5 ptsPerdu si : Joindre deux tables sans condition
Distinguer WHERE et HAVING par l'ordre d'exécution4 ptsPerdu si : Mettre un agrégat dans un WHERE
Vérifier le volume du résultat3 ptsPerdu si : Accepter un résultat mille fois trop volumineux
Expliquer l'injection SQL et sa parade5 ptsPerdu si : Proposer le filtrage des caractères comme solution complète
4
La méthode
Construire une requête sur plusieurs tables
1
Repérer les tables nécessaires et les colonnes qui les relient.
2
Écrire la jointure avec sa condition, puis vérifier le nombre de lignes obtenues.
3
Ajouter les conditions de sélection sur les lignes avant tout regroupement.
4
Regrouper si la question demande un calcul par catégorie, et filtrer les groupes séparément.
Une condition portant sur un résultat d'agrégat ne peut pas figurer dans la clause de sélection des lignes.
5
Écarter toute construction de la requête par concaténation d'une saisie d'utilisateur, qui ouvre la porte à une injection.
5
Se tester
Touches 1 à 4
NSITerminale
Question 1
Un arbitre de basketball doit vérifier si une requête SQL pour lister les joueurs ayant une moyenne de points par match supérieure à 20 est vulnérable à une injection SQL. La requête est construite ainsi :
"SELECT nom FROM joueurs WHERE moyenne_points > " + moyenne_saisie
Quelle entrée malveillante pourrait corrompre cette requête ?
Aucun compte requis — réponds, la correction s'affiche aussitôt.
Bases de données relationnelles — SQL : c'est en quelle classe ?+
Ce chapitre est au programme de NSI au lycée, en classe de Terminale, année du Baccalauréat. Il est défini par le Bulletin Officiel de l'Éducation nationale, le texte de référence qui fixe ce qui doit être enseigné dans chaque matière.
Que faut-il savoir sur Bases de données relationnelles — SQL ?+
Modèle entité-relation. Clé primaire, clé étrangère, contrainte d'intégrité. SQL : SELECT, WHERE, JOIN, GROUP BY, HAVING, ORDER BY. Requêtes imbriquées. Injection SQL et sécurité. Les notions à maîtriser sont : SQL, SELECT, JOIN, clé primaire, clé étrangère, GROUP BY.
Où télécharger la fiche PDF de Bases de données relationnelles — SQL ?+
Sur cette page, dans le bloc « Imprimer » : 3 documents à télécharger — le cours, les exercices et le corrigé — soit 6 pages au format A4, prêtes à imprimer. Le téléchargement est gratuit, immédiat, et ne demande ni compte ni adresse e-mail.
Le corrigé de Bases de données relationnelles — SQL est-il fourni ?+
Oui, et c'est un document à part : chaque exercice y est repris étape par étape, avec le barème détaillé en fin de fiche — ce qui est attendu, combien de points, et ce qui fait perdre le point. Un parent qui ne se souvient plus du programme peut corriger une copie avec.
Bases de données relationnelles — SQL peut-il tomber au Baccalauréat ?+
Ce chapitre fait partie du programme officiel de Terminale, il entre donc dans le périmètre du Baccalauréat. Le sujet exact varie chaque année et aucun chapitre n'est garanti, mais l'ensemble du programme de l'année est susceptible d'être évalué : mieux vaut ne pas parier sur des impasses.
Comment réviser Bases de données relationnelles — SQL efficacement ?+
Commence par lire la fiche de révision pour remettre la règle en place, puis enchaîne immédiatement sur le quiz de cette page. Répondre juste après avoir lu ne suffit pas : reviens sur le chapitre deux ou trois jours plus tard. C'est l'espacement des révisions, plus que leur durée, qui fait tenir une notion en mémoire. Une session de quinze minutes répétée vaut mieux qu'une heure unique.
Faut-il un compte pour s'entraîner sur Bases de données relationnelles — SQL ?+
Non. Les quiz, les corrections détaillées et les fiches de révision sont accessibles sans créer de compte et sans donner d'adresse e-mail. Le compte gratuit sert uniquement à conserver la progression d'un appareil à l'autre.