SQL : interroger, modéliser et exploiter une base de données
Quitter

Leçon 1 sur 14 · Premiers pas en SQL

Bases de données relationnelles : tables, lignes, clés et SGBD

35 min Python 3.12 (Debian, git, pip)

Objectif

Comprendre comment une base de données relationnelle range l'information d'un commerce (clients, produits, commandes), parler le bon vocabulaire, et savoir à quoi servent PostgreSQL, MySQL/MariaDB, SQLite et SQL Server. Vous lancerez vos premières requêtes SQL sur la base d'une vraie boutique en ligne.

L'essentiel

  • Une base de données relationnelle range les données dans des tables ; chaque table a des colonnes (nom, type) et contient des lignes (les enregistrements).
  • Chaque ligne est identifiée par une clé primaire unique (souvent id). Une clé étrangère fait référence à la clé primaire d'une autre table : c'est le « lien » de la base relationnelle.
  • Le SGBD (système de gestion de bases de données) est le logiciel qui stocke les données, applique les règles, gère les accès concurrents et exécute vos requêtes.
  • SQL est le langage normalisé pour parler à tous les SGBD relationnels : SELECT pour lire, INSERT/UPDATE/DELETE pour modifier, CREATE TABLE pour définir.
  • PostgreSQL, MySQL/MariaDB et SQL Server sont des serveurs ; SQLite est une bibliothèque qui lit un simple fichier. Le SQL de base est le même partout ; les détails changent.

Le problème : le cahier et le tableur

La boutique en ligne « Souk Atlas », installée à Casablanca, vend de l'artisanat, des cosmétiques et de l'épicerie fine dans tout le Maroc. Au début, le gérant notait tout dans un tableur :

Date Client Ville Téléphone Produit Qté Prix
03/09 Amina Benali Casablanca 06 … Huile d'argan 250 ml 2 180
03/09 Amina Benali Casablanca 06 … Savon noir 500 g 3 45
18/09 Amina Benalli Casa 06 … Tapis berbère 1 2800

Trois problèmes apparaissent vite :

  1. Répétition : le nom, la ville et le téléphone d'Amina sont recopiés à chaque achat.
  2. Incohérence : « Benalli », « Casa »… Combien de clientes différentes ? Impossible à dire.
  3. Mise à jour risquée : si Amina déménage à Rabat, il faut corriger toutes ses lignes, sans en oublier une.

La base relationnelle résout cela en séparant les sujets dans des tables reliées par des clés.

Tables, lignes, colonnes

Voici la base de la boutique que vous utiliserez dans tous les labs de ce cours :

clients                      produits
+----+--------------+------------+    +----+----------------------+------------+---------+-------+
| id | nom          | ville      |    | id | nom                  | categorie  | prix_ht | stock |
+----+--------------+------------+    +----+----------------------+------------+---------+-------+
|  1 | Amina Benali | Casablanca |    |  3 | Huile d'argan 250 ml | Cosmétique |  180.00 |    40 |
|  2 | Youssef …    | Rabat      |    |  4 | Savon noir 500 g     | Cosmétique |   45.00 |   120 |
+----+--------------+------------+    +----+----------------------+------------+---------+-------+

commandes                                   lignes_commande
+----+-----------+---------------+--------+  +-------------+------------+----------+---------------+
| id | client_id | date_commande | statut |  | commande_id | produit_id | quantite | prix_unitaire |
+----+-----------+---------------+--------+  +-------------+------------+----------+---------------+
|  1 |         1 | 2025-09-03    | livree |  |           1 |          3 |        2 |        180.00 |
|  3 |         1 | 2025-09-18    | livree |  |           1 |          4 |        3 |         45.00 |
+----+-----------+---------------+--------+  +-------------+------------+----------+---------------+

Le vocabulaire :

Terme Signification Exemple
Table (ou relation) un ensemble de données d'un même sujet clients
Colonne (ou attribut) une propriété, avec un type ville, de type texte
Ligne (ou enregistrement, tuple) un élément concret la cliente n° 1, Amina
Valeur le contenu d'une case 'Casablanca'
Schéma la description des tables, colonnes, types et règles « clients a 5 colonnes… »
NULL absence de valeur (inconnue) un client sans e-mail

Dans une table, l'ordre des lignes n'a pas de sens : la base ne garantit aucun ordre tant que vous ne le demandez pas (avec ORDER BY, leçon suivante).

