Séance 1 — Cadrage : pourquoi une base de données relationnelle ?

1. Mise en situation : la bibliothèque sans base de données

« On veut gérer les livres d’une bibliothèque : chaque livre a un titre, un auteur, et sait s’il est disponible ou emprunté. On veut pouvoir lister les livres, en ajouter, en supprimer. »

Étape A — la version « structures en mémoire ». Exemple en pseudo-Python orienté objet en utilisant des listes :

class Auteur:
    def __init__(self, id, prenom, nom):
        self.id, self.prenom, self.nom = id, prenom, nom

class Livre:
    def __init__(self, id, titre, auteur, disponible=True):
        self.id, self.titre, self.auteur, self.disponible = id, titre, auteur, disponible

auteurs = [Auteur(1, "George", "Orwell"), ...]
livres  = [Livre(1, "1984", auteurs[0], disponible=False), ...]

Questions :

  1. Que se passe-t-il si le programme s’arrête ? → tout est perdu (problème de persistance).
  2. Que se passe-t-il si deux instances du programme modifient livres en même temps ? → l’une écrase l’autre, ou on obtient un état incohérent (problème de concurrence).
  3. Que se passe-t-il si on supprime auteurs[0] alors qu’un livre le référence ? → le livre pointe vers un objet qui n’existe plus, ou il faut écrire du code de vérification partout (problème d’intégrité).

Étape B — la version « fichiers ». : sérialiser dans un fichier CSV ou JSON.

id,titre,auteur_id,disponible
1,1984,1,0

Cela règle partiellement la persistance, mais aggrave les deux autres problèmes :

Conclusion de la mise en situation :

Problème En mémoire En fichier Ce qu’on attend d’un SGBD
Persistance ✗ ✓ (fragile) ✓ robuste
Concurrence ✗ ✗ ✓ (transactions, verrous)
Intégrité ✗ ✗ ✓ (contraintes déclaratives)
Recherche ✓ (en RAM) ✗ ✓ (index)
Requêtes ad hoc code à écrire code à écrire ✓ (SQL)

D’où l’intérêt de la SGBD.

2. Vocabulaire minimal

SGBD (Système de Gestion de Base de Données) : le logiciel qui stocke, sécurise, interroge et garantit l’intégrité des données. Exemples : MariaDB/MySQL, PostgreSQL, SQLite, Oracle. On précise : le SGBD n’est pas la base ; c’est le moteur.

Base de données : ici, l’ensemble nommé bibliotheque qui regroupe les tables et leur contenu, géré par le SGBD.

Schéma : la description de la structure — quelles tables, quelles colonnes, quels types, quelles contraintes. C’est le « plan » de la base, distinct des données. deux fichiers : schema.sql (le plan) et data.sql (le contenu).

Table : un ensemble de données du même type. Ici auteur et livre. Faites le parallèle avec la classe : une table ≈ la définition d’une classe ; une ligne ≈ une instance.

Ligne (enregistrement / tuple) : un élément de la table. Exemple concret :

(1, '1984', 1, 0)

Colonne (attribut / champ) : une propriété de la table, avec un type. CREATE TABLE livre :

id         INT          NOT NULL AUTO_INCREMENT
titre      VARCHAR(200) NOT NULL
auteur_id  INT          NOT NULL
disponible TINYINT(1)   NOT NULL DEFAULT 1

INT pour les identifiants et la clé étrangère, VARCHAR(200) pour les textes de longueur variable, TINYINT(1) comme booléen (convention MySQL/MariaDB à connaître).

Clé primaire : la colonne qui identifie de façon unique une ligne. Dans auteur c’est id, dans livre c’est id. On insiste : unique (deux auteurs ne peuvent pas avoir le même id) et non nulle (pas de ligne sans identifiant). On fait le lien avec un attribut d’identité dans un objet.

Clé étrangère : une colonne qui référence la clé primaire d’une autre table. Dans livre, auteur_id référence auteur.id. C’est ce qui matérialise la relation « un livre a un auteur » et permet au SGBD de refuser un livre dont l’auteur n’existe pas.

On peut faire un mini-schéma :

