Retour à la page d'accueilNSI · Terminale (maths expertes) · Changer de matière
Commencer gratuitement
Terminale (maths expertes) · NSI
Structures de données, bases de données et algorithmique · Bases de données relationnelles

Modèle relationnel et langage SQL

La médiathèque de Nantes enregistre chaque emprunt. Faut-il recopier le nom et l'adresse de l'adhérent à chaque ligne d'emprunt ? Et comment interroger ces données en quelques secondes parmi des millions de lignes ? Le modèle relationnel et le langage SQL répondent à ces deux questions.

Le modèle relationnel

Une base de données relationnelle range l'information dans des tables. Chaque table ressemble à un tableau : les colonnes décrivent des caractéristiques, les lignes décrivent des objets.

id nom prenom classe
1 Martin Lucas T1
2 Bernard Emma T2
3 Petit Léa T1

Pourquoi id plutôt que nom ? Deux élèves peuvent s'appeler Martin. Un numéro attribué à chacun ne peut pas être partagé : il joue le rôle d'une plaque d'immatriculation.

Il faut distinguer la structure (le schéma : noms des attributs et domaines) du contenu (les lignes à un instant donné). Le contenu change tous les jours, la structure change rarement.

Entraîne-toi★☆☆Pas commencé
Une relation Eleve(id, nom, prenom, classe) a pour clef primaire id. a) Expliquer ce qu'est une relation, un attribut et un domaine, en prenant des exemples dans Eleve.…

Une relation Eleve(id, nom, prenom, classe) a pour clef primaire id.

  1. a) Expliquer ce qu'est une relation, un attribut et un domaine, en prenant des exemples dans Eleve.
  1. b) Expliquer le rôle d'une clef primaire et pourquoi deux élèves ne peuvent pas avoir le même id.
  1. c) Donner le schéma de la relation.
Résoudre

Interroger une table : SELECT

Le langage SQL (Structured Query Language) permet de questionner la base. Une requête de lecture a cette forme :

SELECT attributs

FROM table

WHERE condition

ORDER BY attribut;
  • SELECT : les colonnes à afficher (* pour toutes) ;

  • FROM : la table interrogée ;

  • WHERE : la condition que doivent vérifier les lignes (=, <>, <, >=, AND, OR, NOT) ;

  • ORDER BY : le tri (ASC croissant par défaut, DESC décroissant) ;

  • DISTINCT après SELECT : supprime les doublons.

Les textes s'écrivent entre apostrophes 'Zola'. En SQL, les nombres décimaux s'écrivent avec un point : 7.50.

Prenons Livre(id, titre, auteur, annee, prix) :

id titre auteur annee prix
1 Germinal Zola 1885 7,50
2 Candide Voltaire 1759 5,00
3 Nana Zola 1880 8,00
Entraîne-toi★☆☆Pas commencé
On considère la table Livre(id, titre, auteur, annee, prix) contenant, entre autres, les livres suivants : (1, "Germinal", "Zola", 1885, 7.50), (2, "Candide",…

On considère la table Livre(id, titre, auteur, annee, prix) contenant, entre autres, les livres suivants : (1, "Germinal", "Zola", 1885, 7.50), (2, "Candide", "Voltaire", 1759, 5.00), (3, "Nana", "Zola", 1880, 8.00).

  1. a) Écrire la requête SQL qui renvoie les titres des livres de Zola.
  1. b) Écrire la requête qui renvoie tous les livres triés par prix croissant.
  1. c) Donner le résultat de la requête SELECT titre FROM Livre WHERE annee < 1882;.
Résoudre

Modifier les données : INSERT, UPDATE, DELETE

Trois instructions modifient le contenu de la base.

INSERT INTO Livre VALUES (5, 'Thérèse Raquin', 'Zola', 1867, 6.00);

UPDATE Livre SET prix = 6.50 WHERE id = 1;