Les clés : ce qui relie les tables

La clé primaire

La clé primaire (primary key) identifie chaque ligne de façon unique et jamais vide. Deux clientes peuvent s'appeler « Amina Benali » ; elles auront deux id différents.

-- La commande numéro 7, et elle seule
SELECT * FROM commandes WHERE id = 7;

On choisit souvent un numéro sans signification (id 1, 2, 3…) plutôt qu'une donnée métier : un numéro de téléphone ou un e-mail peut changer, un id jamais.

La clé étrangère

La colonne client_id de commandes contient l'id d'un client : c'est une clé étrangère (foreign key). Elle répond à « quelle cliente a passé cette commande ? » sans recopier son nom.

commandes.client_id  ───►  clients.id
lignes_commande.commande_id  ───►  commandes.id
lignes_commande.produit_id   ───►  produits.id

Le SGBD peut vérifier ces liens : impossible d'enregistrer une commande pour le client n° 999 s'il n'existe pas, ou de supprimer un client qui a encore des commandes. C'est l'intégrité référentielle (leçon 2.4).

Un fait à un seul endroit

Si Amina déménage à Rabat, on modifie une seule case : clients.ville de la ligne 1. Toutes ses commandes « suivent » automatiquement, parce qu'elles ne contiennent que son numéro. C'est tout l'intérêt du modèle relationnel.

Le SGBD : bien plus qu'un fichier

Un système de gestion de bases de données fait pour vous ce qu'un tableur ne fait pas :

  • stocker de gros volumes et retrouver une ligne parmi des millions en quelques millisecondes (index) ;
  • faire respecter les règles : types, valeurs obligatoires, unicité, liens entre tables ;
  • gérer la concurrence : dix vendeurs et le site web écrivent en même temps sans s'écraser ;
  • garantir les transactions : un paiement est enregistré en entier ou pas du tout, même en cas de coupure de courant ;
  • contrôler les accès : le comptable lit les factures, le site ne peut pas supprimer les tables ;
  • sauvegarder et restaurer.

Client et serveur

PostgreSQL, MySQL/MariaDB et SQL Server fonctionnent en client-serveur : un programme serveur tourne en permanence (sur le VPS de la boutique), garde les fichiers de données et écoute sur le réseau (port 5432 pour PostgreSQL, 3306 pour MySQL). Les clients se connectent : l'application web, l'outil en ligne de commande psql, un logiciel graphique comme DBeaver ou pgAdmin.

  Site web (Node, PHP, Python)  ─┐
  psql (administrateur)         ─┼──►  serveur PostgreSQL :5432  ──►  fichiers de données
  Outil de reporting            ─┘       (un processus par connexion)

Un serveur PostgreSQL gère plusieurs bases (databases) ; chaque base contient des schémas, qui contiennent les tables. On y reviendra en leçon 3.3.

SQLite : la base dans un fichier

SQLite n'a pas de serveur : c'est une bibliothèque intégrée au programme, et toute la base tient dans un seul fichier (boutique.db). Elle équipe les téléphones Android et iOS, les navigateurs, beaucoup d'applications de bureau… et Python l'embarque d'office (module sqlite3). Parfaite pour apprendre, pour une application mobile ou un petit outil ; moins adaptée à un site où des centaines d'utilisateurs écrivent en même temps.

Panorama des SGBD

SGBD Modèle Licence Points forts Usage typique au Maroc
PostgreSQL serveur libre (licence PostgreSQL, très permissive) respect du standard SQL, types riches (JSONB, tableaux, dates), extensions, fiabilité applications web modernes, SaaS, startups, administrations
MySQL serveur libre (GPL) + éditions Oracle très répandu, simple, rapide en lecture hébergements mutualisés, WordPress, PrestaShop
MariaDB serveur libre (GPL) fork communautaire de MySQL, compatible distributions Linux, remplacement de MySQL
SQLite fichier (embarqué) domaine public zéro installation, un fichier, très léger applications mobiles, caisses hors ligne, prototypes
SQL Server serveur propriétaire (Microsoft), édition Express gratuite intégration Windows, .NET, outils BI ERP, banques, grandes entreprises

Ce cours utilise PostgreSQL comme référence et SQLite pour les labs (aucune installation, la base tient dans un fichier). Chaque fois qu'une différence compte, un encadré « SQLite / PostgreSQL » vous le signale.

