Le site du prof

Base de données

Niveau 0

Authentifiez-vous pour suivre votre progression !


Le langage SQL

Pour communiquer avec le SGBD, on utilise des requêtes. Ce sont des demandes que l'on formule au système et auxquelles il fournit une réponse. C'est exactement le même principe qu'avec les requêtes HTTP dans la relation client-serveur

Pour formuler ces requêtes, on utilise le langage SQL. Il s'agit d'un langage déclaratif, et pas d'un langage de programmation. En effet, on demande au SGBD de lire ou d'accéder à une partie de la base, mais c'est lui qui choisit comment il va faire.

Clause SELECT : Les requêtes d'accès en lecture

Commencons par un exemple. Considérons la relation suivante :

Livres
ID Titre Auteur Parution Genre Stock
101 Le Petit Prince Antoine de Saint-Exupéry 1943 Roman 4
102 1984 George Orwell 1949 Science-fiction 2
103 Orgueil et Préjugés Jane Austen 1813 Roman 3
104 Le Seigneur des Anneaux J.R.R. Tolkien 1954 Aventure 5
105 Harry Potter à l'école des sorciers J.K. Rowling 1997 Aventure 4
106 Les Misérables Victor Hugo 1862 Roman 3
107 Le Comte de Monte-Cristo Alexandre Dumas 1844 Aventure 6
108 Bel-Ami Guy de Maupassant 1885 Roman 4
109 Fondation Isaac Asimov 1951 Science-fiction 7
110 Dune Frank Herbert 1965 Science-fiction 5

Supposons que je veuille afficher l'ensemble des titres des livres de la base de données. La requête à écrire sera celle-ci :

SELECT Titre FROM Livres;

Le SGBD renvoie :

Titre
___________________________________

Le Petit Prince
1984
Orgueil et Préjugés
Le Seigneur des Anneaux
Harry Potter à l'école des sorciers
Les Misérables
Le Comte de Monte-Cristo
Bel-Ami  
Fondation
Dune

Il est également possible d'ajouter d'autres attributs. Si on veut également afficher l'auteur et l'année de parution, on écrira cette requête :

SELECT Titre, Auteur, Parution FROM Livres;
Titre                                   Auteur                      Parution
____________________________________________________________________________

Le Petit Prince                         Antoine de Saint-Exupéry    1943
1984                                    George Orwell               1949
Orgueil et Préjugés                     Jane Austen                 1813
Le Seigneur des Anneaux                 J.R.R. Tolkien              1954
Harry Potter à l'école des sorciers     J.K. Rowling                1997
Les Misérables                          Victor Hugo                 1862
Le Comte de Monte-Cristo                Alexandre Dumas             1844
Bel-Ami                                 Guy de Maupassant           1885
Fondation                               Isaac Asimov                1951
Dune                                    Frank Herbert               1965

Remarque

Enfin, on peut également utiliser le symbole * en tant que "wild card", que l'on pourrait traduire par "joker". Il signifie que l'on souhaite afficher tous les attributs.

SELECT * FROM Livres;

Clause WHERE : Ajout de conditions

Supposons maintenant que je ne veuille pas afficher toute la base, mais seulement une partie, selon des conditions à définir. Par exemple, afficher les titres des oeuvres parues après 1900 :

SELECT Titre FROM Livres WHERE Parution>1900;
Titre
___________________________________

Le Petit Prince
1984
Le Seigneur des Anneaux
Harry Potter à l'école des sorciers
Fondation
Dune

Le mot clé WHERE est utilisé dans la plupart des requêtes. On peut également ajouter les mots clés AND et OR pour gérer de la logique.

Order By, Distinct et Fonctions d'agrégation

  • ORDER BY permet de choisir un attribut pour trier les résultats. Il s'agit de l'ordre croissant par defaut, ORDER BY ... ASC, mais on peut choisir de trier dans l'ordre décroissant en écrivant ORDER BY ... DESC
  • DISTINCT permet de n'afficher que des résultats distincts.
  • Les fonctions d'agrégation sont un peu à part. Elles ne renvoient pas un tableau mais un résultat unique, calculé à partir des enregistrements retournés par SELECT :
    • COUNT compte le nombre d'enregistrements retournés par la requête et n'affiche que le résultat.
    • SUM affiche la somme des valeurs retournées par la requête et n'affiche que le résultat.
    • AVG affiche la moyenne des valeurs retournées par la requête.
    • MIN et MAX affichent la valeur minimale/maximale des valeurs retournées par la requête.

On peut aussi écrire la requête sur plusieurs lignes pour améliorer la lisibilité. C'est le point virgule qui valide la requête.

SELECT  
    FROM Livres 
     
      ;
ID      Titre                                   Auteur                      Parution    Genre               Stock
_________________________________________________________________________________________________________________

101     Le Petit Prince                         Antoine de Saint-Exupéry    1943        Roman               4
102     1984                                    George Orwell               1949        Science-fiction     2
103     Orgueil et Préjugés                     Jane Austen                 1813        Roman               3
104     Le Seigneur des Anneaux                 J.R.R. Tolkien              1954        Aventure            5
105     Harry Potter à l'école des sorciers     J.K. Rowling                1997        Aventure            4
106     Les Misérables                          Victor Hugo                 1862        Roman               3
107     Le Comte de Monte-Cristo                Alexandre Dumas             1844        Aventure            6
108     Bel-Ami                                 Guy de Maupassant           1885        Roman               4
109     Fondation                               Isaac Asimov                1951        Science-fiction     7
110     Dune                                    Frank Herbert               1965        Science-fiction     5

Clause INSERT INTO : Création d'un enregistrement

Pour ajouter un enregistrement à une relation, on utilise le mot clé INSERT INTO, suivi de la table, puis du mot VALUES et des valeurs à ajouter, sous forme de tuple.