auteur                          livre
┌────┬────────┬──────────┐      ┌────┬─────────────────┬───────────┬────────────┐
│ id │ prenom │ nom      │      │ id │ titre           │ auteur_id │ disponible │
├────┼────────┼──────────┤      ├────┼─────────────────┼───────────┼────────────┤
│ 1  │ George │ Orwell   │◄─────│ 1  │ 1984            │ 1         │ 0          │
│ 4  │ Jules  │ Verne    │◄─────│ 4  │ Vingt mille...  │ 4         │ 1          │
│ 11 │ Erskine│ Caldwell │      │ 6  │ Voyage au...    │ 4         │ 1          │
└────┴────────┴──────────┘      └────┴─────────────────┴───────────┴────────────┘
       PK: id                              PK: id    FK: auteur_id → auteur.id

On fait remarquer deux choses sur les données :

SQL : le langage pour interroger et manipuler. Nous verrons bientôt : SELECT (séances 3–4), INSERT/UPDATE/DELETE (séance 5), sous-requêtes et vues (6), droits (7), puis usage depuis le code (8).

3. Lecture guidée du modèle fourni

Analyse et compréhension ligne par ligne :

CREATE TABLE auteur (
  id     INT          NOT NULL AUTO_INCREMENT,
  prenom VARCHAR(100) NOT NULL,
  nom    VARCHAR(100) NOT NULL,
  PRIMARY KEY (id)
);

Questions guidées :

CREATE TABLE livre (
  id         INT          NOT NULL AUTO_INCREMENT,
  titre      VARCHAR(200) NOT NULL,
  auteur_id  INT          NOT NULL,
  disponible TINYINT(1)   NOT NULL DEFAULT 1,
  PRIMARY KEY (id),
  KEY idx_livre_auteur (auteur_id),
  CONSTRAINT fk_livre_auteur
    FOREIGN KEY (auteur_id) REFERENCES auteur (id)
    ON UPDATE CASCADE
    ON DELETE RESTRICT
);

Questions guidées :

Synthèse :

Table Colonnes Clé primaire Clé(s) étrangère(s) Contraintes notables
auteur id, prenom, nom id — prénom et nom obligatoires
livre id, titre, auteur_id, disponible id auteur_id → auteur.id suppression d’auteur restreinte ; disponible par défaut

Message clé : le schéma porte une partie des règles métier (unicité, existence de l’auteur, valeur par défaut). C’est du code déclaratif que le SGBD fait respecter pour tous les programmes, contrairement au code applicatif qui ne protège que l’application qui l’exécute.


TP (1 h 30) — Installation, première connexion, exploration

Livrable : un fichier compte_rendu_seance1.txt contenant les réponses aux questions numérotées et les captures de sortie demandées. Le TP est conçu pour être faisable sans connaissance SQL préalable ; toutes les commandes sont fournies, vous devez les exécuter, observer et commenter.

Étape 0 — Vérifier l’installation (10 min)

Selon l’environnement :

Commande de connexion :

sudo mariadb

Une fois dans le client (avec le prompt MariaDB [(none)]> ), on vérifie le serveur :

MariaDB [(none)]> SELECT VERSION();
+--------------------------------------+
| VERSION()                            |
+--------------------------------------+
| **.*.*-MariaDB-0+deb13u1 from Debian |
+--------------------------------------+
1 row in set (0,001 sec)
MariaDB [(none)]> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| phpmyadmin         |
| sys                |
+--------------------+

Q0 : quelle version du SGBD utilisez-vous ? Combien de bases sont déjà présentes sur le serveur ?

Étape 1 — Importer le schéma et les données (15 min)

Comme nous allons le voir il est possible d’envoyer des requêtes SQL en ligne de commande. Vérifier que vous avez bien les fichiers schema.sql et data.sql demandés puis tapez les commandes suivantes dans une Konsole (pas dans le client mariadb) :

sudo mariadb -e "CREATE DATABASE bibliotheque;"
sudo mariadb bibliotheque < schema.sql
sudo mariadb bibliotheque < data.sql

Vous avez créé une nouvelle base de données bibliotheque ; importé dans cette base la structure décrite par schema.sql, puis rempli cette structure avec les données fournies par data.sql. Ces fichiers sont lisibles, vous pouvez les ouvrir avec kate pour visualiser leur contenu. Puis, dans le client, selectionnez la base bibliotheque et demandez à voir les Tables associées :

