CPGE MP / PSI · Informatique · 2ᔉ pĂ©riode

Les bases de données relationnelles

Pr. EL HADIQ Zouhair

ModÚle relationnel, modÚle entité-association, clés primaires et étrangÚres, et manipulation des données avec le langage SQL sous SQLite.

Objectifs du chapitre. À la fin de cette partie, vous saurez :

Sommaire

  1. Vocabulaire des bases de données relationnelles
  2. Le modÚle entité-association
  3. Clés primaires et clés étrangÚres
  4. Du modĂšle E/A au modĂšle relationnel
  5. SQL : manipulation des donnĂ©es (INSERT, UPDATE, DELETE)
  6. Interroger une base : SELECT, projection et sĂ©lection
  7. Opérateurs ensemblistes et produit cartésien
  8. Les jointures internes
  9. Renommage avec AS
  10. Fonctions d'agrégation et GROUP BY
  11. Filtrer les agrégats avec HAVING
  12. Tri et limitation : ORDER BY, LIMIT, OFFSET
  13. RequĂȘtes imbriquĂ©es (sous-requĂȘtes)
  14. Récapitulatif
La base fil rouge de ce cours.

Tous les exemples utilisent une petite base d'une universitĂ©, composĂ©e de quatre tables :

1. Vocabulaire des bases de données relationnelles

Une base de donnĂ©es est un ensemble structurĂ© de donnĂ©es mĂ©morisĂ©es de façon durable et partagĂ©es par plusieurs utilisateurs. Un SGBD (SystĂšme de Gestion de Base de DonnĂ©es) est le logiciel qui gĂšre cette base : il en assure le stockage, la cohĂ©rence et l'interrogation. Dans ce cours, le SGBD utilisĂ© est SQLite, un SGBD lĂ©ger qui stocke toute la base dans un seul fichier.

Dans le modĂšle relationnel, les donnĂ©es sont organisĂ©es en tables. Le vocabulaire est le suivant :

Terme Synonyme Signification
TablerelationTableau à deux dimensions décrivant une catégorie d'objets.
Attributcolonne, champUne propriĂ©tĂ© dĂ©crivant les objets (ex. : nom, age).
Enregistrementligne, n-uplet, tupleUn objet de la table (une valeur par attribut).
DomainetypeEnsemble des valeurs possibles d'un attribut (entier, texte
).
SchĂ©ma—Description de la table : nom + liste des attributs et de leurs domaines.

Le schĂ©ma de la table des Ă©tudiants se note : Etudiant(id, nom, prenom, age, id_dep). Voici un extrait du contenu (les enregistrements) :

idnomprenomageid_dep
1AlamiSara191
2BennaniKarim201
3ChraibiYasmine212
Domaines (types SQLite). SQLite reconnaĂźt principalement : INTEGER (entiers), REAL (rĂ©els), TEXT (chaĂźnes), NULL (valeur absente). La valeur spĂ©ciale NULL signifie « information inconnue ou non renseignĂ©e Â» ; elle n'est Ă©gale Ă  rien, pas mĂȘme Ă  NULL.

2. Le modÚle entité-association

Avant de créer les tables, on conçoit la base au moyen d'un modÚle entité-association (modÚle E/A, ou modÚle entité-relation). C'est un schéma de conception, indépendant du SGBD, qui décrit ce que représente la base.

Notion Définition
EntitĂ©Un type d'objet du monde rĂ©el que l'on veut dĂ©crire (ex. : Étudiant, Module).
AttributUne propriĂ©tĂ© d'une entitĂ© ou d'une association (ex. : nom, age).
IdentifiantUn (ou plusieurs) attribut qui distingue de façon unique chaque objet de l'entité.
AssociationUn lien sĂ©mantique entre deux entitĂ©s (ex. : un Ă©tudiant s'inscrit Ă  un module).
CardinalitésCombien d'objets de chaque cÎté participent à l'association (1-1, 1-*, *-*).

Une cardinalitĂ© indique, pour une entitĂ©, combien d'occurrences de l'autre entitĂ© lui sont reliĂ©es :

Étudiant Module s'inscrit * * attribut de l'association : note
IdĂ©e clĂ©. Le modĂšle E/A rĂ©pond Ă  la question « de quoi parle ma base ? Â» avant de rĂ©pondre Ă  « comment la stocker ? Â». On le traduit ensuite mĂ©caniquement en tables (section 4).

3. Clés primaires et clés étrangÚres

Clé primaire

La clĂ© primaire d'une table est un attribut (ou un groupe d'attributs) dont la valeur identifie de façon unique chaque enregistrement. Deux lignes ne peuvent pas avoir la mĂȘme valeur de clĂ© primaire, et celle-ci ne peut jamais ĂȘtre NULL. Dans Etudiant, la clĂ© primaire est id.