Ce qui change d'un SGBD à l'autre

Le cœur de SQL (SELECT, WHERE, JOIN, GROUP BY, INSERT…) est commun. Les différences portent surtout sur :

Sujet PostgreSQL MySQL/MariaDB SQLite SQL Server
Limiter les lignes LIMIT 10 LIMIT 10 LIMIT 10 TOP 10 ou OFFSET … FETCH
Numéro automatique GENERATED ALWAYS AS IDENTITY AUTO_INCREMENT INTEGER PRIMARY KEY IDENTITY(1,1)
Dates vrais types date, timestamp DATE, DATETIME texte '2025-09-03' + fonctions date, datetime2
Concaténer 'a' || 'b' CONCAT('a','b') 'a' || 'b' 'a' + 'b'
Types stricts assez stricts souples (« affinité ») stricts

SQL en trente secondes

SQL est un langage déclaratif : vous décrivez ce que vous voulez, pas comment le trouver. Le SGBD choisit la méthode (parcourir la table, utiliser un index…).

-- Lire : les clients de Rabat
SELECT nom, email FROM clients WHERE ville = 'Rabat';

-- Compter les produits
SELECT COUNT(*) FROM produits;

-- Ajouter, modifier, supprimer (leçon 1.4)
INSERT INTO clients (nom, email, ville, inscrit_le)
VALUES ('Imane Fassi', 'imane.fassi@exemple.ma', 'Meknès', '2025-10-01');
UPDATE produits SET stock = 35 WHERE id = 3;
DELETE FROM commandes WHERE id = 4;

Règles d'écriture :

  • une instruction se termine par un point-virgule ; ;
  • les mots-clés (SELECT, FROM) ne sont pas sensibles à la casse ; on les écrit en majuscules par convention, pour les distinguer des noms de tables et de colonnes ;
  • les chaînes s'écrivent entre apostrophes simples : 'Rabat' (les guillemets doubles servent aux noms d'objets en PostgreSQL) ;
  • un commentaire commence par -- et va jusqu'au bout de la ligne ;
  • les retours à la ligne et les espaces sont libres : présentez vos requêtes pour qu'elles se lisent.

On classe souvent les instructions en familles :

Famille Rôle Instructions
DQL (interrogation) lire SELECT
DML (manipulation) modifier les données INSERT, UPDATE, DELETE
DDL (définition) définir la structure CREATE, ALTER, DROP
DCL (contrôle) gérer les droits GRANT, REVOKE
TCL (transactions) valider ou annuler BEGIN, COMMIT, ROLLBACK

Le catalogue : la base se décrit elle-même

Un SGBD range la description des tables… dans des tables. On peut donc interroger la structure en SQL :

-- SQLite : les tables de la base
SELECT name FROM sqlite_schema WHERE type = 'table';

-- PostgreSQL (norme SQL) : les tables du schéma public
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';

Dans l'outil psql de PostgreSQL, des raccourcis font la même chose : \dt liste les tables, \d clients décrit la table clients.

Pièges fréquents

  • Confondre base et tableur : recopier le nom du client dans chaque commande. Un fait doit être stocké à un seul endroit, les autres tables y font référence par la clé.
  • Croire que les lignes ont un ordre : sans ORDER BY, l'ordre affiché est le fruit du hasard et peut changer d'un jour à l'autre.
  • Choisir une clé primaire qui change (téléphone, e-mail, nom) : préférez un identifiant technique.
  • Utiliser des guillemets doubles pour les textes : WHERE ville = "Rabat" fonctionne parfois en SQLite ou MySQL, mais en PostgreSQL c'est le nom d'une colonne. Prenez l'habitude des apostrophes.

Lab

La machine de lab contient la base de la boutique dans le fichier /root/boutique.db (son script de création est lisible dans /root/boutique.sql) et une commande sql pour exécuter vos requêtes :

sql "SELECT * FROM produits;"        # exécuter une requête tapée directement
sql /root/sql/clients.sql            # exécuter le contenu d'un fichier .sql
cat /root/boutique.sql               # lire la structure et les données de départ
python3 -m sqlite3 /root/boutique.db # console SQLite interactive (Ctrl+D pour sortir)

Écrivez chaque requête dans le fichier demandé (par exemple avec echo "SELECT …;" > /root/sql/clients.sql), lancez-la avec sql, puis demandez la vérification. Vous allez :

  1. afficher toute la table clients ;
  2. compter les produits du catalogue ;
  3. retrouver une commande par sa clé primaire ;
  4. interroger le catalogue de la base pour lister ses tables.

