← Retour au chapitre

Fiche à trous · Terminale · NSI

Bases de données relationnelles — SQL

Complétez de mémoire, puis vérifiez avec la page de corrigé.

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.

Le modèle relationnel

DéfinitionClé primaire et clé étrangère :

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.

Interroger une table

Propriété

3

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.

Joindre deux tables

Règle

5

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.

Compter les tables jointes : il faut une condition de moins que de tables.

L'injection SQL

Propriété

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

  1. 7.
  2. 8.
  3. 9.
  4. 10.
  5. 11.
  • 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 ?

Corrigé · à détacher

Bases de données relationnelles — SQL

  1. 1. 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.
  2. 2. 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.
  3. 3.
  4. 4. 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.
  5. 5.
  6. 6. 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.
  7. 7. Identifier les tables nécessaires et, pour chacune, ce qu'on en attend.
  8. 8. Repérer les clé étrangères qui les relient : ce sont elles qui donnent les conditions de JOIN.
  9. 9. Écrire la jointure avec sa condition, et vérifier qu'il y a une condition de moins que de tables.
  10. 10. Ajouter le filtrage : WHERE pour les lignes, HAVING pour les groupes après GROUP BY.
  11. 11. Vérifier le nombre de lignes obtenu : un résultat anormalement volumineux signale une condition manquante.