Les requêtes SQL
Objectifs du Chapitre
Comprendre le rôle du langage SQL dans la gestion des bases de données relationnelles.
Créer une base de données et des tables avec des contraintes simples.
Manipuler les données avec les instructions SELECT, INSERT, UPDATE et DELETE.
Interroger les données avec des filtres, des tris, des jointures simples et des fonctions d'agrégation.
Jusqu'ici tu as modélisé et raisonné sur les données. Ici tu leur parles. SQL est un langage déclaratif : tu décris le résultat voulu, pas la marche à suivre, et c'est ce qui le rend à la fois court à écrire et déroutant au début. Les requêtes de ce chapitre s'exécutent directement dans la page, sur une base de démonstration : lis, modifie, relance.
Chaque bloc SQL a un bouton Exécuter et un bouton Schéma. Modifie la requête, relance, regarde ce qui change : c'est de loin la façon la plus rapide d'apprendre le langage. La base repart neuve à chaque exécution.
À quoi sert SQL ?
Dans les chapitres précédents, vous avez appris à modéliser une base de données (MCD, MLD) et à raisonner sur les données avec l'algèbre relationnelle. SQL est la traduction concrète de tout cela : c'est le langage que vous tapez pour interroger une vraie base de données.
SQL (Structured Query Language) est un langage déclaratif utilisé pour interagir avec des bases de données relationnelles. Il permet de définir des structures, de manipuler des données, et d'interroger des informations rapidement et efficacement.
SQL est omniprésent dans les systèmes informatiques modernes. Il permet à la fois :
- De créer et structurer une base de données (
CREATE,ALTER,DROP) ; - D'ajouter, modifier ou supprimer des données (
INSERT,UPDATE,DELETE) ; - D'interroger et exploiter les données (
SELECT,JOIN,GROUP BY, etc.) ; - De contrôler les accès et la sécurité (
GRANT,REVOKE) ; - De générer des statistiques simples (moyennes, totaux, comptages).
Pourquoi le SQL est-il toujours utilisé aujourd'hui ?
- Standardisé : SQL est un langage reconnu par tous les grands systèmes de gestion de bases de données (MySQL, PostgreSQL, Oracle, SQL Server…).
- Lisible : sa syntaxe proche du langage naturel le rend facilement compréhensible.
- Puissant : il permet de traiter efficacement de très grandes quantités de données.
- Transverse : il est utilisé dans presque tous les métiers liés à la donnée.
- Informatique : authentification, gestion des comptes, suivi des activités utilisateur.
- BTP : planification des interventions, suivi des livraisons, gestion des équipements.
- Énergie : gestion des capteurs, alertes sur la consommation, historique des relevés.
- Transport : géolocalisation des véhicules, affectation des tournées, suivi des colis.
- Industrie : traçabilité des produits, contrôle qualité, gestion de la maintenance.
SQL est un outil essentiel pour manipuler et exploiter efficacement des données relationnelles. Il est utilisé dans tous les secteurs d'activité, quel que soit le volume ou le type d'information à gérer.
Types de données courants
| Type SQL | Description |
|---|---|
INT, BIGINT | Nombres entiers (positifs ou négatifs) |
SMALLINT, TINYINT | Entiers de plus petite taille (moins de mémoire utilisée) |
DECIMAL(p,s) | Nombres décimaux précis avec p chiffres au total et s après la virgule |
FLOAT, REAL | Nombres décimaux à virgule flottante (moins précis, plus légers) |
CHAR(n) | Texte fixe de longueur n (utile pour des codes, comme un code postal) |
VARCHAR(n) | Texte variable jusqu'à n caractères |
TEXT | Texte long (commentaires, descriptions...) |
DATE | Date au format AAAA-MM-JJ |
TIME, DATETIME | Heure seule ou date avec heure |
BOOLEAN | Valeur logique : TRUE ou FALSE |
ENUM(...) | Valeur choisie parmi une liste définie (ex : 'Homme', 'Femme') |
BLOB | Données binaires (images, fichiers, sons...) |
nom VARCHAR(50): chaîne de texte pouvant aller jusqu'à 50 caractères.montant DECIMAL(8,2): valeur numérique avec 6 chiffres avant la virgule et 2 après (ex : 123456.78).sexe ENUM('Homme', 'Femme', 'Autre'): contraint la valeur à une liste prédéfinie.codePostal CHAR(5): champ texte fixe pour un code à 5 chiffres.photo BLOB: stocke une image en base de données (rarement conseillé).
CHAR vs VARCHAR - quand choisir lequel ?
Utilisez CHAR(n) quand la valeur a toujours exactement la même taille (code postal, numéro INSEE, identifiant fixe).
Utilisez VARCHAR(n) pour les textes de longueur variable (noms, adresses, titres).
CHAR est légèrement plus rapide ; VARCHAR économise de l'espace disque.
Familles de commandes SQL
Le langage SQL est divisé en plusieurs familles de commandes, selon leur rôle dans la gestion d'une base de données relationnelle.
| Catégorie | Signification | Exemples |
|---|---|---|
| DDL (Data Definition Language) | Définir ou modifier la structure des objets (tables, vues, clés). | CREATE, ALTER, DROP |
| DML (Data Manipulation Language) | Ajouter, modifier ou supprimer des données. | INSERT, UPDATE, DELETE |
| DQL (Data Query Language) | Interroger les données pour les lire ou les analyser. | SELECT |
| DCL (Data Control Language) | Gérer les permissions et la sécurité d'accès. | GRANT, REVOKE |
| TCL (Transaction Control Language) | Contrôler les transactions (groupes d'opérations atomiques). | COMMIT, ROLLBACK |
- DDL : Créer une nouvelle table dans la base.
- DML : Ajouter un étudiant ou modifier son prénom.
- DQL : Rechercher tous les étudiants nés après 2001.
- DCL : Donner à un utilisateur le droit de modifier la table
Etudiant. - TCL : Annuler une série d'insertions en cas d'erreur (
ROLLBACK).
Les commandes DML et DQL sont les plus courantes pour interagir avec les données au quotidien. Les commandes DDL et DCL sont essentielles pour la structure et la sécurité de la base.
Structure d'une base de données
Création d'une base de données
CREATE DATABASE Ecole;
USE Ecole;
La commande CREATE DATABASE crée une base nommée Ecole. La commande USE permet de travailler à l'intérieur de cette base. Toutes les commandes suivantes s'appliqueront à cette base tant qu'on ne change pas de contexte.
Création d'une table
CREATE TABLE Etudiant (
idEtudiant INT PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(50) NOT NULL,
prenom VARCHAR(50) NOT NULL,
dateNaissance DATE,
email VARCHAR(100) UNIQUE,
actif BOOLEAN DEFAULT TRUE
);
PRIMARY KEY: identifie chaque ligne de façon unique.AUTO_INCREMENT: la valeur deidEtudiantest générée automatiquement (1, 2, 3…). Plus besoin de la saisir manuellement.NOT NULL: le champ est obligatoire - il ne peut pas être vide.UNIQUE: deux lignes ne peuvent pas avoir la même valeur (ici, deux étudiants ne peuvent pas avoir le même email).DEFAULT TRUE: si on n'indique pas de valeur pouractif, il vautTRUEpar défaut.
Ce que ça donne dans la table
Une fois la table créée, vous pourrez y stocker des données comme :
+------------+--------+--------+---------------+---------------------+-------+
| idEtudiant | nom | prenom | dateNaissance | email | actif |
+------------+--------+--------+---------------+---------------------+-------+
| 1 | Martin | Alice | 2001-05-12 | alice@ecole.fr | 1 |
| 2 | Durand | Lucas | 2000-11-03 | lucas@ecole.fr | 1 |
+------------+--------+--------+---------------+---------------------+-------+
idEtudiant a été généré automatiquement grâce à AUTO_INCREMENT.
Autres contraintes utiles
CREATE TABLE Cours (
idCours INT PRIMARY KEY AUTO_INCREMENT,
intitule VARCHAR(100) NOT NULL,
volumeHoraire INT CHECK (volumeHoraire > 0),
coefficient DECIMAL(3,1) DEFAULT 1.0
);
CHECK: impose une condition logique sur la valeur (ici, le volume horaire doit être positif).DEFAULT 1.0: si aucun coefficient n'est précisé à l'insertion, la valeur 1.0 est utilisée automatiquement.
Bien définir ses contraintes dès la création des tables permet de garantir la cohérence et la qualité des données dans la base. Une contrainte rejetée au niveau de la base vaut mieux qu'une erreur découverte dans l'application.
Modifier la structure d'une table : ALTER TABLE
Après la création, il est possible de modifier la structure d'une table sans la supprimer.
-- Ajouter une colonne
ALTER TABLE Etudiant ADD COLUMN telephone VARCHAR(15);
-- Modifier le type d'une colonne
ALTER TABLE Etudiant MODIFY COLUMN telephone VARCHAR(20);
-- Supprimer une colonne
ALTER TABLE Etudiant DROP COLUMN telephone;
-- Renommer une colonne (MySQL 8+)
ALTER TABLE Etudiant RENAME COLUMN actif TO estActif;
ALTER TABLE fait partie du DDL. Utilisez-le quand vous devez faire évoluer le schéma sans perdre les données existantes. En production, ces modifications doivent être planifiées avec soin (risque de perte de données si on supprime une colonne).
Manipuler les données avec SQL
Insertion de données : INSERT
On insère une ligne dans la table Etudiant. On ne précise pas idEtudiant car il est généré automatiquement par AUTO_INCREMENT. Les colonnes non mentionnées (actif) prendront leur valeur par défaut.
Insérer plusieurs lignes à la fois :
Sans nommer les colonnes (déconseillé) :
-- ⚠️ Déconseillé : fragile si la structure de la table change
INSERT INTO Etudiant
VALUES (NULL, 'Lefevre', 'Luc', '2001-11-30', NULL, TRUE);
Il est toujours préférable de préciser les colonnes dans l'ordre d'insertion. Cela rend le code plus lisible, robuste et évite des erreurs en cas de changement dans la structure de la table.
Lecture des données : SELECT
La commande SELECT permet d'afficher les données souhaitées. Ici, on affiche nom et prenom des étudiants nés après le 1er janvier 2001, triés par nom croissant.
Opérateurs de filtre courants
| Opérateur | Description | Exemple |
|---|---|---|
=, !=, <, > | Comparaison classique | WHERE note > 10 |
BETWEEN ... AND ... | Dans un intervalle (bornes incluses) | WHERE note BETWEEN 10 AND 15 |
IN (...) | Parmi une liste de valeurs | WHERE ville IN ('Lyon', 'Paris') |
LIKE | Correspondance avec un motif | WHERE nom LIKE 'Du%' |
IS NULL / IS NOT NULL | Valeur absente ou présente | WHERE email IS NOT NULL |
Le caractère joker % dans LIKE
% remplace n'importe quelle suite de caractères (y compris vide).
_ remplace exactement un caractère.
Exemples : 'Du%' → commence par "Du" | '%on' → finit par "on" | 'D_pont' → "Dupont", "Damont", etc.
Afficher des valeurs distinctes : DISTINCT
DISTINCT supprime les doublons dans le résultat : si 50 clients habitent Lyon, "Lyon" n'apparaît qu'une fois.
Limiter le nombre de résultats : LIMIT
Retourne uniquement les 10 premiers résultats - utile pour la pagination ou pour tester une requête.
- Évitez
SELECT *dans les applications : préférez lister les colonnes utiles. - Utilisez
WHEREpour limiter le volume de données retourné. - Triez avec
ORDER BYpour faciliter la lecture des résultats. - Utilisez
LIMITpour ne pas surcharger votre application lors des tests.
Mise à jour : UPDATE
On modifie le nom et l'email de l'étudiant dont l'idEtudiant est 2. On peut modifier plusieurs colonnes en les séparant par des virgules dans SET.
Toujours utiliser WHERE pour cibler les lignes à modifier. Un UPDATE Etudiant SET nom = 'Dupond' sans WHERE modifie tous les étudiants de la table - erreur irrécupérable sans sauvegarde.
Suppression : DELETE
Supprime uniquement l'étudiant dont l'idEtudiant est 4. Préférez toujours filtrer sur la clé primaire pour cibler exactement une ligne.
Supprimer toutes les données de la table (dangereux) :
-- Supprime toutes les lignes une par une (lent, journalisé)
DELETE FROM Etudiant;
-- Vide la table d'un coup et réinitialise l'AUTO_INCREMENT (plus rapide, non journalisé)
TRUNCATE TABLE Etudiant;
DELETE vs TRUNCATE
DELETE sans WHERE supprime toutes les lignes mais conserve la structure et peut être annulé avec ROLLBACK.
TRUNCATE vide la table et remet l'AUTO_INCREMENT à 1 - opération non annulable. À réserver aux environnements de développement.
Requêtes avec jointures
Une jointure permet de combiner des données provenant de plusieurs tables. C'est l'opération clé dans une base relationnelle, où les informations sont réparties sur plusieurs tables reliées par des clés.
Données d'exemple
Pour illustrer les jointures, imaginons ces deux tables :
Table Etudiant :
| idEtudiant | nom | prenom |
|---|---|---|
| 1 | Martin | Alice |
| 2 | Durand | Lucas |
| 3 | Leroy | Emma |
Inscription (idCours = 10 = "Maths", 20 = "SQL")
| idEtudiant | idCours |
|---|---|
| 1 | 10 |
| 1 | 20 |
| 2 | 10 |
Emma (id=3) n'a aucune inscription.
Jointure interne (INNER JOIN)
Résultat :
| nom | prenom | idCours |
|---|---|---|
| Martin | Alice | 10 |
| Martin | Alice | 20 |
| Durand | Lucas | 10 |
Jointure interne
Une JOIN (ou INNER JOIN) ne conserve que les lignes ayant une correspondance dans les deux tables. Emma n'apparaît pas car elle n'a aucune inscription.
Jointure externe gauche (LEFT JOIN)
Résultat :
| nom | prenom | idCours |
|---|---|---|
| Martin | Alice | 10 |
| Martin | Alice | 20 |
| Durand | Lucas | 10 |
| Leroy | Emma | NULL |
Jointure externe gauche
Une LEFT JOIN conserve toutes les lignes de la table de gauche (Etudiant), même si elles n'ont pas de correspondance à droite. Emma apparaît avec NULL dans idCours.
Jointure sur 3 tables
On chaîne les jointures pour remonter les données à travers la table de liaison Inscription.
Résumé des types de jointures
| Type de jointure | Résultat attendu |
|---|---|
INNER JOIN | Correspondances exactes dans toutes les tables |
LEFT JOIN | Toutes les lignes de gauche, même sans correspondance (droite = NULL) |
RIGHT JOIN | Toutes les lignes de droite, même sans correspondance (gauche = NULL) |
FULL JOIN | Toutes les lignes des deux tables (non supporté nativement par MySQL) |
- Utilisez
INNER JOINquand vous ne voulez que les données qui ont une correspondance dans toutes les tables. - Utilisez
LEFT JOINquand vous voulez garder tous les enregistrements de la table principale, même sans correspondance. RIGHT JOINest rarement utilisé : on préfère inverser l'ordre des tables et utiliserLEFT JOIN.
Requêtes avec agrégats
Les fonctions d'agrégation permettent de faire des calculs sur plusieurs lignes d'une table. Elles sont très utiles pour obtenir des statistiques ou des résumés de données.
Fonctions d'agrégation disponibles
| Fonction | Rôle | Exemple |
|---|---|---|
COUNT() | Compte le nombre de lignes | COUNT(*), COUNT(idEtudiant) |
SUM() | Somme les valeurs | SUM(montant) |
AVG() | Calcule la moyenne | AVG(note) |
MAX() | Renvoie la valeur maximale | MAX(note) |
MIN() | Renvoie la valeur minimale | MIN(note) |
COUNT(*) vs COUNT(colonne)
COUNT(*) compte toutes les lignes, y compris celles avec des NULL.
COUNT(colonne) ne compte que les lignes où la colonne n'est pas NULL.
Renommer une colonne avec AS
AS donne un alias lisible à la colonne résultante. C'est particulièrement utile avec les agrégats, qui n'ont pas de nom par défaut.
Regrouper des résultats : GROUP BY
Calcule le nombre d'inscrits et la moyenne pour chaque cours.
Filtrer les groupes : HAVING
WHERE vs HAVING
WHERE filtre les lignes avant le regroupement - il s'applique aux données brutes.
HAVING filtre les groupes après le GROUP BY - il s'applique aux résultats agrégés.
On ne peut pas écrire WHERE AVG(note) > 12 : WHERE ne connaît pas encore la moyenne à ce stade.
Exemple complet avec jointure + agrégat
Cette requête :
- Affiche chaque cours avec le nombre d'étudiants inscrits et la moyenne des notes,
- Ne garde que les cours avec une moyenne ≥ 10,
- Trie les résultats par moyenne décroissante.
Ordre d'exécution d'une requête SQL
Il est important de comprendre que SQL n'exécute pas les clauses dans l'ordre où on les écrit.
| Ordre d'exécution | Clause | Rôle |
|---|---|---|
| 1 | FROM + JOIN | Charge les tables et les assemble |
| 2 | WHERE | Filtre les lignes |
| 3 | GROUP BY | Regroupe les lignes restantes |
| 4 | HAVING | Filtre les groupes |
| 5 | SELECT | Sélectionne les colonnes (et applique les agrégats) |
| 6 | DISTINCT | Supprime les doublons |
| 7 | ORDER BY | Trie les résultats |
| 8 | LIMIT | Limite le nombre de lignes retournées |
Pourquoi cet ordre est important
Cela explique pourquoi on ne peut pas utiliser un alias défini dans SELECT dans une clause WHERE : WHERE est exécuté avant SELECT, donc l'alias n'existe pas encore.
En revanche, on peut utiliser cet alias dans ORDER BY (qui vient après).
Créer une table avec une clé étrangère
- Clé primaire composite : le couple
(idEtudiant, idCours)est unique - un étudiant ne peut s'inscrire qu'une seule fois à un même cours. - FOREIGN KEY : crée un lien vers une autre table. Le SGBD vérifie que la valeur existe bien dans la table référencée.
- ON DELETE CASCADE : si un étudiant est supprimé, ses inscriptions sont automatiquement supprimées aussi.
- ON DELETE RESTRICT : si un cours est supprimé mais a des inscrits, la suppression est bloquée. Protection contre les suppressions accidentelles.
Ce que garantit l'intégrité référentielle
Les clés étrangères garantissent l'intégrité référentielle : on ne peut pas créer de liens vers des données inexistantes.
Choisissez entre ON DELETE CASCADE (suppression en cascade) et ON DELETE RESTRICT (blocage) selon le comportement souhaité.