Une clĂ© primaire n'est pas forcĂ©ment rĂ©duite Ă  une seule colonne, mĂȘme si c'est le cas le plus frĂ©quent. Dans Inscription, le couple (id_etudiant, code_module) joue le rĂŽle de clĂ© primaire : un Ă©tudiant ne s'inscrit qu'une fois Ă  un module donnĂ©.

Clé étrangÚre

Une clĂ© Ă©trangĂšre est un attribut d'une table qui rĂ©fĂ©rence la clĂ© primaire d'une autre table. Elle matĂ©rialise le lien entre deux tables et garantit la cohĂ©rence rĂ©fĂ©rentielle : une valeur de clĂ© Ă©trangĂšre doit correspondre Ă  une ligne existante dans la table rĂ©fĂ©rencĂ©e.

Dans Etudiant, l'attribut id_dep est une clĂ© Ă©trangĂšre qui rĂ©fĂ©rence Departement(id) : il indique Ă  quel dĂ©partement appartient chaque Ă©tudiant.

CREATE TABLE Departement (
    id   INTEGER PRIMARY KEY,
    nom  TEXT NOT NULL
);

CREATE TABLE Etudiant (
    id      INTEGER PRIMARY KEY,
    nom     TEXT NOT NULL,
    prenom  TEXT,
    age     INTEGER,
    id_dep  INTEGER,
    FOREIGN KEY (id_dep) REFERENCES Departement(id)
);
Clé primaire Clé étrangÚre
Identifie une ligne de SA table.Pointe vers une ligne d'UNE AUTRE table.
Unique, jamais NULL.Peut se rĂ©pĂ©ter, peut ĂȘtre NULL.
Une seule par table.Plusieurs possibles par table.

4. Du modĂšle E/A au modĂšle relationnel

On transforme le schéma E/A en tables selon des rÚgles systématiques.

RĂšgle 1 — Une entitĂ© devient une table

Chaque entitĂ© devient une table. Ses attributs deviennent des colonnes et son identifiant devient la clĂ© primaire. Ainsi : ÉtudiantEtudiant(id, nom, prenom, age) et ModuleModule(code, intitule, credits).

RĂšgle 2 — Association 1-1 ou 1-* : clĂ© Ă©trangĂšre

Pour une association 1 - *, on ajoute dans la table du cĂŽtĂ© « plusieurs Â» une clĂ© Ă©trangĂšre rĂ©fĂ©rençant la clĂ© primaire du cĂŽtĂ© « un Â». Un dĂ©partement contient plusieurs Ă©tudiants (1-*) : on ajoute donc id_dep dans Etudiant.

