Interroger une base en SQL

Sélectionner des données, joindre des relations, calculer des agrégats et écrire des modifications SQL contrôlées.

Environ 40 minutes

  • Construire SELECT, FROM, WHERE et JOIN
  • Interpréter les doublons et les agrégats
  • Écrire INSERT, UPDATE et DELETE
Sommaire
  1. 1. Choisir les lignes et les colonnes
  2. 2. Relier les informations sans perdre le sens
  3. 3. Résumer plusieurs lignes
  4. 4. Insérer, modifier et supprimer
  5. 5. Au bac : passer d’une question à une requête

Comment retrouver les livres d’un auteur sans recopier son nom dans chaque ligne du catalogue ?

SQL est un langage de requêtes : on décrit le résultat souhaité plutôt que la suite exacte des parcours de la mémoire. La base utilisée ici possède deux relations, Auteur(id, nom) et Livre(id, titre, auteur, prix). Les clés primaires sont les attributs id ; Livre.auteur référence Auteur.id. Les noms des tables et attributs font partie de la spécification : on ne peut pas les remplacer librement dans une requête. Le cours suit progressivement la sélection, les liens, les calculs, puis les modifications. Chaque commande de modification se pratique sur une copie d’exercice.

1. Choisir les lignes et les colonnes

Chaque ligne est un livre. Le prix est exprimé en euros ; les deux livres à 12 euros sont distincts.

La commande SELECT titre, prix FROM Livre; renvoie les deux attributs titre et prix de toutes les lignes de Livre. SELECT choisit les expressions à afficher et FROM indique la relation interrogée. SELECT * demande toutes les colonnes, ce qui est utile pour une exploration mais rend moins explicite le résultat attendu. Une requête SELECT ne modifie pas les enregistrements de départ : le tableau résultat n’est pas une nouvelle version du catalogue.

La clause WHERE filtre les lignes selon une condition. SELECT titre FROM Livre WHERE prix < 10; ne renvoie ici que Matin. Les opérateurs de comparaison usuels comprennent =, <, <=, >, >= et <> pour différent. Les valeurs textuelles sont placées entre apostrophes SQL, comme dans nom = 'Lina'. Les noms d’attributs ne sont pas des valeurs textuelles : écrire 'prix' compare une constante, pas la colonne.

AND exige que deux conditions soient vraies ; OR en exige au moins une. Des parenthèses rendent le regroupement clair. Par exemple, un critère qui combine l’auteur et deux prix possibles s’écrit auteur = 1 AND (prix = 8 OR prix = 12). Sans parenthèses, on risque de sélectionner aussi les livres à 12 euros d’un autre auteur. Pour le marqueur NULL, une recherche de valeur absente se fait avec IS NULL ; une comparaison ordinaire avec = ne fournit pas le même test.

Sans ORDER BY, l’ordre des lignes du résultat n’est pas garanti. ORDER BY prix DESC trie les prix du plus élevé au plus faible ; ASC exprime l’ordre croissant. Pour départager les égalités, ajoute un second critère. L’ordre des colonnes dans SELECT et l’ordre des lignes dans ORDER BY sont donc deux choix différents. Une égalité de prix ne signifie pas que deux livres sont le même enregistrement.

La sélection prix >= 12 retient trois livres. Le tri ORDER BY prix DESC, id ASC place Nuit en premier, puis Rivage et Écho.

Exemple résolu

Trouver les titres et prix des livres coûtant au moins 12 euros, par prix décroissant puis par identifiant croissant.

  1. Étape 1 : On interroge Livre, car cette relation contient les attributs demandés.
  2. Étape 2 : On filtre avec prix >= 12 : le prix 12 doit rester inclus.
  3. Étape 3 : On ne conserve que titre et prix, puis on ordonne selon les deux critères.

Résultat : SELECT titre, prix FROM Livre WHERE prix >= 12 ORDER BY prix DESC, id ASC; Résultat : (Nuit, 15), (Rivage, 12), (Écho, 12).

Piège à éviter : Employer > 12 exclurait les deux livres au prix limite alors que la consigne dit au moins.

À toi d'essayer

Sur la même base, écris une requête renvoyant les identifiants des livres de l’auteur 2 coûtant strictement moins de 15 euros.

Voir la réponse

SELECT id FROM Livre WHERE auteur = 2 AND prix < 15; Le résultat contient seulement l’identifiant 14.

2. Relier les informations sans perdre le sens

Auteur contient ici (1, Lina), (2, Sami) et (3, Noa). Une jointure associe les lignes qui satisfont sa condition de correspondance. Pour chaque livre, on recherche l’auteur dont l’identifiant est égal à Livre.auteur. La commande SELECT Livre.titre, Auteur.nom FROM Livre JOIN Auteur ON Livre.auteur = Auteur.id; renvoie les quatre titres avec le nom de leur auteur. JOIN désigne ici une jointure interne : seules les correspondances sont retenues.