Quiz

  1. Quelle est la différence entre une ligne et une colonne d'une table ?
  2. À quoi sert une clé primaire, et pourquoi préférer un id au numéro de téléphone ?
  3. Dans la base de la boutique, quelle colonne est une clé étrangère vers clients ?
  4. Citez une différence de fonctionnement entre SQLite et PostgreSQL.
  5. En PostgreSQL, que désigne "Rabat" (entre guillemets doubles) dans une requête ?
Réponses
  1. Une colonne est une propriété de même type pour tous les éléments (la ville) ; une ligne est un élément concret (la cliente Amina, avec toutes ses valeurs).
  2. Elle identifie chaque ligne de façon unique et non vide ; un téléphone peut changer ou être partagé, alors qu'un identifiant technique ne change jamais.
  3. commandes.client_id, qui contient l'id d'un client.
  4. PostgreSQL est un serveur auquel on se connecte par le réseau, avec utilisateurs et droits ; SQLite est une bibliothèque qui lit directement un fichier, sans serveur (autres réponses possibles : typage souple de SQLite, dates stockées en texte).
  5. Un nom d'objet (une colonne ou une table appelée Rabat), pas une chaîne de caractères : les textes s'écrivent 'Rabat'.

Sources de référence : documentation officielle PostgreSQL (postgresql.org, licence PostgreSQL). Texte original MasterLinux.

Exercices pratiques

À réaliser sur Python 3.12 (Debian, git, pip)

Le terminal en ligne ouvre bientôt. En attendant, réalisez ces tâches sur votre machine Linux, une machine virtuelle ou WSL.

  1. Écrivez dans /root/sql/clients.sql la requête qui affiche toute la table clients (toutes les colonnes, toutes les lignes). Testez-la avec : sql /root/sql/clients.sql
    Afficher un indiceSELECT * FROM nom_de_la_table; — l'étoile veut dire « toutes les colonnes »
    Voir la solution
    echo "SELECT * FROM clients;" > /root/sql/clients.sql

    Vérification : sql --egal /root/sql/clients.sql "SELECT * FROM clients"

  2. Écrivez dans /root/sql/nb-produits.sql une requête qui renvoie le nombre de produits du catalogue (une seule valeur)
    Afficher un indiceLa fonction COUNT(*) compte les lignes : SELECT COUNT(*) FROM …;
    Voir la solution
    echo "SELECT COUNT(*) FROM produits;" > /root/sql/nb-produits.sql

    Vérification : sql --egal /root/sql/nb-produits.sql "SELECT COUNT(*) FROM produits"

  3. La clé primaire de commandes est la colonne id. Écrivez dans /root/sql/commande-7.sql la requête qui affiche la ligne complète de la commande numéro 7, et elle seule
    Afficher un indiceAjoutez une condition : WHERE id = 7
    Voir la solution
    echo "SELECT * FROM commandes WHERE id = 7;" > /root/sql/commande-7.sql

    Vérification : sql --egal /root/sql/commande-7.sql "SELECT * FROM commandes WHERE id = 7"

  4. Écrivez dans /root/sql/tables.sql une requête qui liste le nom de toutes les tables de la base, en interrogeant le catalogue de SQLite (la table sqlite_schema, colonne name, lignes dont type vaut 'table')
    Afficher un indiceSELECT name FROM sqlite_schema WHERE type = 'table'; — les chaînes de caractères s'écrivent entre apostrophes
    Voir la solution
    echo "SELECT name FROM sqlite_schema WHERE type = 'table';" > /root/sql/tables.sql

    Vérification : sql --egal /root/sql/tables.sql "SELECT name FROM sqlite_schema WHERE type = 'table'"

Références officielles consultées : PostgreSQL — What Is PostgreSQL? — https://www.postgresql.org/docs/current/intro-whatis.html ; PostgreSQL — Tutorial : Concepts — https://www.postgresql.org/docs/current/tutorial-concepts.html ; PostgreSQL — Tutorial : Architectural Fundamentals — https://www.postgresql.org/docs/current/tutorial-arch.html ; PostgreSQL — Tutorial : The SQL Language, Introduction — https://www.postgresql.org/docs/current/tutorial-sql-intro.html. Texte original MasterLinux.