INSERT INTO Livres VALUES (111, 'L\'Assassin Royal', 'Robin Hobb', 1995, 'Aventure', 2);

Remarques

Trois remarques ici :

  • On utilise des apostrophes pour délimiter les chaînes de caractères en SQL plutôt que les guillemets.
  • Pensez donc à échapper les apostrophes présentes dans les noms avec le caractère backslash \.
  • On peut également ajouter un enregistrement sans renseigner tous les attributs, mais il faut alors préciser lesquels on fournit. L'ordre n'est pas important :
    INSERT INTO Livres (Auteur, Titre) VALUES ('H.P. Lovecraft', 'L\'appel de Cthulhu');

Clause UPDATE ... SET : Modification d'un enregistrement

On peut modifier les valeurs d'un enregistrement avec la clause UPDATE, suivie de la relation à modifier, puis SET suivi des attributs à modifier avec leur nouvelle valeur.

UPDATE Livres 
    SET Parution = 1928, Genre = 'Horreur', Stock = 4 
    WHERE Titre = 'L\Appel de Cthulhu';

Remarques

  • En SQL, le symbole == n'existe pas. On utilise aussi le symbole = pour tester l'égalité dans une clasue WHERE.
  • Il est très rare d'utiliser une clause UPDATE sans clause WHERE. Dans le cas contraire, on aurait modifié tous les enregistrement de la base et on leur aurait affecté les mêmes valeurs pour Parution, Genre et Stock. C'est un moyen assez classique d'altérer gravement une base de données.

Clause DELETE : Suppresion d'un enregistrement

Pour supprimer un enregistrement, on utilise les mots clés DELETE FROM, suivis de la table.

Là encore, dans la plupart des cas, on voudra ajouter une clause WHERE pour préciser les enregistrements à supprimer. Sinon, toutes les lignes sont supprimées et la table sera vide.

DELETE FROM Livres WHERE Stock = 0;

Clause JOIN : Jointure entre deux relations

Considérons le schéma relationnel suivant, utilisé pour un système de gestion de commandes.

  • Clients (id INT, nom TEXT, email TEXT)
  • Commandes (id INT, date DATE, montant REAL, #id_client INT)

Exemple:

Clients
id nom email
1 Dupont dupont@example.com
2 Martin martin@example.com
3 Bernard bernard@example.com
Commandes
id date montant id_client
1001 2025-08-01 150.00 1
1002 2025-08-05 200.50 2
1003 2025-08-10 75.30 1
1004 2025-08-15 300.00 3

Supposons que l'on veuille contacter le client de la commande n°1004. Il n'y a pas de relation qui me permette directement de faire le lien entre l'id de commande, et l'adresse mail du client correspondant. Il faut donc que je me serve de la clé étrangère id_client de la relation commande, pour accéder à l'email du client correspondant dans la relation Clients. On pourrait le faire avec deux requêtes SELECT :

SELECT id_client FROM Commandes WHERE id=1004;

Le SGBD renverrait alors la valeur 3, qui me permettrait d'effectuer la requête suivante :

SELECT email FROM Clients WHERE id=3;

Le SGBD renverrait alors ce que je souhaitais au départ : l'adresse mail bernard@example.com

La clause JOIN permet de faire tout ceci en une seule requête :

SELECT Clients.email
    FROM Clients JOIN Commandes
    ON Commandes.id_client=Clients.id
    WHERE Commandes.id=1004;

Explications

Décortiquons la requête, ligne par ligne :

  • l1 :
    • On souhaite lire une information dans la base, il s'agit donc bien d'une requête SELECT.
    • Au final, tout ce qui m'intéresse est la valeur de l'attribut email de la relation Clients.
    • La notation pointée permet d'éviter les conflits entre les noms d'attribut des différentes relations. Clients.email indique qu'il s'agit de l'attribut email de la relation Clients. Ce n'est pas obligatoire tant que tous les noms sont différents, mais c'est une bonne habitude à prendre dès qu'on utilise des requêtes avec plusieurs relations. Ici, il pourrait y avoir un conflit avec le nom id si on ne précise pas de quelle relation il s'agit.
  • l2 : On fait une jointure : On indique que l'on récupère des informations depuis les deux relations Clients et Commandes que l'on relie ensemble.
  • l3 : On précise comment on fait la jointure, autrement dit quelle est la conditions qui permet d'aligner les enregistrements de chaque relation. Ici, on associe les clés étrangères de la relation Commandes aux clés primaires correspondantes dans la relation Client.
  • l4 : La clause WHERE permet de sélectionner uniquement la ligne qui contient l'id de commande 1004.

Jointures entre plus de deux tables

On peut aussi avoir besoin de faire des jointures entre plus de deux tables. Considérons le schéma relationnel suivant :

  • Gares (id INT, nom TEXT, ville TEXT)
  • Trains (id INT, numero TEXT, type TEXT)
  • Voyages (id INT, #id_train TEXT, #id_gare_depart INT, #id_gare_arrivee INT, heure_depart DATETIME, heure_arrivee DATETIME)

Supposons que l'on souhaite connaître la liste de tous les numeros de train au départ de Toulon. Il faut utiliser la relation Gares pour connaître les noms des villes, la relation Voyages pour connaître les gares de départ, et la relation Trains pour les numéros de train. On peut faire une requête JOIN exactement de la même manière que précédemment.

Je vais en plus utiliser le mot clé AS pour créer des alias : des noms alternatifs qui me semblent plus pratiques à écrire.

SELECT t.numero
    FROM Trains AS t 
    JOIN Voyages AS v
        ON t.id=v.id_train
    JOIN Gares AS g
        ON g.id=v.id_gare_depart
    WHERE g.ville='Toulon';