La condition ON ne signifie pas que les deux colonnes ont le même nom. Elle compare les valeurs jouant les rôles adéquats. Livre.id identifie un livre ; Auteur.id identifie un auteur : les comparer serait une erreur de modèle, même si certains nombres coïncidaient. Lorsque plusieurs relations portent un attribut id, son nom doit être qualifié par la table pour éviter l’ambiguïté.

On peut utiliser des alias pour alléger une requête : Livre AS l et Auteur AS a permettent d’écrire l.auteur = a.id. L’alias ne change pas le contenu de la relation. Il sert de nom dans la requête. Les conditions WHERE filtrent ensuite les lignes obtenues : on peut rechercher un auteur par son nom sans connaître son numéro à l’avance. Cette distinction entre correspondance et sélection facilite la lecture de requêtes longues.

La jointure produit une ligne par correspondance, pas une ligne par personne. Lina apparaît deux fois si on affiche le nom pour chacun de ses livres. SELECT DISTINCT Auteur.nom retire les noms identiques du résultat, mais deux personnes homonymes seraient alors confondues. Pour lister des auteurs distincts en conservant leur identité, on affiche leur identifiant et leur nom. DISTINCT porte sur l’ensemble des colonnes affichées, pas sur une seule colonne choisie implicitement.

Exemple résolu

Renvoyer les identifiants et noms des auteurs ayant au moins un livre à moins de 13 euros, sans doublon.

  1. Étape 1 : La relation Livre fournit le prix ; Auteur fournit le nom. Il faut les joindre par Livre.auteur = Auteur.id.
  2. Étape 2 : Le filtre prix < 13 retient les livres 11, 12 et 14. Lina apparaît deux fois avant suppression des doublons.
  3. Étape 3 : DISTINCT porte sur le couple identifiant et nom afin de préserver l’identité de l’auteur.

Résultat : SELECT DISTINCT Auteur.id, Auteur.nom FROM Auteur JOIN Livre ON Auteur.id = Livre.auteur WHERE Livre.prix < 13 ORDER BY Auteur.id; Résultat : (1, Lina), (2, Sami).

Piège à éviter : Supprimer le filtre ou joindre les deux attributs id répondrait à une autre question.

À toi d'essayer

Sans exécuter la requête, explique pourquoi SELECT Auteur.nom FROM Auteur JOIN Livre ON Auteur.id = Livre.auteur; ne montre pas Noa.

Correction détaillée pas à pasDans ce chapitre : 2 corrections détaillées.

3. Résumer plusieurs lignes

Les fonctions d’agrégation calculent une information sur un ensemble de lignes. COUNT(*) compte les lignes retenues, SUM(prix) additionne les valeurs, AVG(prix) calcule leur moyenne, MIN(prix) et MAX(prix) donnent leurs extrêmes. La commande SELECT COUNT(*), AVG(prix) FROM Livre; renvoie une ligne contenant 4 et 11,75, puisque les quatre prix ont pour somme 47 euros. La notation décimale exacte affichée dépend de l’outil SQL.

WHERE peut réduire l’ensemble avant le calcul. Pour les livres de l’auteur 1, SELECT COUNT(*), SUM(prix) FROM Livre WHERE auteur = 1; donne 2 et 20. Il ne faut pas calculer une moyenne de tous les livres puis croire qu’un filtre s’applique après coup. On raisonne d’abord sur les lignes retenues, puis sur les valeurs agrégées. Cette lecture logique ne décrit pas nécessairement l’organisation interne choisie par le SGBD.

COUNT(attribut) compte les valeurs non NULL de cet attribut ; COUNT(*) compte les lignes, même si certaines colonnes sont NULL. Dans notre catalogue, prix est obligatoire, donc COUNT(prix) et COUNT(*) coïncident. Sur un ensemble vide, COUNT(*) vaut zéro, tandis que la somme et la moyenne SQL renvoient NULL. Il faut distinguer une somme inconnue ou sans donnée d’un stock réellement égal à zéro.

On reste ici sur des agrégats globaux, éventuellement après sélection et jointure. Les clauses GROUP BY et HAVING ne sont pas nécessaires pour les capacités traitées dans cette leçon. Une requête affichant en même temps un titre isolé et la moyenne de tous les prix ne désigne pas clairement quel titre devrait accompagner le résultat : il faut d’abord préciser la question au lieu de compter sur une tolérance de l’outil.

4. Insérer, modifier et supprimer

INSERT INTO ajoute une ligne. Nommer les colonnes évite de dépendre de leur ordre de déclaration : INSERT INTO Livre (id, titre, auteur, prix) VALUES (15, 'Aube', 1, 10); ajoute le livre 15, à condition que cet identifiant soit libre et que l’auteur 1 existe. Une insertion doit respecter les contraintes du schéma. Les exemples de cette section sont indépendants : chaque expérience repart des quatre livres du tableau initial.