Pour une association 1 - 1, la clĂ© Ă©trangĂšre peut ĂȘtre placĂ©e dans l'une ou l'autre des deux tables (souvent avec une contrainte d'unicitĂ©).

Rùgle 3 — Association *-* : une table de liaison

Une association * - * ne peut pas se traduire par une simple clĂ© Ă©trangĂšre. On la dĂ©compose en deux associations 1 - * en crĂ©ant une table de liaison (table d'association). Sa clĂ© primaire est composĂ©e des deux clĂ©s Ă©trangĂšres vers les entitĂ©s liĂ©es ; les attributs de l'association y sont ajoutĂ©s.

Etudiant Inscription (id_etudiant, code_module, note) Module 1* *1
CREATE TABLE Module (
    code     TEXT PRIMARY KEY,
    intitule TEXT NOT NULL,
    credits  INTEGER
);

CREATE TABLE Inscription (
    id_etudiant  INTEGER,
    code_module  TEXT,
    note         REAL,
    PRIMARY KEY (id_etudiant, code_module),
    FOREIGN KEY (id_etudiant) REFERENCES Etudiant(id),
    FOREIGN KEY (code_module) REFERENCES Module(code)
);

5. SQL : manipulation des données

Le SQL (Structured Query Language) est le langage standard d'interrogation et de manipulation des bases relationnelles. Une instruction SQL s'appelle une requĂȘte. Cette section prĂ©sente les trois requĂȘtes qui modifient les donnĂ©es.

INSERT INTO — insĂ©rer des lignes

INSERT INTO Etudiant (id, nom, prenom, age, id_dep)
VALUES (1, 'Alami', 'Sara', 19, 1);

-- plusieurs lignes d'un coup :
INSERT INTO Departement (id, nom) VALUES
    (1, 'Mathematiques'),
    (2, 'Informatique');
Les chaßnes de caractÚres sont entre apostrophes simples '
'. Si l'on omet la liste des colonnes, il faut fournir une valeur pour chaque colonne, dans l'ordre du schéma.

UPDATE — modifier des lignes

UPDATE Etudiant
SET age = 22
WHERE id = 3;
Attention. Un UPDATE (ou DELETE) sans clause WHERE s'applique à toutes les lignes de la table. Toujours vérifier la condition avant d'exécuter.

DELETE FROM — supprimer des lignes

DELETE FROM Etudiant
WHERE age < 18;

6. Interroger une base : SELECT, projection et sélection

La requĂȘte SELECT extrait des donnĂ©es sans les modifier. Sa forme de base :

SELECT  <colonnes>        -- projection
FROM    <table>
WHERE   <condition>;      -- sélection

Projection (choix des colonnes)

La projection garde certaines colonnes. En algĂšbre relationnelle on la note π (pi). SELECT nom, prenom FROM Etudiant; correspond Ă  πnom, prenom(Etudiant). Le symbole * sĂ©lectionne toutes les colonnes.

Sélection (choix des lignes)

La sĂ©lection garde les lignes vĂ©rifiant une condition. En algĂšbre relationnelle on la note σ (sigma). SELECT * FROM Etudiant WHERE age ≥ 20; correspond Ă  σage ≥ 20(Etudiant).

DISTINCT — Ă©liminer les doublons

Le mot-clĂ© DISTINCT supprime les lignes en double dans le rĂ©sultat. Pour obtenir la liste des Ăąges sans rĂ©pĂ©tition :

SELECT DISTINCT age FROM Etudiant;

Opérateurs de condition

Opérateur RÎle Exemple
= != < > <= >=Comparaisonsage >= 20
AND OR NOTConnecteurs logiquesage > 18 AND id_dep = 1
INAppartenance Ă  une listeid_dep IN (1, 3)
BETWEEN 
 AND 
Encadrement (bornes incluses)age BETWEEN 19 AND 21
LIKEMotif texte (% = toute suite, _ = un caractĂšre)nom LIKE 'A%'
Le motif LIKE. 'A%' = commence par A ; '%i' = finit par i ; '%ar%' = contient « ar Â» ; '_a%' = a un « a Â» en 2ᔉ position.

7. Opérateurs ensemblistes et produit cartésien

On peut combiner les rĂ©sultats de deux requĂȘtes SELECT qui ont le mĂȘme nombre de colonnes, de types compatibles, par les opĂ©rateurs ensemblistes :

Opérateur Ensemble Résultat
UNIONA ∪ BLignes de l'une OU l'autre (doublons supprimĂ©s).
INTERSECTA ∩ BLignes prĂ©sentes dans les deux.
EXCEPTA − BLignes de A absentes de B (diffĂ©rence).
SELECT nom FROM Etudiant WHERE id_dep = 1
EXCEPT
SELECT nom FROM Etudiant WHERE age > 20;

Produit cartésien

Le produit cartĂ©sien de deux tables associe chaque ligne de la premiĂšre Ă  chaque ligne de la seconde. Si A a m lignes et B a n lignes, le rĂ©sultat en a m × n. On l'obtient en listant deux tables dans le FROM :

SELECT * FROM Etudiant, Departement;   -- toutes les combinaisons
Le produit cartĂ©sien brut combine des lignes qui n'ont rien Ă  voir entre elles : il faut le filtrer. C'est exactement ce que fait la jointure (section suivante).

8. Les jointures internes

Une jointure interne combine les lignes de deux tables en ne gardant que les couples qui vérifient une condition de liaison, typiquement l'égalité d'une clé étrangÚre et d'une clé primaire. C'est un produit cartésien immédiatement filtré.

SELECT Etudiant.nom, Departement.nom
FROM   Etudiant
JOIN   Departement ON Etudiant.id_dep = Departement.id;

On relie ainsi chaque Ă©tudiant au nom de son dĂ©partement. Pour une requĂȘte croisant trois tables (les notes par module), on enchaĂźne les jointures :

SELECT Etudiant.nom, Module.intitule, Inscription.note
FROM   Inscription
JOIN   Etudiant ON Inscription.id_etudiant = Etudiant.id
JOIN   Module   ON Inscription.code_module = Module.code;
PrĂ©fixer les colonnes. Quand une colonne porte le mĂȘme nom dans deux tables (ici nom), on lĂšve l'ambiguĂŻtĂ© en Ă©crivant Table.colonne.

9. Renommage avec AS

Le mot-clĂ© AS donne un alias (nom temporaire) Ă  une colonne ou Ă  une table, le temps de la requĂȘte. Cela rend les rĂ©sultats plus lisibles et raccourcit les jointures.

SELECT  E.nom AS etudiant,
        D.nom AS departement
FROM    Etudiant AS E
JOIN    Departement AS D ON E.id_dep = D.id;

Ici la colonne rĂ©sultat s'appelle etudiant au lieu de nom, et l'on Ă©crit E et D Ă  la place des noms complets. Le renommage de table est indispensable pour l'auto-jointure (joindre une table avec elle-mĂȘme).

10. Fonctions d'agrégation et GROUP BY

Une fonction d'agrĂ©gation calcule une valeur unique Ă  partir d'un ensemble de lignes :

FonctionCalcule
COUNT(*)le nombre de lignes
SUM(col)la somme
AVG(col)la moyenne
MIN(col) / MAX(col)le minimum / le maximum

Sans GROUP BY, l'agrĂ©gat porte sur toute la table (un seul groupe) :

SELECT COUNT(*), AVG(age) FROM Etudiant;   -- 1 ligne résultat

La clause GROUP BY partitionne les lignes selon une (ou plusieurs) colonnes, puis applique l'agrĂ©gat Ă  chaque groupe. Pour la note moyenne par module :

SELECT   code_module, AVG(note) AS moyenne
FROM     Inscription
GROUP BY code_module;

11. Filtrer les agrégats avec HAVING

La clause HAVING filtre les groupes aprĂšs agrĂ©gation, comme WHERE filtre les lignes avant. Pour ne garder que les modules dont la moyenne dĂ©passe 12 :

SELECT   code_module, AVG(note) AS moyenne
FROM     Inscription
GROUP BY code_module
HAVING   AVG(note) > 12;
WHERE HAVING
S'applique avant le regroupement.S'applique aprĂšs le regroupement.
Filtre des lignes.Filtre des groupes.
Ne peut pas porter sur un agrégat.Peut porter sur un agrégat (AVG, COUNT
).

12. Tri et limitation : ORDER BY, LIMIT, OFFSET

ORDER BY trie les lignes du rĂ©sultat selon une ou plusieurs colonnes : ASC (croissant, par dĂ©faut) ou DESC (dĂ©croissant). LIMIT borne le nombre de lignes affichĂ©es, et OFFSET en saute un certain nombre au dĂ©but.

SELECT nom, age FROM Etudiant
ORDER BY age DESC, nom ASC
LIMIT 5 OFFSET 2;    -- saute 2 lignes, en affiche 5
ORDER BY age DESC, nom ASC : tri principal par Ăąge dĂ©croissant ; en cas d'Ă©galitĂ©, tri secondaire par nom croissant.

13. RequĂȘtes imbriquĂ©es (sous-requĂȘtes)

Une sous-requĂȘte est une requĂȘte SELECT placĂ©e Ă  l'intĂ©rieur d'une autre, entre parenthĂšses. Elle peut apparaĂźtre dans une clause WHERE, FROM ou HAVING. Elle sert Ă  comparer avec une valeur ou un ensemble calculĂ©s dynamiquement.

Les Ă©tudiants plus ĂągĂ©s que la moyenne :

SELECT nom, age FROM Etudiant
WHERE age > (SELECT AVG(age) FROM Etudiant);

Avec IN / NOT IN, on compare Ă  un ensemble de valeurs renvoyĂ© par la sous-requĂȘte. Les Ă©tudiants inscrits Ă  au moins un module :

SELECT nom FROM Etudiant
WHERE id IN (SELECT id_etudiant FROM Inscription);

Avec EXISTS / NOT EXISTS, on teste si la sous-requĂȘte renvoie au moins une ligne. Les dĂ©partements qui ont au moins un Ă©tudiant :

SELECT nom FROM Departement D
WHERE EXISTS (SELECT 1 FROM Etudiant E WHERE E.id_dep = D.id);
OpĂ©rateurUsage avec une sous-requĂȘte
=, <, >, !=, <=, >=Comparaison à une valeur unique renvoyée.
IN / NOT INAppartenance / non-appartenance à l'ensemble renvoyé.
EXISTS / NOT EXISTSVrai si la sous-requĂȘte renvoie (n')au moins une ligne (aucune).

14. Récapitulatif

Informatique CPGE MP/PSI · Les bases de données relationnelles