MariaDB [(none)]> USE bibliotheque;
MariaDB [bibliotheque]> SHOW TABLES;
+------------------------+
| Tables_in_bibliotheque |
+------------------------+
| auteur                 |
| livre                  |
+------------------------+
2 rows in set (0,000 sec)

MariaDB [bibliotheque]> 

Q1 : combien de tables contient la base bibliotheque ? Listez-les.

Q2 : que se passerait-il si vous relanciez schema.sql une deuxième fois ? (indice : regardez la première ligne du fichier)

Étape 2 — Explorer le schéma (25 min)

a) Description des tables.

Réflechissez à l’endroit où vous devez vous placer pour exécuter les commandes suivantes :

DESCRIBE auteur;
DESCRIBE livre;
-- variante équivalente :
SHOW COLUMNS FROM livre;

Q3 : recopiez la sortie de DESCRIBE livre. Identifiez pour chaque colonne : type, nullabilité, valeur par défaut, rôle (clé primaire, clé étrangère, index).

Q4 : DESCRIBE vous montre-t-il la contrainte de clé étrangère ? Sinon, quelle commande utilisez-vous ? (indice : SHOW CREATE TABLE livre;)

b) Exploration des métadonnées via information_schema.

information_schema est une base « système » qui décrit les autres bases. On peut donc l’interroger en SQL comme n’importe quelle table. On l’a vue suite à la commande SQL ‘SHOW DATABASES;’

-- Toutes les tables de la base bibliotheque
SELECT table_name, table_rows
FROM information_schema.tables
WHERE table_schema = 'bibliotheque';

-- Toutes les colonnes de toutes les tables de la base
SELECT table_name, column_name, data_type, is_nullable, column_default, column_key
FROM information_schema.columns
WHERE table_schema = 'bibliotheque'
ORDER BY table_name, ordinal_position;

-- Les clés primaires et étrangères
SELECT table_name, constraint_name, constraint_type
FROM information_schema.table_constraints
WHERE table_schema = 'bibliotheque';

Q5 : quelle table de bibliotheque a le plus de colonnes ? Lesquelles ?

Q6 : d’après la requête sur table_constraints, quelles contraintes existe-t-il dans la base ? Classez-les par type (PRIMARY KEY, FOREIGN KEY, UNIQUE…).

Q7 : la colonne column_key dans information_schema.columns vaut PRI pour la clé primaire et MUL pour une colonne indexée. Vérifiez-le sur livre. Que constatez-vous pour auteur_id ?

c) Visualisation du schéma. Si un client graphique est disponible (DBeaver, phpMyAdmin), demander une capture du diagramme relationnel généré. Sinon, redessiner au propre le schéma (deux boîtes, une flèche auteur_id → auteur.id). Il est toujours bon de savoir que des outils graphiques existent mais ils sont peu pratiques ; il est tellement plus rapide de relire, modifier et lancer une commande ou un script!

Q8 : joignez le diagramme (capture ou dessin). Combien de relations y voyez-vous ? De quel type (1-1, 1-N, N-N) ?

Étape 3 — Premières lectures : SELECT (25 min)

On ne demande aucune écriture : uniquement de l’observation, pour rester dans l’objectif de la séance.

SELECT * FROM auteur;
SELECT * FROM livre;

Q9 : combien y a-t-il de lignes dans chaque table ? Quelle commande avez-vous utilisée pour le vérifier autrement que « à l’œil » ? (réponse : SELECT COUNT(*) FROM ...)

Q10 : identifiez, dans la table auteur, un auteur qui n’apparaît dans aucun livre. Quelle est la valeur de son id ? Expliquez, en une phrase, pourquoi le SGBD autorise ce cas.

Q11 : identifiez un livre indisponible. Quelle colonne et quelle valeur permettent de le savoir ?

Q12 : dans la table livre, combien de livres sont associés à l’auteur d’id = 4 ? Quelle commande avez-vous écrite pour le savoir ? (indice : WHERE auteur_id = 4 — même si WHERE sera vu formellement en séance 3, on l’autorise ici comme lecture)

Étape 4 — Tester l’intégrité (15 min) — démonstration guidée

C’est le moment de voir le SGBD refuser une opération incohérente. On prévient : l’objectif n’est pas d’apprendre INSERT/DELETE (séance 5), mais d’observer le comportement.

