CREATE TABLE Livre (
titre TEXT,
auteur TEXT,
date_pub DATE,
numero_isbn INTEGER,
prix REAL,
PRIMARY KEY(numero_isbn)
);
CREATE TABLE Utilisateur (
nom TEXT,
prenom TEXT,
role TEXT,
id_utilisateur INTEGER,
PRIMARY KEY(id_utilisateur AUTOINCREMENT)
);
CREATE TABLE Emprunt (
livre INTEGER,
utilisateur INTEGER,
date_emprunt DATE,
id_emprunt INTEGER,
PRIMARY KEY(id_emprunt AUTOINCREMENT),
FOREIGN KEY(utilisateur) REFERENCES Utilisateur(id_utilisateur),
FOREIGN KEY(livre) REFERENCES Livre(numero_isbn)
);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('1984', 'George Orwell', '1949-06-08', 9780451524935, 9.99);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Le Petit Prince', 'Antoine de Saint-Exupéry', '1943-04-06', 9782070612758, 7.50);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Les Misérables', 'Victor Hugo', '1862-03-30', 9782253004220, 12.90);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('L`Étranger', 'Albert Camus', '1942-05-19', 9782070360024, 8.70);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Le Comte de Monte-Cristo', 'Alexandre Dumas', '1844-08-28', 9782070105618, 14.99);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Les Trois Mousquetaires', 'Alexandre Dumas', '1846-03-15', 9782070405732, 12.99);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Madame Bovary', 'Gustave Flaubert', '1857-04-01', 9782070360604, 10.50);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Don Quichotte', 'Miguel de Cervantes', '1605-01-16', 9782070117153, 15.80);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Crime et Châtiment', 'Fiodor Dostoïevski', '1866-11-01', 9782070360405, 11.90);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Orgueil et Préjugés', 'Jane Austen', '1813-01-28', 9782070318746, 9.50);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Germinal', 'Émile Zola', '1885-03-01', 9782070443943, 10.99);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Les Fleurs du mal', 'Charles Baudelaire', '1857-06-25', 9782070413113, 8.20);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('L`Odyssée', 'Homère', '0800-01-01', 9782080700241, 13.50);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('La Divine Comédie', 'Dante Alighieri', '1320-09-14', 9782253084079, 16.40);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Ulysse', 'James Joyce', '1922-02-02', 9782253943635, 17.99);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Moby Dick', 'Herman Melville', '1851-10-18', 9782070408485, 12.00);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Le Nom de la Rose', 'Umberto Eco', '1980-09-01', 9782070388824, 11.50);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('À la recherche du temps perdu', 'Marcel Proust', '1913-11-14', 9782070107586, 22.90);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Le Seigneur des Anneaux', 'J.R.R. Tolkien', '1954-07-29', 9782266154115, 29.90);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Harry Potter à l`école des sorciers', 'J.K. Rowling', '1997-06-26', 9782070643022, 8.90);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Le Meilleur des mondes', 'Aldous Huxley', '1932-01-01', 9782070368222, 9.20);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Harry Potter et la Chambre des Secrets', 'J.K. Rowling', '1998-07-02', 9782070643039, 8.90);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Harry Potter et le Prisonnier d`Azkaban', 'J.K. Rowling', '1999-07-08', 9782070643046, 8.90);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Harry Potter et la Coupe de Feu', 'J.K. Rowling', '2000-07-08', 9782070643053, 9.90);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Harry Potter et l`Ordre du Phénix', 'J.K. Rowling', '2003-06-21', 9782070643060, 10.90);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Harry Potter et le Prince de Sang-Mêlé', 'J.K. Rowling', '2005-07-16', 9782070643077, 10.90);
INSERT INTO Livre(titre, auteur, date_pub, numero_isbn, prix) VALUES
('Harry Potter et les Reliques de la Mort', 'J.K. Rowling', '2007-07-21', 9782070643084, 11.90);
INSERT INTO Utilisateur(nom, prenom, role) VALUES
('Dupont', 'Alice', 'enseignant'),
('Martin', 'Benoît', 'bibliothécaire'),
('Leroy', 'Catherine', 'enseignant'),
('Moreau', 'David', 'enseignant'),
('Bernard', 'Elise', 'élève'),
('Petit', 'François', 'élève'),
('Robert', 'Gabrielle', 'élève'),
('Richard', 'Hélène', 'élève'),
('Durand', 'Isabelle', 'bibliothécaire'),
('Dubois', 'Jules', 'élève');
INSERT INTO Emprunt(livre, utilisateur, date_emprunt) VALUES
(9780451524935, 6, '2025-02-01'),
(9782070612758, 3, '2025-02-03'),
(9782253004220, 3, '2025-02-05'),
(9782070360024, 2, '2025-02-07'),
(9782070105618, 8, '2025-02-10'),
(9782070405732, 6, '2025-02-12'),
(9782070360604, 2, '2025-02-15'),
(9782070117153, 1, '2025-02-18'),
(9782070360405, 7, '2025-02-20'),
(9782070318746, 3, '2025-02-22');
select * from canton;
create table canton (
nom text not null,
abr text not null,
chef_lieu text not null,
nb_communes int not null,
population int not null,
superficie decimal(6,2) not null
);
insert into canton values
('Fribourg', 'FR', 'Fribourg', 126, 334465, 1670.7),
('Genève', 'GE', 'Genève', 45, 514114, 282.48),
('Berne', 'BE', 'Berne', 335, 1051437, 5959.44),
('Zurich', 'ZH', 'Zurich', 160, 1579967, 1729),
('Tessin', 'TI', 'Bellinzone', 106, 354023, 2812.2),
('Grison', 'GR', 'Coire', 101, 202538, 7105.44),
('Uri', 'UR', 'Altdorf', 19, 37317, 1076.57);
SQL - Sélectionner des données#
Sélectionner des données#
L'instruction SELECT ... FROM ... permet de rechercher des données dans une table. On fait suivre le mot-clef SELECT du nom de(s) colonne(s) que l'on souhaite afficher, et le FROM de la table contenant ces données. Ainsi, la requête suivante nous permet d'afficher tous les titres et auteurs de notre table Livre.
SELECT titre, auteur FROM Livre
Et celle-ci affiche le nom et le prénom de tous les utilisateurs de la bibliothèque.
SELECT nom, prenom FROM Utilisateur
Si on souhaite ne pas avoir de lignes "doublons" dans les résultats, on peut faire suivre SELECT du mot-clef DISTINCT afin de les retirer du résultat de la recherche et n'avoir ainsi que des lignes uniques.
SELECT DISTINCT auteur FROM Livre
On peut également utiliser SELECT * pour sélectionner toutes les colonnes d'un seul coup.
SELECT * FROM Livre
Trier les données#
Les requêtes SELECT peuvent être suivies des mots-clef ORDER BY afin de trier les résultats par ordre croissant/ascendant (ASC) ou décroissant/descendant (DESC). Pour cela, il faut faire suivre le ORDER BY de la colonne selon laquelle trier les données, ainsi que de ASC ou DESC pour donner l'ordre de tri. La requête suivant permet ainsi d'afficher tous les livres du plus cher au moins cher.
SELECT titre, prix FROM Livre
ORDER BY prix DESC
Filtrer les données#
Les résultats obtenus à l'aide d'une requête SELECT ... FROM ... peuvent être filtrés en faisant suivre cette requête d'un WHERE. Ce mot-clef est suivi d'une condition qui s'écrit de manière similaire à Python en utilisant les opérateurs de comparaisons =, !=, >, >=, <, <=. La requête suivante permet par exemple de sélectionner toutes les lignes où le prix est inférieur ou égal à 10CHF.
SELECT * FROM Livre WHERE prix <= 10
Celle ci-dessous permet de sélectionner les titres de livre écrit par J.K. Rowling.
SELECT titre FROM Livre WHERE auteur = 'J.K. Rowling'
Opérateurs logiques#
Comme en Python, il est possible de chaîner plusieurs conditions avec les opérateurs logiques AND et OR. La requête suivante permet d'afficher tous les livres écrits par Alexandre Dumas ou par Gustave Flaubert.
SELECT titre FROM Livre WHERE auteur = 'Alexandre Dumas' OR Auteur = 'Gustave Flaubert'
La requête suivante permet d'afficher les titres des livres écrits par J.K. Rowling après 2003.
SELECT titre FROM Livre WHERE auteur = 'J.K. Rowling' AND date_pub > '2003-12-31'
Important
Une date s'écrit entre guillemets simples et se compare comme du texte, caractère par
caractère. Il faut donc toujours donner une date complète au format 'AAAA-MM-JJ'.
Écrire date_pub > 2003 (sans guillemets et sans mois ni jour) ne produit aucune erreur, mais
donne un résultat faux : SQL compare alors un nombre à du texte et retourne tous les livres.
Opérateur LIKE#
Le mot-clef LIKE peut s'utiliser comme un opérateur de comparaison sur du texte, de manière similaire à un =. Il permet de vérifier qu'une colonne soit semblable à une valeur que l'on définit. Ces similitudes peuvent se décliner de trois manières
La valeur commence par un certain texte. Par exemple, pour trouver tous les prénoms d'utilisateur qui commencent par "M" ou pour trouver tous les livres dont le titre commence par "Harry". Pour cela, il faut ajouter le signe
%(qui peut être compris par "n'importe quel texte") après la valeur commençant le mot.SELECT * FROM Livre WHERE titre LIKE 'Harry%'
La valeur se termine par un certain texte. Par exemple pour trouver tous les livres dont la date de publication se termine par "2". Cette fois, le signe
%doit précéder la valeur terminant le mot.SELECT * FROM Livre WHERE date_pub LIKE '%2'
La valeur contient un certain texte. Par exemple pour trouver tous les livres dont le titre contient "le". Le signe
%doit ici entourer la valeur à contenir.SELECT * FROM Livre WHERE titre LIKE '%le%'
Exercices#
Exercice 15#
Voici la table canton, qui servira de base aux deux prochains exercices.
select * from canton;
Avant d'exécuter les requêtes ci-dessous, lisez-les attentivement et prédisez leur résultat.
La requête est-elle correcte ou produira-t-elle une erreur ? Si elle est correcte, combien de
lignes affichera-t-elle ? Indiquez ce nombre dans la case à droite (ou le mot erreur si la
requête ne fonctionne pas), puis exécutez la requête pour vérifier.
-
select * from canton where nb_communes = 45;
-
select * from canton where chef_lieu = Coire;
-
select nom, superficie from canton where nom = 'Fribourg';
-
select * from canton where population > 500000;
-
select * from canton where abr < 'GR';
-
select * from canton order by superficie asc;
-
select * from canton where nom like 'F';
-
select * from canton where chef_lieu = 'coire';
-
select nom, superficie from canton order by nb_communes desc;
-
select * from canton where nb_communes > 100 and population > 300000 and superficie < 3000;
-
select nom from canton where nom = 'Fribourg' and nom = 'Genève';
Explications
Un seul canton a 45 communes : Genève.
Cette requête produit une erreur, car il manque les guillemets simples autour de
Coire. Sans eux, SQL cherche une colonne appeléeCoire.Un seul canton s'appelle Fribourg. Notez que seules deux colonnes sont affichées, mais cela ne change rien au nombre de lignes.
Genève, Berne et Zurich dépassent les 500'000 habitants.
Les opérateurs de comparaison pour du texte utilisent l'ordre alphabétique.
Exemples:'a' < 'b'ou'p' > 'd'. Les abréviations placées avantGRdans l'ordre alphabétique sontBE,FRetGE.Un
ORDER BYne filtre rien : il ne fait que changer l'ordre des lignes. Les 7 cantons sont donc affichés.Aucune ligne.
LIKE 'F'cherche un nom exactement égal àF. Pour trouver les noms qui commencent par F, il faut écrireLIKE 'F%'.Aucune ligne. Contrairement au
LIKE, l'opérateur=distingue les majuscules des minuscules :'coire'n'est pas'Coire'.Sept lignes également. On peut parfaitement trier selon une colonne qui n'est pas affichée : le tri se fait avant la sélection des colonnes.
Rien n'empêche de chaîner plus de deux conditions avec
and. Une ligne n'est retenue que si toutes les conditions sont vraies : Fribourg, Zurich et Tessin remplissent les trois.Aucune ligne : un canton ne peut pas s'appeler à la fois Fribourg et Genève. Quand on veut plusieurs valeurs possibles pour une même colonne, c'est un
orqu'il faut utiliser.
Exercice 16#
En vous basant sur la table canton ci-dessus, écrivez les requêtes SQL répondant aux critères suivants.
Écrire une requête SQL qui retourne toutes les colonnes du canton dont le chef-lieu est Bellinzone.
Solution
select * from canton where chef_lieu = 'Bellinzone';
Écrire une requête SQL qui retourne toutes les colonnes des cantons dont la population est inférieure à 300'000 habitants.
Solution
select * from canton where population < 300000;
Écrire une requête SQL qui retourne toutes les colonnes des cantons dans l'ordre alphabétique des abréviations.
Solution
select * from canton order by abr asc;
Écrire une requête SQL qui retourne le nom, l'abréviation et le chef-lieu des cantons.
Solution
select nom, abr, chef_lieu from canton;
Écrire une requête SQL qui retourne le nom, l'abréviation et le chef-lieu des cantons ordonnés selon le nombre d'habitants du plus grand au plus petit.
Solution
select nom, abr, chef_lieu from canton order by population desc;
Écrire une requête SQL qui retourne toutes les colonnes des cantons qui ont plus de 100 communes et une population inférieure à 500'000 habitants.
Solution
select * from canton where nb_communes > 100 and population < 500000;
Écrire une requête SQL qui retourne toutes les colonnes des cantons dont le chef-lieu est Altdorf ou le nombre de communes supérieur ou égal à 150.
Solution
select * from canton where chef_lieu = 'Altdorf' or nb_communes >= 150;
Écrire une requête SQL qui retourne le nom des cantons dont l'abréviation n'est pas FR.
Solution
select nom from canton where abr != 'FR';
Écrire une requête SQL qui retourne le nom et l'abréviation des cantons dont la population se trouve entre 300'000 et 500'000 habitants.
Solution
select nom, abr from canton where population > 300000 and population < 500000;
Exercice 17#
Chacune des requêtes ci-dessous, écrite sur la base de données de la bibliothèque, comporte une erreur. Parfois l'erreur produit un message rouge, parfois la requête s'exécute mais ne retourne pas ce qui était demandé. Corrigez-les.
On souhaite afficher le titre des livres coûtant moins de 10 CHF.
SELECT titre WHERE prix < 10
On souhaite afficher tous les livres de Victor Hugo.
SELECT * FROM Livre WHERE auteur = Victor Hugo
On souhaite afficher tous les livres du plus cher au moins cher.
SELECT * FROM Livre ORDER prix BY DESC
On souhaite afficher tous les livres de la saga Harry Potter.
SELECT * FROM Livre WHERE titre LIKE 'Harry'
On souhaite afficher les livres qui coûtent moins de 10 CHF ou plus de 20 CHF.
SELECT * FROM Livre WHERE prix < 10 AND prix > 20
Solution
Le
FROMa été oublié : SQL ne sait pas dans quelle table chercher.SELECT titre FROM Livre WHERE prix < 10
Il manque les guillemets simples autour du texte recherché.
SELECT * FROM Livre WHERE auteur = 'Victor Hugo'
Les deux mots-clefs
ORDER BYvont ensemble et se placent avant le nom de la colonne.SELECT * FROM Livre ORDER BY prix DESC
La requête ne produit aucune erreur, mais retourne zéro ligne : sans
%, leLIKEcherche un titre exactement égal àHarry.SELECT * FROM Livre WHERE titre LIKE 'Harry%'
Aucune erreur non plus, mais aucun résultat : un prix ne peut pas être à la fois inférieur à 10 et supérieur à 20. Il fallait un
OR.SELECT * FROM Livre WHERE prix < 10 OR prix > 20
Exercice 18#
Les exercices suivants utilisent la table jeu ci-dessous, qui recense quelques jeux vidéo.
select * from jeu;
create table jeu (
titre text not null,
studio text not null,
genre text not null,
annee int not null,
note real not null,
prix real not null
);
insert into jeu values
('The Legend of Zelda: Breath of the Wild', 'Nintendo', 'Aventure', 2017, 9.7, 59.90),
('Super Mario Odyssey', 'Nintendo', 'Plateforme', 2017, 9.4, 54.90),
('Mario Kart 8 Deluxe', 'Nintendo', 'Course', 2017, 9.2, 49.90),
('Minecraft', 'Mojang', 'Bac à sable', 2011, 9.0, 26.95),
('Stardew Valley', 'ConcernedApe', 'Simulation', 2016, 8.9, 13.99),
('Hollow Knight', 'Team Cherry', 'Aventure', 2017, 9.1, 14.99),
('Celeste', 'Maddy Makes Games', 'Plateforme', 2018, 9.4, 19.99),
('Rocket League', 'Psyonix', 'Sport', 2015, 8.6, 0.00),
('Among Us', 'Innersloth', 'Party game', 2018, 7.8, 4.30),
('Terraria', 'Re-Logic', 'Bac à sable', 2011, 8.8, 9.99),
('It Takes Two', 'Hazelight', 'Aventure', 2021, 9.3, 39.90),
('Portal 2', 'Valve', 'Réflexion', 2011, 9.5, 8.19);
select * from jeu;
Pour commencer, où faut-il placer le signe % ? On cherche ici des auteurs dans une table
Livre.
Le nom de l'auteur commence par Zola
Le nom de l'auteur se termine par Zola
Le nom de l'auteur contient Zola
Écrivez maintenant les requêtes suivantes sur la table jeu. Toutes nécessitent un LIKE.
Afficher tous les jeux dont le titre commence par Super.
Solution
select * from jeu where titre like 'Super%';
Afficher tous les jeux dont le titre contient Mario.
Solution
select * from jeu where titre like '%Mario%';
Afficher le titre et le studio des jeux dont le nom du studio se termine par o et qui coûtent plus de 50 CHF.
Solution
select titre, studio from jeu where studio like '%o' and prix > 50;
Afficher les jeux dont le genre se termine par ure et dont la note dépasse 9.2.
Solution
select * from jeu where genre like '%ure' and note > 9.2;
Afficher les jeux dont le titre contient la lettre a, qui coûtent moins de 20 CHF et dont la note est supérieure ou égale à 8.8.
Solution
select * from jeu where titre like '%a%' and prix < 20 and note >= 8.8;
Rien n'empêche d'enchaîner trois conditions avec deux and : la ligne n'est retenue que si les
trois sont vraies en même temps. Cette requête retourne 3 jeux. Notez au passage que le LIKE ne
fait pas la différence entre majuscules et minuscules : Portal 2 est bien trouvé.
Exercice 19#
Toujours sur la table jeu, écrivez les requêtes suivantes. Elles nécessitent toutes un
DISTINCT, un ORDER BY, ou les deux.
Afficher la liste des genres présents dans la table, sans doublon.
Solution
select distinct genre from jeu;
Sans le DISTINCT, la requête afficherait 12 lignes (une par jeu) au lieu des 8 genres réellement
différents.
Afficher la liste des studios, sans doublon, par ordre alphabétique.
Solution
select distinct studio from jeu order by studio asc;
Afficher les années de sortie, sans doublon, de la plus récente à la plus ancienne.
Solution
select distinct annee from jeu order by annee desc;
Afficher le titre et la note des jeux d'aventure ou de plateforme, du mieux noté au moins bien noté.
Solution
select titre, note from jeu where genre = 'Aventure' or genre = 'Plateforme' order by note desc;
Afficher le titre et le prix des jeux qui coûtent moins de 20 CHF, sont sortis après 2014 et ont une note supérieure à 8.5, du moins cher au plus cher.
Solution
select titre, prix from jeu where prix < 20 and annee > 2014 and note > 8.5
order by prix asc;
Les trois conditions sont chaînées par deux and, et le order by se place toujours après
l'ensemble du where.
Exercice 20#
Cet exercice fonctionne dans l'autre sens : les requêtes sont données, à vous de dire ce qu'elles font. Répondez en une phrase, en français, sans les exécuter. Elles portent sur la base de données de la bibliothèque.
SELECT DISTINCT auteur FROM Livre ORDER BY auteur ASCSELECT titre, prix FROM Livre WHERE prix > 15 OR auteur = 'Victor Hugo'SELECT nom FROM Utilisateur WHERE role != 'élève'SELECT * FROM Livre WHERE titre LIKE '%Potter%' AND prix < 10 AND date_pub > '2000-01-01'SELECT titre, date_pub FROM Livre WHERE date_pub < '1900-01-01' ORDER BY date_pub ASC
Solution
Affiche la liste de tous les auteurs de la bibliothèque, sans doublon, par ordre alphabétique.
Affiche le titre et le prix des livres qui coûtent plus de 15 CHF, ainsi que ceux écrits par Victor Hugo (même s'ils coûtent moins de 15 CHF).
Affiche le nom de tous les utilisateurs qui ne sont pas des élèves, c'est-à-dire les enseignants et les bibliothécaires.
Affiche toutes les informations des livres de la saga Harry Potter qui coûtent moins de 10 CHF et qui ont été publiés après le 1er janvier 2000. Un seul livre remplit les trois conditions.
Affiche le titre et la date de publication des livres publiés avant 1900, du plus ancien au plus récent.