555 lines
16 KiB
Markdown
555 lines
16 KiB
Markdown
# Cours : Le langage SQL
|
|
|
|
---
|
|
|
|
## 1. Introduction
|
|
|
|
### 1.1. Historique
|
|
|
|
**SQL** (*Structured Query Language*) est un langage de requêtes créé en 1974 par IBM, puis normalisé en 1986. Il permet d'interagir avec les **bases de données relationnelles**.
|
|
|
|
SQL est aujourd'hui le standard universel pour :
|
|
- Créer et modifier la structure des bases de données
|
|
- Insérer, modifier et supprimer des données
|
|
- Interroger les données (requêtes)
|
|
|
|
### 1.2. Les SGBD
|
|
|
|
Un **SGBD** (*Système de Gestion de Base de Données*) est un logiciel qui permet de stocker, organiser et manipuler des données. Exemples :
|
|
|
|
| SGBD | Type | Utilisation |
|
|
|------|------|-------------|
|
|
| SQLite | Léger, fichier local | Applications mobiles, embarqué |
|
|
| MySQL / MariaDB | Serveur | Sites web, applications |
|
|
| PostgreSQL | Serveur avancé | Applications complexes |
|
|
| Oracle | Entreprise | Grandes entreprises |
|
|
| Microsoft SQL Server | Entreprise | Environnement Windows |
|
|
|
|
En NSI, nous utilisons principalement **SQLite** avec l'outil **DB Browser for SQLite**.
|
|
|
|
---
|
|
|
|
## 2. Structure d'une base de données
|
|
|
|
### 2.1. Tables, attributs et enregistrements
|
|
|
|
Une base de données relationnelle est composée de **tables**. Chaque table contient :
|
|
- Des **colonnes** (ou **attributs**) : les caractéristiques des données
|
|
- Des **lignes** (ou **enregistrements**) : les données elles-mêmes
|
|
|
|
**Exemple : Table LIVRES**
|
|
|
|
| id | titre | auteur | ann_publi | note |
|
|
|----|-------|--------|-----------|------|
|
|
| 1 | 1984 | Orwell | 1949 | 10 |
|
|
| 2 | Dune | Herbert | 1965 | 8 |
|
|
| 3 | Fondation | Asimov | 1951 | 9 |
|
|
|
|
### 2.2. Types de données
|
|
|
|
| Type SQL | Description | Exemple |
|
|
|----------|-------------|---------|
|
|
| `INT` ou `INTEGER` | Nombre entier | 42, -7, 2024 |
|
|
| `REAL` ou `FLOAT` | Nombre décimal | 3.14, -0.5 |
|
|
| `TEXT` ou `VARCHAR` | Chaîne de caractères | 'Bonjour', 'Alice' |
|
|
| `DATE` | Date | '2024-01-15' |
|
|
| `BOOLEAN` | Booléen | TRUE, FALSE |
|
|
|
|
### 2.3. Clés primaires et étrangères
|
|
|
|
- **Clé primaire** (`PRIMARY KEY`) : Identifiant unique de chaque enregistrement
|
|
- **Clé étrangère** (`FOREIGN KEY`) : Référence vers la clé primaire d'une autre table
|
|
|
|
```
|
|
Table AUTEURS Table LIVRES
|
|
+----+--------+ +----+--------+-----------+
|
|
| id | nom | | id | titre | id_auteur |
|
|
+----+--------+ +----+--------+-----------+
|
|
| 1 | Orwell |<─────────────────| 1 | 1984 | 1 |
|
|
| 2 | Asimov |<─────────────────| 2 | Robots | 2 |
|
|
+----+--------+ +----+--------+-----------+
|
|
PK PK FK
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Création et modification de tables
|
|
|
|
### 3.1. Créer une table : CREATE TABLE
|
|
|
|
```sql
|
|
CREATE TABLE LIVRES (
|
|
id INTEGER PRIMARY KEY,
|
|
titre TEXT,
|
|
auteur TEXT,
|
|
ann_publi INTEGER,
|
|
note INTEGER
|
|
);
|
|
```
|
|
|
|
### 3.2. Créer une table avec clé étrangère
|
|
|
|
```sql
|
|
CREATE TABLE LIVRES (
|
|
id INTEGER PRIMARY KEY,
|
|
titre TEXT,
|
|
id_auteur INTEGER,
|
|
ann_publi INTEGER,
|
|
FOREIGN KEY (id_auteur) REFERENCES AUTEURS(id)
|
|
);
|
|
```
|
|
|
|
### 3.3. Supprimer une table : DROP TABLE
|
|
|
|
```sql
|
|
DROP TABLE LIVRES;
|
|
```
|
|
|
|
⚠️ **Attention** : Cette opération est irréversible !
|
|
|
|
### 3.4. Modifier une table : ALTER TABLE
|
|
|
|
```sql
|
|
-- Ajouter une colonne
|
|
ALTER TABLE LIVRES ADD COLUMN editeur TEXT;
|
|
|
|
-- Supprimer une colonne (selon le SGBD)
|
|
ALTER TABLE LIVRES DROP COLUMN editeur;
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Manipulation des données
|
|
|
|
### 4.1. Insérer des données : INSERT INTO
|
|
|
|
```sql
|
|
-- Insérer un enregistrement
|
|
INSERT INTO LIVRES (id, titre, auteur, ann_publi, note)
|
|
VALUES (1, '1984', 'Orwell', 1949, 10);
|
|
|
|
-- Insérer plusieurs enregistrements
|
|
INSERT INTO LIVRES (id, titre, auteur, ann_publi, note)
|
|
VALUES
|
|
(2, 'Dune', 'Herbert', 1965, 8),
|
|
(3, 'Fondation', 'Asimov', 1951, 9);
|
|
```
|
|
|
|
### 4.2. Modifier des données : UPDATE
|
|
|
|
```sql
|
|
-- Modifier tous les enregistrements correspondant à la condition
|
|
UPDATE LIVRES
|
|
SET note = 10
|
|
WHERE auteur = 'Asimov';
|
|
|
|
-- Modifier plusieurs colonnes
|
|
UPDATE LIVRES
|
|
SET note = 9, ann_publi = 1950
|
|
WHERE id = 3;
|
|
```
|
|
|
|
⚠️ **Attention** : Sans clause `WHERE`, tous les enregistrements seront modifiés !
|
|
|
|
### 4.3. Supprimer des données : DELETE
|
|
|
|
```sql
|
|
-- Supprimer les enregistrements correspondant à la condition
|
|
DELETE FROM LIVRES
|
|
WHERE ann_publi < 1950;
|
|
|
|
-- Supprimer tous les enregistrements (vider la table)
|
|
DELETE FROM LIVRES;
|
|
```
|
|
|
|
⚠️ **Attention** : Sans clause `WHERE`, tous les enregistrements seront supprimés !
|
|
|
|
---
|
|
|
|
## 5. Requêtes de sélection : SELECT
|
|
|
|
### 5.1. Syntaxe de base
|
|
|
|
```sql
|
|
SELECT colonnes
|
|
FROM table
|
|
WHERE conditions
|
|
ORDER BY colonne [ASC|DESC];
|
|
```
|
|
|
|
### 5.2. Sélectionner des colonnes
|
|
|
|
```sql
|
|
-- Toutes les colonnes
|
|
SELECT * FROM LIVRES;
|
|
|
|
-- Colonnes spécifiques
|
|
SELECT titre, auteur FROM LIVRES;
|
|
|
|
-- Avec alias
|
|
SELECT titre AS "Titre du livre", auteur AS "Écrivain"
|
|
FROM LIVRES;
|
|
```
|
|
|
|
### 5.3. Filtrer avec WHERE
|
|
|
|
**Opérateurs de comparaison :**
|
|
|
|
| Opérateur | Signification |
|
|
|-----------|---------------|
|
|
| `=` | Égal à |
|
|
| `<>` ou `!=` | Différent de |
|
|
| `<`, `<=` | Inférieur (ou égal) |
|
|
| `>`, `>=` | Supérieur (ou égal) |
|
|
| `BETWEEN a AND b` | Entre a et b (inclus) |
|
|
| `IN (v1, v2, ...)` | Dans la liste |
|
|
| `LIKE` | Correspondance de motif |
|
|
| `IS NULL` | Est nul |
|
|
|
|
**Exemples :**
|
|
|
|
```sql
|
|
-- Égalité
|
|
SELECT * FROM LIVRES WHERE auteur = 'Asimov';
|
|
|
|
-- Comparaison
|
|
SELECT * FROM LIVRES WHERE ann_publi > 1960;
|
|
|
|
-- Entre deux valeurs
|
|
SELECT * FROM LIVRES WHERE ann_publi BETWEEN 1950 AND 1970;
|
|
|
|
-- Dans une liste
|
|
SELECT * FROM LIVRES WHERE auteur IN ('Asimov', 'Bradbury', 'K.Dick');
|
|
|
|
-- Correspondance de motif (LIKE)
|
|
SELECT * FROM LIVRES WHERE titre LIKE '%Robot%';
|
|
-- % = n'importe quelle suite de caractères
|
|
-- _ = un seul caractère
|
|
|
|
-- Valeur nulle
|
|
SELECT * FROM LIVRES WHERE note IS NULL;
|
|
```
|
|
|
|
### 5.4. Combiner les conditions : AND, OR, NOT
|
|
|
|
```sql
|
|
-- ET logique
|
|
SELECT * FROM LIVRES
|
|
WHERE auteur = 'Asimov' AND ann_publi > 1950;
|
|
|
|
-- OU logique
|
|
SELECT * FROM LIVRES
|
|
WHERE auteur = 'Asimov' OR auteur = 'Bradbury';
|
|
|
|
-- Négation
|
|
SELECT * FROM LIVRES
|
|
WHERE NOT auteur = 'Asimov';
|
|
|
|
-- Combinaison avec parenthèses
|
|
SELECT * FROM LIVRES
|
|
WHERE (auteur = 'Asimov' OR auteur = 'Bradbury') AND note >= 8;
|
|
```
|
|
|
|
### 5.5. Trier les résultats : ORDER BY
|
|
|
|
```sql
|
|
-- Tri croissant (par défaut)
|
|
SELECT * FROM LIVRES ORDER BY ann_publi;
|
|
SELECT * FROM LIVRES ORDER BY ann_publi ASC;
|
|
|
|
-- Tri décroissant
|
|
SELECT * FROM LIVRES ORDER BY note DESC;
|
|
|
|
-- Tri multiple
|
|
SELECT * FROM LIVRES ORDER BY auteur ASC, ann_publi DESC;
|
|
```
|
|
|
|
### 5.6. Éliminer les doublons : DISTINCT
|
|
|
|
```sql
|
|
-- Liste des auteurs (sans doublons)
|
|
SELECT DISTINCT auteur FROM LIVRES;
|
|
```
|
|
|
|
### 5.7. Limiter les résultats : LIMIT
|
|
|
|
```sql
|
|
-- Les 5 premiers résultats
|
|
SELECT * FROM LIVRES LIMIT 5;
|
|
|
|
-- Pagination : 5 résultats à partir du 10e
|
|
SELECT * FROM LIVRES LIMIT 5 OFFSET 10;
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Fonctions d'agrégation
|
|
|
|
Les fonctions d'agrégation effectuent des calculs sur un ensemble de valeurs.
|
|
|
|
### 6.1. Les fonctions principales
|
|
|
|
| Fonction | Description |
|
|
|----------|-------------|
|
|
| `COUNT(*)` | Nombre d'enregistrements |
|
|
| `COUNT(colonne)` | Nombre de valeurs non nulles |
|
|
| `SUM(colonne)` | Somme des valeurs |
|
|
| `AVG(colonne)` | Moyenne des valeurs |
|
|
| `MIN(colonne)` | Valeur minimale |
|
|
| `MAX(colonne)` | Valeur maximale |
|
|
|
|
### 6.2. Exemples
|
|
|
|
```sql
|
|
-- Nombre total de livres
|
|
SELECT COUNT(*) FROM LIVRES;
|
|
|
|
-- Nombre de livres par auteur
|
|
SELECT COUNT(*) FROM LIVRES WHERE auteur = 'Asimov';
|
|
|
|
-- Note moyenne
|
|
SELECT AVG(note) FROM LIVRES;
|
|
|
|
-- Note minimale et maximale
|
|
SELECT MIN(note), MAX(note) FROM LIVRES;
|
|
|
|
-- Somme des notes (peu utile ici, mais illustratif)
|
|
SELECT SUM(note) FROM LIVRES;
|
|
|
|
-- Année du livre le plus ancien
|
|
SELECT MIN(ann_publi) FROM LIVRES;
|
|
```
|
|
|
|
### 6.3. Regrouper les données : GROUP BY
|
|
|
|
`GROUP BY` permet de regrouper les enregistrements par valeur d'une colonne.
|
|
|
|
```sql
|
|
-- Nombre de livres par auteur
|
|
SELECT auteur, COUNT(*) AS nb_livres
|
|
FROM LIVRES
|
|
GROUP BY auteur;
|
|
|
|
-- Note moyenne par auteur
|
|
SELECT auteur, AVG(note) AS note_moyenne
|
|
FROM LIVRES
|
|
GROUP BY auteur;
|
|
|
|
-- Résultat :
|
|
-- +----------+--------------+
|
|
-- | auteur | note_moyenne |
|
|
-- +----------+--------------+
|
|
-- | Asimov | 8.67 |
|
|
-- | Bradbury | 7.50 |
|
|
-- | K.Dick | 8.33 |
|
|
-- +----------+--------------+
|
|
```
|
|
|
|
### 6.4. Filtrer les groupes : HAVING
|
|
|
|
`HAVING` filtre les résultats **après** le regroupement (contrairement à `WHERE` qui filtre **avant**).
|
|
|
|
```sql
|
|
-- Auteurs ayant écrit plus de 2 livres
|
|
SELECT auteur, COUNT(*) AS nb_livres
|
|
FROM LIVRES
|
|
GROUP BY auteur
|
|
HAVING COUNT(*) > 2;
|
|
|
|
-- Auteurs avec une note moyenne >= 8
|
|
SELECT auteur, AVG(note) AS note_moyenne
|
|
FROM LIVRES
|
|
GROUP BY auteur
|
|
HAVING AVG(note) >= 8;
|
|
```
|
|
|
|
**Différence WHERE / HAVING :**
|
|
|
|
```sql
|
|
-- WHERE filtre les lignes AVANT le regroupement
|
|
SELECT auteur, AVG(note)
|
|
FROM LIVRES
|
|
WHERE ann_publi > 1950 -- Filtre les livres publiés après 1950
|
|
GROUP BY auteur;
|
|
|
|
-- HAVING filtre les groupes APRÈS le regroupement
|
|
SELECT auteur, AVG(note)
|
|
FROM LIVRES
|
|
GROUP BY auteur
|
|
HAVING AVG(note) > 8; -- Garde les auteurs avec moyenne > 8
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Jointures
|
|
|
|
Les jointures permettent de combiner des données provenant de plusieurs tables.
|
|
|
|
### 7.1. INNER JOIN (jointure interne)
|
|
|
|
Retourne uniquement les enregistrements qui ont une correspondance dans les deux tables.
|
|
|
|
```sql
|
|
SELECT LIVRES.titre, AUTEURS.nom, AUTEURS.prenom
|
|
FROM LIVRES
|
|
INNER JOIN AUTEURS ON LIVRES.id_auteur = AUTEURS.id;
|
|
```
|
|
|
|
**Schéma :**
|
|
```
|
|
LIVRES AUTEURS Résultat INNER JOIN
|
|
+----+------+ +----+------+ +------+------+
|
|
| id | id_a | | id | nom | | titre| nom |
|
|
+----+------+ +----+------+ +------+------+
|
|
| 1 | 1 | | 1 | Orwell| | 1984 | Orwell|
|
|
| 2 | 2 | | 2 | Asimov| | Fond.| Asimov|
|
|
| 3 | NULL | | 3 | Dick | +------+------+
|
|
+----+------+ +----+------+ (le livre 3 est exclu car id_a est NULL)
|
|
```
|
|
|
|
### 7.2. LEFT JOIN (jointure externe gauche)
|
|
|
|
Retourne tous les enregistrements de la table de gauche, même sans correspondance.
|
|
|
|
```sql
|
|
SELECT LIVRES.titre, AUTEURS.nom
|
|
FROM LIVRES
|
|
LEFT JOIN AUTEURS ON LIVRES.id_auteur = AUTEURS.id;
|
|
```
|
|
|
|
### 7.3. Alias de tables
|
|
|
|
Pour simplifier l'écriture :
|
|
|
|
```sql
|
|
SELECT L.titre, A.nom, A.prenom
|
|
FROM LIVRES L
|
|
INNER JOIN AUTEURS A ON L.id_auteur = A.id
|
|
WHERE A.langue_ecriture = 'français';
|
|
```
|
|
|
|
### 7.4. Jointures multiples
|
|
|
|
```sql
|
|
SELECT L.titre, A.nom, E.nom_editeur
|
|
FROM LIVRES L
|
|
INNER JOIN AUTEURS A ON L.id_auteur = A.id
|
|
INNER JOIN EDITEURS E ON L.id_editeur = E.id;
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Ordre d'exécution des clauses
|
|
|
|
L'ordre d'écriture et l'ordre d'exécution sont différents :
|
|
|
|
**Ordre d'écriture :**
|
|
```sql
|
|
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... LIMIT ...
|
|
```
|
|
|
|
**Ordre d'exécution :**
|
|
1. `FROM` et `JOIN` : Sélection des tables
|
|
2. `WHERE` : Filtrage des lignes
|
|
3. `GROUP BY` : Regroupement
|
|
4. `HAVING` : Filtrage des groupes
|
|
5. `SELECT` : Sélection des colonnes
|
|
6. `DISTINCT` : Élimination des doublons
|
|
7. `ORDER BY` : Tri
|
|
8. `LIMIT` : Limitation du nombre de résultats
|
|
|
|
---
|
|
|
|
## 9. Bonnes pratiques
|
|
|
|
### 9.1. Conventions d'écriture
|
|
|
|
- Mots-clés SQL en **MAJUSCULES** : `SELECT`, `FROM`, `WHERE`
|
|
- Noms de tables en **MAJUSCULES** : `LIVRES`, `AUTEURS`
|
|
- Noms de colonnes en **minuscules** : `titre`, `auteur`
|
|
- Indentation pour la lisibilité
|
|
|
|
```sql
|
|
SELECT L.titre,
|
|
A.nom,
|
|
A.prenom
|
|
FROM LIVRES L
|
|
INNER JOIN AUTEURS A ON L.id_auteur = A.id
|
|
WHERE A.langue_ecriture = 'français'
|
|
AND L.ann_publi > 1950
|
|
ORDER BY L.ann_publi DESC;
|
|
```
|
|
|
|
### 9.2. Sécurité : Injections SQL
|
|
|
|
⚠️ Ne jamais construire des requêtes SQL par concaténation de chaînes avec des entrées utilisateur !
|
|
|
|
```python
|
|
# DANGEREUX - Injection SQL possible
|
|
requete = "SELECT * FROM USERS WHERE nom = '" + nom_utilisateur + "'"
|
|
|
|
# SÉCURISÉ - Requête paramétrée
|
|
cursor.execute("SELECT * FROM USERS WHERE nom = ?", (nom_utilisateur,))
|
|
```
|
|
|
|
---
|
|
|
|
## 10. Synthèse
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ REQUÊTE SQL │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ SELECT [DISTINCT] colonnes, AGG(colonne) │
|
|
│ FROM table1 │
|
|
│ [INNER|LEFT] JOIN table2 ON condition │
|
|
│ WHERE conditions │
|
|
│ GROUP BY colonne │
|
|
│ HAVING condition_agregation │
|
|
│ ORDER BY colonne [ASC|DESC] │
|
|
│ LIMIT n [OFFSET m] │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
|
|
┌──────────────┬────────────────────────────────────────────────┐
|
|
│ Commande │ Action │
|
|
├──────────────┼────────────────────────────────────────────────┤
|
|
│ CREATE TABLE │ Créer une table │
|
|
│ DROP TABLE │ Supprimer une table │
|
|
│ INSERT INTO │ Insérer des données │
|
|
│ UPDATE │ Modifier des données │
|
|
│ DELETE │ Supprimer des données │
|
|
│ SELECT │ Interroger des données │
|
|
└──────────────┴────────────────────────────────────────────────┘
|
|
|
|
┌──────────────┬────────────────────────────────────────────────┐
|
|
│ Agrégation │ Description │
|
|
├──────────────┼────────────────────────────────────────────────┤
|
|
│ COUNT(*) │ Nombre d'enregistrements │
|
|
│ SUM(col) │ Somme │
|
|
│ AVG(col) │ Moyenne │
|
|
│ MIN(col) │ Minimum │
|
|
│ MAX(col) │ Maximum │
|
|
└──────────────┴────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Pour aller plus loin
|
|
|
|
- **SQL Murder Mystery** : Un jeu pour apprendre SQL en résolvant un meurtre
|
|
[https://mystery.knightlab.com](https://mystery.knightlab.com)
|
|
|
|
- **SQLBolt** : Tutoriel interactif
|
|
[https://sqlbolt.com](https://sqlbolt.com)
|
|
|
|
- **W3Schools SQL** : Référence complète
|
|
[https://www.w3schools.com/sql/](https://www.w3schools.com/sql/)
|
|
|
|
---
|
|
|
|
Auteur : Florian Mathieu
|
|
|
|
Licence CC BY NC
|
|
|
|
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|