-- 1. Tenter d'insérer un livre avec un auteur inexistant (id 999)
INSERT INTO livre (titre, auteur_id) VALUES ('Livre fantôme', 999);

-- 2. Tenter de supprimer un auteur qui a des livres (Jules Verne, id 4)
DELETE FROM auteur WHERE id = 4;

-- 3. Tenter d'insérer un auteur sans nom
INSERT INTO auteur (prenom) VALUES ('Anonyme');

Q13 : pour chaque commande, recopiez le message d’erreur renvoyé et expliquez quelle contrainte du schéma l’a provoqué (clé étrangère ? NOT NULL ? autre ?).

Q14 : après ces trois tentatives, vérifiez avec SELECT COUNT(*) que la base n’a pas été modifiée. Conclusion : que garantit le SGBD même quand le code applicatif se trompe ?

Étape 5 — Synthèse (10 min)

Q15 : en 5 à 8 lignes, répondez à la question « pourquoi une base de données relationnelle plutôt que des fichiers ou des structures en mémoire ? », en vous appuyant sur au moins trois observations concrètes faites pendant ce TP (persistance, refus d’une donnée incohérente, métadonnées interrogeables, séparation schéma/données…).

À préparer pour la séance 2


Auto-évaluation

Question : Citez les trois limites principales d’un stockage des données en mémoire vive (structures de type listes/objets), et expliquez brièvement chacune.

  1. Persistance : à l’arrêt du programme, toutes les données sont perdues (la mémoire n’est pas conservée).
  2. Concurrence : si deux instances du programme modifient les mêmes données simultanément, l’une peut écraser l’autre ou produire un état incohérent.
  3. Intégrité : rien n’empêche nativement une référence invalide (par exemple un livre pointant vers un auteur supprimé) ; il faut écrire du code de vérification partout.

Question : Le passage d’un stockage en mémoire à un stockage en fichiers règle-t-il tous les problèmes ? Justifiez en indiquant ce qu’il améliore et ce qu’il aggrave.

Non. Le stockage en fichier (CSV, JSON) règle partiellement la persistance, mais aggrave la concurrence (deux processus qui écrivent le même fichier en même temps peuvent le corrompre ou perdre la dernière écriture) et ne règle pas l’intégrité (rien n’empêche d’écrire un auteur_id qui n’existe pas ; c’est au code applicatif de tout vérifier). Il ajoute aussi d’autres défauts : recherche lente (parcours linéaire), absence de types, absence de transactions.

Question : Définissez le SGBD et distinguez-le de la base de données elle-même.

Le SGBD (Système de Gestion de Base de Données) est le logiciel/moteur qui stocke, sécurise, interroge et garantit l’intégrité des données (ex. : MariaDB, MySQL, PostgreSQL, SQLite, Oracle). La base de données est l’ensemble nommé de tables et de données géré par ce moteur (ici la base bibliotheque). Le SGBD n’est donc pas la base : c’est l’outil qui la gère.

Question : Qu’appelle-t-on le schéma d’une base ? Comment se distingue-t-il des données, et quels sont les deux fichiers fournis qui illustrent cette séparation ?

Le schéma est la description de la structure : quelles tables, quelles colonnes, quels types, quelles contraintes. C’est le « plan » de la base. Les données sont le contenu effectivement stocké dans ces tables. Dans le TP, cette séparation est illustrée par schema.sql (le plan : les CREATE TABLE et contraintes) et data.sql (le contenu : les lignes insérées).

Question : Associez chaque terme à sa définition : table, ligne, colonne, clé primaire, clé étrangère.

Question : Dans le schéma fourni, quelle colonne de la table livre est une clé étrangère, et vers quelle colonne pointe-t-elle ? Quel est l’intérêt de cette contrainte pour le SGBD ?

C’est la colonne auteur_id de livre, qui référence auteur.id. Grâce à cette contrainte de clé étrangère, le SGBD refuse l’insertion d’un livre dont l’auteur n’existe pas (par exemple auteur_id = 999). Elle matérialise la relation « un livre a un auteur » et garantit l’intégrité référentielle sans que chaque programme applicatif ait à la vérifier.