DELETE FROM Livre WHERE annee < 1800;
  • INSERT INTO … VALUES (…) ajoute une ligne (les valeurs suivent l'ordre des attributs) ;

  • UPDATE … SET … WHERE … modifie des valeurs ;

  • DELETE FROM … WHERE … supprime des lignes.

Le SGBD (système de gestion de bases de données) refuse d'insérer une ligne dont la clef primaire existe déjà : c'est lui qui garantit l'unicité.

Entraîne-toi★☆☆Pas commencé
Avec la table Livre(id, titre, auteur, annee, prix) de l'exercice précédent : a) Écrire la requête qui ajoute le livre (4, "Au bonheur des dames", "Zola", 1883, 9.00).…

Avec la table Livre(id, titre, auteur, annee, prix) de l'exercice précédent :

  1. a) Écrire la requête qui ajoute le livre (4, "Au bonheur des dames", "Zola", 1883, 9.00).
  1. b) Écrire la requête qui passe le prix du livre d'id 2 à 6,00.
  1. c) Écrire la requête qui supprime les livres publiés avant 1800.
Résoudre

Agréger : COUNT, SUM, AVG, GROUP BY

Parfois, on ne veut pas les lignes mais un résumé : combien ? quelle somme ? quelle moyenne ? Les fonctions d'agrégation COUNT, SUM, AVG, MIN, MAX résument toutes les lignes sélectionnées en une seule valeur.

SELECT COUNT(*) FROM Livre WHERE auteur = 'Zola';

SELECT AVG(prix) FROM Livre WHERE auteur = 'Zola';

Sur notre table de trois livres, ces requêtes donnent 2, puis 7,75 (la moyenne de 7,50 et 8,00). On peut agréger une expression : SUM(quantite * prix_unitaire).

Pour obtenir un résumé par groupe, on ajoute GROUP BY :

SELECT auteur, COUNT(*) FROM Livre GROUP BY auteur;

Les lignes sont regroupées par valeur de auteur, puis on agrège chaque groupe : on obtient Zola → 2 et Voltaire → 1.

Pour garder seulement certains groupes, on utilise HAVING, qui s'écrit après GROUP BY :

SELECT auteur, COUNT(*) FROM Livre GROUP BY auteur HAVING COUNT(*) >= 2;

Pour ne garder que les premières lignes d'un classement, on trie puis on limite : ORDER BY quantite DESC LIMIT 3 renvoie les trois plus grandes quantités.

Entraîne-toi★★☆Pas commencé
La table Vente(id, produit, magasin, quantite, prix_unitaire) recense les ventes d'une chaîne de boulangeries. a) Écrire la requête qui calcule le chiffre d'affaires…

La table Vente(id, produit, magasin, quantite, prix_unitaire) recense les ventes d'une chaîne de boulangeries.

  1. a) Écrire la requête qui calcule le chiffre d'affaires total ($\text{quantité} \times \text{prix unitaire}$).
  1. b) Écrire la requête qui donne, pour chaque magasin, la quantité totale vendue.
  1. c) Écrire la requête qui renvoie le prix unitaire moyen des ventes du produit « baguette ».
  1. d) Écrire la requête qui renvoie les trois ventes de plus grande quantité.
Résoudre

Relier les tables : clef étrangère et jointure

Pour ne pas recopier les informations d'un adhérent à chaque emprunt, on les range dans une table Adherent et on renvoie vers elle depuis Emprunt.

Deux tables Adherent et Emprunt reliées par une clef étrangère Adherent num (clef primaire) nom ville Emprunt id (clef primaire) num_adherent (clef étr.) titre date_emprunt renvoie à

Avec Adherent (1, Durand, Nantes), (2, Morel, Rezé) et Emprunt (1, 1, « Germinal »), (2, 1, « Nana »), (3, 2, « Candide »), on rassemble les informations avec JOIN :

SELECT Adherent.nom, Emprunt.titre

FROM Adherent

