Publié le

Qu’est-ce que SQL ? Comprendre son rôle, ses origines et son utilisation

Auteurs

    Qu’est-ce que SQL ? Comprendre son rôle, ses origines et son utilisation

    La plupart des applications modernes, du simple blog aux immenses réseaux sociaux, stockent et récupèrent leurs données avec un langage appelé SQL.

    Dans cet article, vous découvrirez :

    • Ce qu’est SQL et pourquoi il a été créé
    • Comment les bases relationnelles organisent les informations
    • Un exemple concret avec deux tables
    • Comment exécuter de vraies requêtes SQL, notamment des JOIN
    • Pourquoi SQL reste la référence après plus de 50 ans

    Commençons.

    Qu’est-ce que SQL ?

    SQL (Structured Query Language) est un langage de programmation déclaratif créé pour gérer les bases de données relationnelles, organisées autour de tables, de lignes et des relations entre elles.

    SQL permet de :

    • Créer des tables
    • Insérer et modifier des données
    • Interroger les données avec des filtres
    • Joindre des données liées provenant de plusieurs tables
    • Imposer des contraintes, comme l’unicité des adresses courriel ou les clés étrangères

    SQL est utilisé dans de nombreux systèmes de bases relationnelles populaires. Voici quelques exemples :

    • PostgreSQL : une base relationnelle open source avancée avec une prise en charge solide des standards SQL.
    • MySQL : largement utilisé dans les applications web, connu pour sa rapidité et sa simplicité.
    • MariaDB : une version dérivée de MySQL portée par la communauté, avec des fonctionnalités améliorant les performances.
    • SQLite : une base légère fondée sur un fichier, utilisée dans les applications mobiles, les navigateurs et les systèmes embarqués.
    • Microsoft SQL Server : une base commerciale de niveau entreprise avec des outils solides pour Windows et les environnements cloud.
    • Des services SQL entièrement gérés dans le cloud, comme :
      • Amazon RDS
      • Google Cloud SQL
      • PlanetScale Ces plateformes, Amazon RDS, Google Cloud SQL et PlanetScale, gèrent les sauvegardes, la montée en charge, les mises à jour et la maintenance tout en conservant la puissance de SQL.

    Pourquoi SQL a été créé

    Dans les années 1970, chez IBM, les chercheurs Edgar F. Codd et Donald Chamberlin travaillaient sur une meilleure façon de stocker et de récupérer les données. À l’époque, les bases étaient hiérarchiques ou en réseau, et interagir avec elles était :

    • Complexe
    • Source d’erreurs
    • Étroitement lié au stockage physique
    • Difficile à adapter à des requêtes flexibles

    Pour résoudre cela, ils ont introduit le modèle relationnel, qui organise les données dans des tables avec des relations bien définies.

    SQL a été créé parce que :

    1. Les développeurs avaient besoin d’un langage simple et lisible pour interroger les données.
    2. Les entreprises avaient besoin de règles cohérentes pour stocker les relations.
    3. Les données devaient être accessibles sans connaître les détails internes du stockage.

    Le résultat ? SQL est devenu un standard en 1986, avec ANSI SQL, et presque toutes les grandes bases actuelles reposent encore sur lui.

    Comprendre les tables, les colonnes et les relations

    Dans une base relationnelle :

    • Une table ressemble à une feuille de calcul, avec des lignes et des colonnes
    • Une ligne représente un enregistrement
    • Une colonne représente une propriété
    • Une clé primaire identifie chaque ligne de manière unique
    • Une clé étrangère relie une table à une autre

    Examinons un exemple simple avec des utilisateurs et des commandes.

    Exemple de schéma : utilisateurs et commandes

    Table 1 : users

    idname (nom)email (courriel)
    1Alicealice@example.com
    2Bobbob@example.com
    3Carolinecaroline@example.com

    Table 2 : orders

    iduser_idproduct (produit)price (prix)
    11Tasse à café12.99
    21Sweat à capuche39.99
    32Autocollants4.99

    Relation

    • Chaque commande appartient à un utilisateur, avec orders.user_id → users.id.
    • Un utilisateur peut avoir plusieurs commandes, une relation de type un-à-plusieurs.

    Créer les tables : exemple SQL

    CREATE TABLE users (
      id SERIAL PRIMARY KEY,
      name TEXT NOT NULL,
      email TEXT UNIQUE NOT NULL
    );
    
    CREATE TABLE orders (
      id SERIAL PRIMARY KEY,
      user_id INTEGER NOT NULL REFERENCES users(id),
      product TEXT NOT NULL,
      price NUMERIC(10,2) NOT NULL
    );
    

    Cela crée deux tables relationnelles fortement typées avec une contrainte de clé étrangère. Mais que signifie « fortement typées » ? Dans des bases SQL comme PostgreSQL et MySQL, chaque colonne possède un type de données strict :

    • Les chaînes doivent être des chaînes
    • Les nombres doivent être des nombres
    • Les dates doivent être des dates
    • Les types incorrects provoquent des erreurs

    Cela évite des erreurs comme :

    • Enregistrer « vingt dollars » dans une colonne numérique
    • Enregistrer 123 dans un champ d’adresse courriel
    • Enregistrer des dates invalides

    SQLite fonctionne différemment : son typage est flexible, ou dynamique, et les types y sont imposés moins strictement. PostgreSQL est la plus fortement typée des grandes bases de données.

    Création des tables expliquée ligne par ligne

    Table 1 : users

    CREATE TABLE users (
    

    Explication : Cette instruction commence la création d’une table nommée users.

    • Fonctionne dans PostgreSQL, MySQL, MariaDB, SQLite et SQL Server.
    • Une « table » est un ensemble structuré de lignes et de colonnes dans la base.
      id SERIAL PRIMARY KEY,
    

    Explication :

    • id → Le nom de la colonne.

    • SERIAL → Un entier auto-incrémenté, propre à PostgreSQL.

      • Équivalents dans les autres moteurs :

        • MySQL : INT AUTO_INCREMENT
        • SQLite : INTEGER PRIMARY KEY AUTOINCREMENT
    • PRIMARY KEY → Garantit l’unicité et identifie chaque ligne.

      name TEXT NOT NULL,
    

    Explication :

    • name → Une colonne pour stocker du texte.
    • TEXT → Du texte de longueur variable, une chaîne de caractères.
    • NOT NULL → Ne peut pas être vide.

    Fonctionne dans PostgreSQL, MySQL, MariaDB et SQLite. SQL Server utilise toutefois VARCHAR(MAX) à la place de TEXT.

      email TEXT UNIQUE NOT NULL
    

    Explication :

    • email → Stocke l’adresse courriel de l’utilisateur.
    • TEXT → Le type texte.
    • UNIQUE → Empêche les adresses courriel en double.
    • NOT NULL → Un champ obligatoire.

    Fonctionne dans PostgreSQL, MySQL, MariaDB et SQLite, en tenant compte des différences internes du type TEXT.

    );
    

    Explication : Ferme la définition de la table.

    Table 2 : orders

    CREATE TABLE orders (
    

    Commence une table nommée orders. Fonctionne dans tous les principaux moteurs.

      id SERIAL PRIMARY KEY,
    

    Même sens que dans la table users :

    • Clé primaire auto-incrémentée
    • Type propre à PostgreSQL, SERIAL
    • MySQL utilise INT AUTO_INCREMENT
    • SQLite utilise INTEGER PRIMARY KEY AUTOINCREMENT
      user_id INTEGER NOT NULL REFERENCES users(id),
    

    Explication :

    • user_id → Un nombre qui relie la commande à une ligne de users.
    • INTEGER → Un nombre entier.
    • NOT NULL → Chaque commande doit appartenir à un utilisateur.
    • REFERENCES users(id) → Une contrainte de clé étrangère.

    Sens de clé étrangère :

    • Garantit que user_id correspond à un véritable id dans la table users.
    • Si un utilisateur est supprimé, la base applique la relation selon les règles de clé étrangère.

    Compatibilité des moteurs :

    • PostgreSQL : entièrement pris en charge.
    • MySQL/MariaDB : fonctionne, mais exige le moteur de stockage InnoDB.
    • SQLite : pris en charge uniquement si la gestion des clés étrangères est activée, avec PRAGMA foreign_keys = ON;.
      product TEXT NOT NULL,
    

    Stocke le nom du produit acheté.

    • Le type TEXT fonctionne différemment selon les moteurs, mais stocke toujours des chaînes.
    • Champ obligatoire avec NOT NULL.
      price NUMERIC(10,2) NOT NULL
    

    Explication :

    • price → Le coût du produit.

    • NUMERIC(10,2) → Un nombre à précision fixe avec :

      • Jusqu’à 10 chiffres au total
      • 2 chiffres après la virgule

    Ce type convient aux montants monétaires, car il évite les erreurs de calcul en virgule flottante.

    Compatibilité des moteurs :

    • PostgreSQL : prise en charge complète.
    • MySQL : DECIMAL(10,2) est équivalent.
    • SQLite : l’accepte, mais stocke les valeurs en interne en TEXT, INT ou REAL, selon son typage dynamique.
    );
    

    Termine la table.

    Insérer les données d’exemple

    Maintenant que les tables sont créées, insérons les données d’exemple présentées plus haut. Nous ne fournirons pas manuellement de valeurs id. La base les générera automatiquement avec le type auto-incrémenté SERIAL.

    Insérer les données de users

    INSERT INTO users (name, email)
    VALUES
      ('Alice', 'alice@example.com'),
      ('Bob', 'bob@example.com'),
      ('Caroline', 'caroline@example.com');
    

    Insertion dans users expliquée ligne par ligne

    INSERT INTO users (name, email)
    
    • INSERT INTO users Nous ajoutons des lignes à la table users.

    • (name, email) Nous fournissons uniquement name et email, pas id.

      Pourquoi ne pas fournir l’identifiant ? Comme la colonne id utilise un type serial/auto-incrémenté, le SERIAL de PostgreSQL, la base crée automatiquement les identifiants :

    • Premier utilisateur → id = 1

    • Deuxième utilisateur → id = 2

    • Troisième utilisateur → id = 3

    Ce fonctionnement est prévisible dans PostgreSQL, MySQL, MariaDB et SQLite, avec leurs mécanismes respectifs d’auto-incrémentation.

    VALUES
      ('Alice', 'alice@example.com'),
      ('Bob', 'bob@example.com'),
      ('Caroline', 'caroline@example.com');
    
    • VALUES introduit une liste de lignes à insérer.
    • Chaque groupe ( ... ) correspond à une nouvelle ligne.
    • La base attribue automatiquement les identifiants dans l’ordre d’apparition des lignes.

    Table users après insertion :

    idname (nom)email (courriel)
    1Alicealice@example.com
    2Bobbob@example.com
    3Carolinecaroline@example.com

    Même si nous n’avons écrit aucun identifiant manuellement, le mécanisme d’auto-incrémentation assure cet ordre.

    Insérer les données de orders

    Pour insérer dans orders, nous devons fournir user_id, car une commande doit appartenir à un utilisateur précis.

    Même si nous n’avons pas fixé manuellement les identifiants des utilisateurs, nous connaissons leurs valeurs :

    • Alice → Identifiant 1
    • Bob → Identifiant 2
    • Caroline → Identifiant 3

    Ils ont été générés automatiquement dans l’ordre d’insertion. L’auto-incrémentation attribue toujours les identifiants séquentiellement, sauf si des lignes sont supprimées.

    Voici l’insertion :

    INSERT INTO orders (user_id, product, price)
    VALUES
      (1, 'Coffee Mug', 12.99),
      (1, 'Hoodie', 39.99),
      (2, 'Stickers', 4.99);
    

    Insertion dans orders expliquée ligne par ligne

    INSERT INTO orders (user_id, product, price)
    
    • Nous insérons de nouvelles lignes dans la table orders.

    • Nous précisons :

      • user_id → L’utilisateur auquel appartient la commande
      • product → Le nom
      • price → Le coût

    Remarquez à nouveau que nous ne fournissons pas id (orders.id), car il s’auto-incrémente.

    VALUES
      (1, 'Coffee Mug', 12.99),
      (1, 'Hoodie', 39.99),
      (2, 'Stickers', 4.99);
    
    • (1, 'Coffee Mug', 12.99)

      • Cette commande appartient à l’utilisateur 1, Alice.
    • (1, 'Hoodie', 39.99)

      • Une autre commande pour Alice.
    • (2, 'Stickers', 4.99)

      • Une commande pour l’utilisateur 2, Bob.

      Comment connaître l’identifiant de chaque utilisateur ? Parce que :

    1. Les utilisateurs ont été insérés en premier.

    2. Les identifiants auto-incrémentés sont toujours des entiers séquentiels.

    3. Par conséquent :

      • Premier utilisateur inséré → Identifiant 1
      • Deuxième utilisateur inséré → Identifiant 2
      • Troisième utilisateur inséré → Identifiant 3

    Il est ainsi entièrement prévisible de référencer les utilisateurs par leur identifiant.

    Tables finales obtenues

    users

    idname (nom)email (courriel)
    1Alicealice@example.com
    2Bobbob@example.com
    3Carolinecaroline@example.com

    orders

    iduser_idproduct (produit)price (prix)
    11Tasse à café12.99
    21Sweat à capuche39.99
    32Autocollants4.99

    Interroger les données avec SQL

    Voici des requêtes SQL que nous pouvons exécuter sur les deux tables définies plus haut.

    1. Sélectionner tous les utilisateurs

    SELECT * FROM users;
    

    Résultat :

    idname (nom)email (courriel)
    1Alicealice@example.com
    2Bobbob@example.com
    3Carolinecaroline@example.com

    2. Sélectionner les utilisateurs avec un filtre

    SELECT * FROM users
    WHERE email LIKE '%alice@example.com';
    

    Signification :

    • LIKE est un opérateur SQL qui compare du texte à l’aide de motifs.
    • % est un caractère générique qui correspond à n’importe quel nombre de caractères, y compris aucun.

    Ainsi :

    • '%alice@example.com' signifie : « Rechercher tout texte qui se termine par alice@example.com. »

    Cela renvoie la ligne dont l’adresse courriel est exactement :

    alice@example.com
    

    Mais correspondrait aussi à des valeurs comme :

    • test-alice@example.com
    • hello.alice@example.com
    • anythingalice@example.com

    Si elles existaient.

    Résultat :

    idname (nom)email (courriel)
    1Alicealice@example.com

    Cette requête renvoie uniquement l’utilisateur dont l’adresse courriel correspond au filtre.

    3. Insérer une nouvelle commande

    INSERT INTO orders (user_id, product, price)
    VALUES (2, 'T-Shirt', 29.99);
    

    Table orders après insertion :

    iduser_idproduct (produit)price (prix)
    11Tasse à café12.99
    21Sweat à capuche39.99
    32Autocollants4.99
    42T-shirt29.99
    • La nouvelle ligne possède id = 4, généré automatiquement.
    • user_id = 2 relie cette commande à Bob.

    Les jointures : une fonctionnalité puissante de SQL

    Les jointures permettent d’interroger des données liées dans plusieurs tables.

    Explorons-les avec nos tables users et orders.

    Exemple 1 : INNER JOIN, le plus courant

    Récupérer chaque commande avec l’utilisateur qui l’a passée.

    SELECT users.name, orders.product, orders.price
    FROM orders
    INNER JOIN users
      ON orders.user_id = users.id;
    

    Résultat :

    name (nom)product (produit)price (prix)
    AliceTasse à café12.99
    AliceSweat à capuche39.99
    BobAutocollants4.99
    BobT-shirt29.99

    Bob apparaît désormais deux fois à cause de la nouvelle commande insérée précédemment :

    INSERT INTO orders (user_id, product, price)
    VALUES (2, 'T-Shirt', 29.99);
    

    Exemple 2 : LEFT JOIN

    Récupérer tous les utilisateurs, même ceux qui n’ont pas de commande.

    SELECT users.name, orders.product
    FROM users
    LEFT JOIN orders
      ON users.id = orders.user_id;
    

    Résultat :

    name (nom)product (produit)
    AliceTasse à café
    AliceSweat à capuche
    BobAutocollants
    BobT-shirt
    Carolinenull

    Caroline apparaît avec null, car elle n’a pas de commande.

    Exemple 3 : requête d’agrégation

    Montant total dépensé par chaque utilisateur :

    SELECT users.name, SUM(orders.price) AS total_spent
    FROM users
    LEFT JOIN orders ON users.id = orders.user_id
    GROUP BY users.name;
    

    Résultat :

    name (nom)total_spent (total dépensé)
    Alice52.98
    Bob34.98
    Carolinenull

    Explication

    • Alice : 12.99 + 39.99 = 52.98
    • Bob : 4.99 + 29.99 = 34.98
    • Caroline : aucune commande → NULL

    Où en apprendre davantage ?

    Pour terminer

    SQL existe depuis plus de 50 ans et fait toujours fonctionner les applications les plus importantes au monde, car il est :

    • Déclaratif
    • Cohérent
    • Prévisible
    • Capable de monter en charge
    • Soutenu par des décennies de recherche

    Une fois le fonctionnement des tables et des jointures compris, SQL devient l’un des outils les plus puissants de votre boîte à outils de programmation.