Question : Que signifie la mention AUTO_INCREMENT sur la colonne id d’une table ? Et que signifie DEFAULT 1 sur la colonne disponible de livre ?

Question : Que produisent les clauses ON DELETE RESTRICT et ON UPDATE CASCADE dans le CREATE TABLE livre du schéma fourni ?

Question : Remplissez (mentalement ou sur papier) le tableau d’analyse du schéma : pour chaque table, indiquez ses colonnes, sa clé primaire, ses clés étrangères et une contrainte notable.

Table Colonnes Clé primaire Clé(s) étrangère(s) Contrainte notable
auteur id, prenom, nom id — prénom et nom obligatoires (NOT NULL)
livre id, titre, auteur_id, disponible id auteur_id → auteur.id suppression d’auteur restreinte ; disponible vaut 1 par défaut

Question : Un auteur apparaît une seule fois dans la table auteur mais peut être référencé par plusieurs livres. Quel avantage cela procure-t-il par rapport à un stockage où l’on écrirait le nom de l’auteur dans chaque ligne de livre ?

Cela évite la duplication des informations sur l’auteur : on ne répète pas « Jules Verne » dans chaque ligne de livre, on stocke son identifiant (auteur_id). On gagne en cohérence (une seule source de vérité pour le nom de l’auteur : une modification ne se fait qu’à un seul endroit). Cela évite d’avoir un livre dont l’auteur est « Jules Verne » et un autre dont l’auteur est « jules Verne ». On gagne aussi en intégrité, tout en matérialisant la relation « un auteur → plusieurs livres ». C’est tout l’intérêt de la séparation en deux tables reliées par une clé étrangère.

Question : Lors du TP, vous avez tenté d’insérer un livre avec auteur_id = 999. Décrivez le comportement du SGBD et la contrainte responsable.

Le SGBD refuse l’insertion et renvoie une erreur de type « violation de contrainte de clé étrangère » (foreign key constraint fails). La contrainte responsable est la FOREIGN KEY (auteur_id) REFERENCES auteur(id) : aucun auteur d’id 999 n’existe, donc la référence est invalide. Après l’erreur, la base n’a pas été modifiée.

Question : Lors du TP, vous avez tenté de supprimer l’auteur Jules Verne (id 4). Pourquoi le SGBD refuse-t-il ? Que faudrait-il faire pour pouvoir le supprimer légitimement ?

Le SGBD refuse car cet auteur est référencé par des livres et la contrainte est ON DELETE RESTRICT : on ne peut pas supprimer une ligne encore référencée par une clé étrangère. Pour le supprimer légitimement, il faudrait d’abord traiter ses livres : soit les supprimer, soit les réaffecter à un autre auteur (modifier leur auteur_id), de sorte qu’aucune ligne de livre ne référence plus l’id 4.

Question : Lors du TP, vous avez tenté d’insérer un auteur sans fournir de nom. Décrivez la réaction du SGBD et la contrainte en cause.

Le SGBD refuse l’insertion avec une erreur du type « Column ‘nom’ cannot be null » (ou « doesn’t have a default value »). La contrainte responsable est le NOT NULL sur la colonne nom (et prenom) de la table auteur : une valeur absente est interdite. La base reste inchangée.

Question : Quelle base « système » permet d’interroger les métadonnées (tables, colonnes, contraintes) d’une base en SQL, et quelles tables de cette base avez-vous utilisées en TP ?

Il s’agit de information_schema, une base système décrivant les autres bases et interrogeable en SQL comme n’importe quelle table. En TP, on a notamment utilisé information_schema.tables (liste et nombre de lignes des tables), information_schema.columns (colonnes, types, nullabilité, valeur par défaut, column_key) et information_schema.table_constraints (clés primaires, étrangères, unicité…).

Question : Que vous montre la commande DESCRIBE livre; ? Montre-t-elle la contrainte de clé étrangère ? Si non, quelle commande permet de la voir ?

DESCRIBE livre; (ou SHOW COLUMNS FROM livre;) affiche les colonnes de la table avec leur type, leur nullabilité, leur valeur par défaut et leur rôle (column_key : PRI pour la clé primaire, MUL pour une colonne indexée comme auteur_id). Elle ne montre pas la contrainte de clé étrangère elle-même. Pour la voir, on utilise SHOW CREATE TABLE livre; (qui affiche le DDL -Data Definition Language- complet, avec la clause FOREIGN KEY ... REFERENCES ...).