JOIN Emprunt ON Adherent.num = Emprunt.num_adherent;

Le ON indique quelles lignes s'associent : celles dont la clef étrangère est égale à la clef primaire. Résultat : (Durand, Germinal), (Durand, Nana), (Morel, Candide). Le préfixe Table.attribut lève toute ambiguïté.

On combine ensuite jointure et agrégation :

SELECT Adherent.num, COUNT(*)

FROM Adherent JOIN Emprunt ON Adherent.num = Emprunt.num_adherent

GROUP BY Adherent.num;

Ici : 1 → 2 et 2 → 1. Pour relier trois tables, on enchaîne deux jointures : … JOIN B ON … JOIN C ON ….

Pour trouver les lignes qui n'ont aucune correspondance, on utilise une sous-requête avec NOT IN :

SELECT nom FROM Adherent

WHERE num NOT IN (SELECT num_adherent FROM Emprunt);

Cette requête renvoie les adhérents qui n'ont jamais emprunté (aucun ici). Pour compter des valeurs différentes, on écrit COUNT(DISTINCT attribut).

Entraîne-toi★★☆Pas commencé
Une médiathèque de Nantes utilise les tables Adherent(num, nom, ville) et Emprunt(id, num_adherent, titre, date_emprunt), où num_adherent est une clef étrangère vers…

Une médiathèque de Nantes utilise les tables Adherent(num, nom, ville) et Emprunt(id, num_adherent, titre, date_emprunt), où num_adherent est une clef étrangère vers Adherent(num).

  1. a) Expliquer le rôle de la clef étrangère.
  1. b) Écrire la requête qui renvoie le nom des adhérents et les titres qu'ils ont empruntés.
  1. c) Écrire la requête qui renvoie le nombre d'emprunts de chaque adhérent (numéro et nombre).
  1. d) Écrire la requête qui renvoie sans doublon les villes des adhérents ayant emprunté au moins un livre.
Résoudre
Entraîne-toi★★★Pas commencé
Un lycée gère les relations Eleve(id, nom, classe), Matiere(code, intitule) et Note(id_eleve, code_matiere, valeur). La clef primaire de Note est le couple (id_eleve,…

Un lycée gère les relations Eleve(id, nom, classe), Matiere(code, intitule) et Note(id_eleve, code_matiere, valeur). La clef primaire de Note est le couple (id_eleve, code_matiere).

  1. a) Donner les clefs étrangères du schéma.
  1. b) Écrire la requête qui renvoie, pour chaque élève (nom), sa moyenne en « Mathématiques ».
  1. c) Écrire la requête qui renvoie les noms des élèves de classe « T1 » dont la moyenne en « NSI » dépasse 14.
  1. d) Expliquer pourquoi l'insertion d'une note avec un id_eleve inexistant doit être refusée et par quel mécanisme.
Résoudre
Entraîne-toi★★★Pas commencé
Soit la table Film(id, titre, realisateur, annee) et la table Projection(id_film, salle, heure) où id_film est une clef étrangère. a) Écrire la requête qui renvoie les…

Soit la table Film(id, titre, realisateur, annee) et la table Projection(id_film, salle, heure) où id_film est une clef étrangère.

  1. a) Écrire la requête qui renvoie les titres des films projetés dans au moins deux salles différentes.
  1. b) Écrire la requête qui renvoie les réalisateurs dont aucun film n'est projeté.
  1. c) Expliquer la différence entre WHERE et HAVING en justifiant l'usage nécessaire de l'un d'eux dans la question a).
Résoudre

Redondance, anomalies et décomposition

Reprenons la question du début : peut-on tout mettre dans une seule table ? Regardons Pret(num_pret, nom_adherent, ville_adherent, titre) :

num_pret nom_adherent ville_adherent titre
1 Durand Nantes Germinal
2 Durand Nantes Nana
3 Morel Rezé Candide