UPDATE modifie les valeurs des lignes qui satisfont WHERE. DELETE FROM supprime les lignes sélectionnées. DELETE ne supprime pas la définition de la table. Une instruction sans WHERE concerne toutes les lignes, ce qui peut être volontaire mais doit correspondre exactement à la demande. Il faut donc contrôler la population visée, pas ajouter mécaniquement une condition quelconque pour se rassurer.

Exemple résolu

Le prix du livre 12 passe à 9 euros. Écris la commande puis indique ce qui change.

  1. Étape 1 : La clé primaire identifie une seule ligne : on utilise id = 12.
  2. Étape 2 : SET précise la nouvelle valeur du prix, sans modifier le titre ni l’auteur.
  3. Étape 3 : Une lecture ciblée permet de constater le résultat et de vérifier que les trois autres livres sont inchangés.

Résultat : UPDATE Livre SET prix = 9 WHERE id = 12; La ligne devient (12, Matin, 1, 9). Une commande DELETE FROM Livre WHERE id = 12; aurait supprimé cette ligne entière.

Piège à éviter : Filtrer avec prix = 8 peut fonctionner sur le tableau présent, mais ne décrit pas l’identifiant demandé et pourrait toucher d’autres livres dans une base différente.

À toi d'essayer

Une requête renvoie le nombre 4 pour COUNT(*) après une jointure Catalogue JOIN Emprunt. Un élève en déduit que quatre livres différents ont été empruntés. Cette conclusion est-elle garantie ? Propose la donnée à compter.

Correction détaillée pas à pasDans ce chapitre : 2 corrections détaillées.

5. Au bac : passer d’une question à une requête

Au bac : construire puis contrôler une requête

  1. Repère les attributs demandés et les tables qui les possèdent. Pour plusieurs tables, écris le chemin des clés à comparer.
  2. Traduis séparément les correspondances ON et les filtres WHERE. Vérifie strictement inférieur, au moins, et les regroupements AND/OR.
  3. Choisis les colonnes, les agrégats et l’éventuelle suppression des doublons. Demande-toi ce que représente une ligne du résultat.
  4. Simule la requête sur quelques enregistrements : un cas retenu, un cas exclu et un cas à la limite. Ajoute ORDER BY seulement lorsque l’ordre est demandé.

Vocabulaire

Projection :
Choix des attributs affichés dans le résultat.
Sélection :
Filtrage des enregistrements par une condition.
Jointure :
Association de lignes selon une condition de correspondance.
Agrégat :
Calcul portant sur un ensemble de lignes.
Attention :

Erreurs fréquentes : confondre nom de colonne et texte ; oublier la condition de jointure ; croire que DISTINCT désigne toujours des personnes ; prendre le nombre de correspondances pour le nombre d’objets distincts ; utiliser = NULL pour rechercher une absence.

Relier les besoins aux mécanismes

BesoinRéponse
Choisir les colonnesSELECT
Filtrer les lignesWHERE
Relier les tablesJOIN avec ON
Changer une valeurUPDATE avec SET

S’entraîner : consulte la rubrique Exercices du site. Pour vérifier une solution sur ordinateur, commence par annoncer le résultat attendu et compare ensuite chaque ligne obtenue.

À retenir

  • SELECT construit un résultat sans modifier les tables interrogées.
  • Une jointure interne produit une ligne par correspondance.
  • COUNT(*) compte les lignes ; COUNT(colonne) ignore les valeurs NULL.
  • INSERT ajoute, UPDATE modifie et DELETE supprime des enregistrements.

Fiche de révision

Ordre de lecture utile

relations nécessaires, liens entre elles, lignes retenues, colonnes ou calculs affichés, ordre final.

Contrôle d’une borne

un prix égal au seuil appartient au filtre >=, mais pas au filtre >.

Pour éviter de compter deux fois un objet, conserve son identifiant dans ton raisonnement avant d’utiliser DISTINCT.

Avant une modification, une sélection portant sur la même condition rend la cible observable.

Questions fréquentes

Pourquoi un auteur apparaît-il plusieurs fois après une jointure ?

La jointure construit une ligne par livre correspondant. L’auteur peut donc être présent sur plusieurs lignes sans erreur.

Une requête sans ORDER BY est-elle nécessairement triée par identifiant ?

Non. L’ordre constaté lors d’un essai ne constitue pas une garantie d’ordre du résultat.

Et maintenant ?

Tu as lu le cours. L’étape suivante tient en une action.

Relis le coursReprends l’essentiel avant de passer à la suite.

Prolonge l’expérience !

Continue à explorer ce chapitre à travers de nouvelles activités, des défis et des expériences interactives. Avec Premium, l’apprentissage continue !

Ici, tu débloques aussi 2 corrections détaillées.

Parent ? Suivez les progrès de votre enfant.

Tous les cours de NSI