Question : Dans la sortie de DESCRIBE livre, que signifie la valeur MUL dans la colonne Key pour auteur_id ? Et PRI pour id ?

Question : Combien de relations voyez-vous dans le schéma bibliotheque, et de quel type sont-elles (1-1, 1-N, N-N) ? Justifiez à l’aide des données.

Il y a une seule relation : entre auteur et livre, via livre.auteur_id → auteur.id. Elle est de type 1-N (un auteur peut avoir plusieurs livres ; un livre a un seul auteur). Les données le confirment : Jules Verne (id 4) est référencé par deux livres, tandis qu’un livre n’a qu’un seul auteur_id. Il n’y a pas de relation N-N dans ce schéma.

Question : En TP, vous avez identifié un auteur n’ayant aucun livre. Pourquoi le SGBD autorise-t-il ce cas, alors qu’il refuse un livre dont l’auteur n’existe pas ?

Parce que la contrainte de clé étrangère ne s’applique que dans un sens : elle vérifie que tout auteur_id saisi dans livre existe dans auteur (intégrité référentielle côté « livre → auteur »). Elle n’impose rien sur l’existence de livres pour un auteur donné. Un auteur sans livre est donc parfaitement valide : la relation n’est pas obligatoire dans les deux sens. (Ce cas sera exploité en séance 4 avec les jointures externes LEFT JOIN.)

Question : Comment vérifier « autrement qu’à l’œil » le nombre de lignes d’une table ? Donnez la commande.

On utilise la fonction d’agrégation COUNT : SELECT COUNT(*) FROM auteur; et SELECT COUNT(*) FROM livre;. Cela renvoie le nombre exact de lignes, contrairement à une lecture visuelle de SELECT * qui n’est fiable que sur de petits volumes.

Question : Après les trois tentatives d’écriture incohérentes du TP (livre fantôme, suppression d’auteur référencé, auteur sans nom), qu’observez-vous si vous recomptez les lignes ? Que garantit le SGBD même quand le code applicatif se trompe ?

Le recomptage avec SELECT COUNT(*) montre que les tables n’ont pas été modifiées : les trois opérations ont été rejetées en bloc. Le SGBD garantit donc que les contraintes déclaratives du schéma sont toujours respectées, indépendamment du programme qui l’interroge (même un code applicatif buggé ne peut pas insérer une donnée incohérente). C’est là tout l’intérêt du code déclaratif porté par le schéma : il protège la base pour tous les programmes, contrairement au code applicatif qui ne protège que l’application qui l’exécute.

Question : Synthèse : en quelques lignes, argumentez le recours à une base de données relationnelle plutôt qu’à des fichiers ou à des structures en mémoire, en vous appuyant sur au moins trois observations concrètes du TP.

Réponse attendue (forme libre, 5 à 8 lignes) articulant au moins trois arguments parmi :

Question : En vous appuyant sur le TP, expliquez en une phrase la différence entre « le schéma porte les règles métier » et « le code applicatif porte les règles métier ».

Quand les règles sont dans le schéma (contraintes NOT NULL, FOREIGN KEY, UNIQUE, DEFAULT…), le SGBD les fait respecter pour tous les programmes qui accèdent à la base ; quand elles sont dans le code applicatif, elles ne protègent que l’application qui les exécute (un autre programme, un script d’administration ou un bug peuvent contourner le contrôle).

Question : Question ouverte de préparation (séance 2) : si l’on voulait enregistrer les emprunts de livres dans cette base, quelles tables faudrait-il ajouter, et quelles clés étrangères contiendraient-elles ?

Réponse attendue (amorce, sans exigence formelle) : ajouter au minimum une table emprunt (ou emprunt/lecteur) contenant par exemple id (clé primaire), livre_id (clé étrangère → livre.id), lecteur_id (clé étrangère → lecteur.id si l’on ajoute une table lecteur), ainsi que des dates (date_emprunt, date_retour). Les clés étrangères garantiraient qu’on n’enregistre pas un emprunt pour un livre ou un lecteur inexistant. Cette question prépare la séance 2 (contraintes, types de dates, NULL pour la date de retour) et le projet intégrateur.