La ville de Durand est écrite deux fois : c'est une redondance. Elle provoque trois anomalies :

  • mise à jour : si Durand déménage, il faut modifier toutes ses lignes, sinon la base devient incohérente ;

  • insertion : on ne peut pas enregistrer un nouvel adhérent tant qu'il n'a rien emprunté ;

  • suppression : en supprimant le prêt n° 3, on perd aussi toute trace de Morel.

Ici : Adherent(num, nom, ville) et Pret(num_pret, num_adherent, titre), avec num_adherent clef étrangère vers Adherent. On retrouve la table d'origine par une jointure.

On crée les tables avec CREATE TABLE, en déclarant les clefs :

CREATE TABLE Adherent (

    num INTEGER PRIMARY KEY,

    nom TEXT,

    ville TEXT

);

CREATE TABLE Pret (

    num_pret INTEGER PRIMARY KEY,

    num_adherent INTEGER,

    titre TEXT,

    FOREIGN KEY (num_adherent) REFERENCES Adherent(num)

);

Pour une clef primaire composée de deux attributs, on écrit PRIMARY KEY (a, b) en fin de déclaration. Les domaines usuels sont INTEGER, REAL, TEXT.

Entraîne-toi★★☆Pas commencé
Voici une table unique Commande(num, client, adresse_client, produit, prix) : (1, "Durand", "12 rue Verte, Rennes", "stylo", 2,00) (2, "Durand", "12 rue Verte, Rennes",…

Voici une table unique Commande(num, client, adresse_client, produit, prix) :

(1, "Durand", "12 rue Verte, Rennes", "stylo", 2,00)

(2, "Durand", "12 rue Verte, Rennes", "cahier", 3,50)

(3, "Morel", "5 av. Foch, Brest", "stylo", 2,00)

  1. a) Repérer la redondance présente dans cette table.
  1. b) Décrire une anomalie de mise à jour, une anomalie d'insertion et une anomalie de suppression.
  1. c) Proposer un schéma à trois relations, avec clefs primaires et étrangères, qui supprime ces anomalies.
Résoudre
Entraîne-toi★★★Pas commencé
On considère la relation Inscription(num_etudiant, nom_etudiant, code_cours, intitule_cours, enseignant), avec la clef primaire (num_etudiant, code_cours). Un cours a un…

On considère la relation Inscription(num_etudiant, nom_etudiant, code_cours, intitule_cours, enseignant), avec la clef primaire (num_etudiant, code_cours). Un cours a un seul intitulé et un seul enseignant.

  1. a) Montrer que cette relation présente des redondances et des anomalies d'insertion, de suppression et de mise à jour.
  1. b) Proposer une décomposition en relations sans redondance, en précisant clefs primaires et étrangères.
  1. c) Écrire en SQL les instructions CREATE TABLE correspondantes.
  1. d) Écrire la requête qui reconstitue la liste (nom d'étudiant, intitulé du cours, enseignant).
Résoudre

L'essentiel

  • Une relation (table) a des attributs (colonnes) munis d'un domaine ; la clef primaire identifie chaque ligne de façon unique ; une clef étrangère renvoie à la clef primaire d'une autre table.

  • Lecture : SELECT … FROM … WHERE … ORDER BY … (DISTINCT supprime les doublons, LIMIT garde les premières lignes).

  • Mise à jour : INSERT INTO, UPDATE … SET … WHERE, DELETE FROM … WHERE : ne jamais oublier le WHERE.

  • Agrégation : COUNT, SUM, AVG, MIN, MAX ; GROUP BY regroupe, HAVING filtre les groupes (WHERE filtre les lignes).

  • JOIN … ON clef_étrangère = clef_primaire rassemble les informations de plusieurs tables.

  • Une table qui répète des informations souffre d'anomalies de mise à jour, d'insertion et de suppression : on la décompose, et CREATE TABLE déclare clefs primaires et étrangères.

Voir tous les exercices de cette partie