Ordre logique d'une requête
FROM/JOIN → WHERE → GROUP BY → HAVING → SELECT (fenêtres, DISTINCT) → ORDER BY → LIMIT/OFFSET. Ordre « purement illustratif » (SQLite) ; il explique pourquoi WHERE ne voit pas les agrégats.
Lire
| Besoin | Modèle |
|---|---|
| Colonnes, alias | SELECT nom AS client FROM client; |
| Sans doublons | SELECT DISTINCT ville FROM client; |
| Filtrer | WHERE ville = 'Ville-A' AND prix < 20 |
| Liste, intervalle | IN ('a','b'), BETWEEN x AND y |
| Trier | ORDER BY prix DESC, nom |
| Limiter | ORDER BY ... LIMIT 3 OFFSET 3 (toujours avec ORDER BY) |
| Compter | COUNT(*) lignes, COUNT(col) non nulles, COUNT(DISTINCT col) |
| Grouper | GROUP BY statut ; HAVING COUNT(*) > 1 filtre les groupes |
NULL
| Piège | Règle |
|---|---|
col = NULL | jamais vrai : écrire IS NULL / IS NOT NULL |
NOT IN (…, NULL) | résultat vide : préférer NOT EXISTS |
col <> 'x' | exclut les NULL |
COUNT(col) | ignore les NULL ; SUM sans valeur : NULL (SQLite : total() donne 0.0) |
UNIQUE | NULL distincts (SQLite, PostgreSQL) ; autre comportement selon le moteur |
ORDER BY | SQLite : NULL avant toute valeur ; NULLS FIRST/LAST selon le dialecte |
Jointures
| Type | Résultat |
|---|---|
INNER JOIN … ON | lignes présentes des deux côtés |
LEFT JOIN … ON | tout le côté gauche, NULL sans correspondance |
RIGHT / FULL JOIN | SQLite depuis 3.39.0 |
CROSS JOIN | toutes les combinaisons |
NATURAL JOIN | à éviter |
- Clients sans commande :
LEFT JOIN … WHERE o.id IS NULL. - Un-à-plusieurs : les lignes du côté « un » sont répétées ; compter avec
COUNT(DISTINCT …). - Filtre sur la table de droite d'un
LEFT JOIN: dans leON, pas dans leWHERE.
Sous-requêtes, CTE, fenêtres
SELECT nom FROM produit WHERE prix > (SELECT AVG(prix) FROM produit);
WITH total AS (SELECT commande_id, SUM(quantite) AS q FROM ligne_commande GROUP BY commande_id)
SELECT * FROM total WHERE q > 5;
SELECT nom, RANK() OVER (PARTITION BY categorie ORDER BY prix DESC) AS rang FROM produit;- Fenêtres : SQLite 3.25.0 ;
row_number,rank,dense_rank,lag,lead,ntile,first_value… - CTE récursive : partie de départ, puis partie récursive ; prévoir une borne.
MATERIALIZED: 3.35.0, déconseillé sans raison.
Écrire (dans une transaction)
BEGIN;
UPDATE produit SET prix = prix * 1.10 WHERE categorie = 'Papeterie';
SELECT nom, prix FROM produit WHERE categorie = 'Papeterie';
ROLLBACK;| Instruction | Rappel |
|---|---|
INSERT INTO t (a,b) VALUES (1,2), (3,4); | plusieurs lignes ; INSERT … SELECT … |
UPDATE t SET a = 1 WHERE …; | sans WHERE : toutes les lignes |
DELETE FROM t WHERE …; | sans WHERE : toutes les lignes |
… RETURNING id | SQLite 3.35.0, non standard, ordre arbitraire |
ON CONFLICT (c) DO UPDATE SET c = excluded.c | upsert, SQLite 3.24.0, non standard |
BEGIN / COMMIT / ROLLBACK | sans BEGIN, chaque instruction est validée aussitôt (SQLite) |
Avant tout UPDATE/DELETE : un SELECT avec le même WHERE, une transaction, une sauvegarde.
Structure (DDL) et contraintes
| Élément | Rappel |
|---|---|
CREATE TABLE | colonnes + contraintes |
PRIMARY KEY, NOT NULL, UNIQUE, CHECK, DEFAULT | intégrité et valeurs |
REFERENCES t(col) | clé étrangère ; SQLite : PRAGMA foreign_keys = ON; à chaque connexion |
ON DELETE | NO ACTION, RESTRICT, SET NULL, SET DEFAULT, CASCADE |
ALTER TABLE t ADD COLUMN c TEXT; | ajoute une colonne |
DROP TABLE t; | supprime table et données : sauvegarde d'abord |
STRICT (SQLite 3.37.0) | typage rigide |
SQLite : typage dynamique (affinités), dates en texte/réel/entier, booléens 0/1.
Index et plan
CREATE INDEX idx_commande_client ON commande (client_id);
EXPLAIN QUERY PLAN SELECT * FROM commande WHERE client_id = 1;
DROP INDEX idx_commande_client;SCAN t: parcours complet ;SEARCH t USING INDEX i (c=?): recherche ciblée ;COVERING INDEX: table non lue.- Format du plan instable entre versions (SQLite) : lecture humaine seulement.
- PostgreSQL :
EXPLAIN ANALYZEexécute la requête ; pour une écriture :BEGIN…ROLLBACK.
Dialectes (repères vérifiés)
| Sujet | Constat |
|---|---|
| Norme | ISO/IEC 9075 ; PostgreSQL : au moins 170 des 177 fonctions Core de SQL:2023 |
RETURNING, upsert | non standard (SQLite) |
group_concat / string_agg | alias de compatibilité (SQLite) |
| T-SQL | dialecte de SQL Server |
| Isolation par défaut | Read Committed (PostgreSQL, SQL Server), Repeatable Read (MySQL/InnoDB) |
TOP, FETCH FIRST, modes SQL MySQL, LIKE, dates | non vérifiés |
Outils SQLite (shell)
| Commande | Rôle |
|---|---|
sqlite3 demo.db | ouvre ou crée le fichier ; sans nom : base en mémoire |
.tables, .schema [motif], .indexes | structure |
.headers on, .mode box | affichage |
.read fichier.sql | exécute un script |
.backup fichier | copie cohérente |
.dump | exporte en SQL |
.quit | quitte |
sqlite3 demo.db ".backup demo-copie.db"Bloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : dossier de test jetable ;
sqlite3présent (non vérifié) ; aucune autre session ouverte surdemo.db. - Droits : lecture de
demo.db, écriture dans le dossier courant. - Effet : crée
demo-copie.db. - Vérification :
sqlite3 demo-copie.db "SELECT COUNT(*) FROM client;"affiche5. - Retour arrière : supprimer
demo-copie.db.
Avant d'exécuter
- Quel moteur, quelle version, quel fichier de base (jamais un système réel par défaut) ?
- Lecture ou écriture ? Un
WHEREest-il présent ? - Transaction ouverte et sauvegarde récente ?
- Nombre de lignes attendu avant ? après ?
ROLLBACKsi le compte ne correspond pas.
Sources
Consultées le 17 octobre 2026.
- SQLite SELECT (s’ouvre dans un nouvel onglet) · fenêtres (s’ouvre dans un nouvel onglet) · WITH (s’ouvre dans un nouvel onglet) · agrégats (s’ouvre dans un nouvel onglet) · types (s’ouvre dans un nouvel onglet) · NULL (s’ouvre dans un nouvel onglet)
- CREATE TABLE (s’ouvre dans un nouvel onglet) · clés étrangères (s’ouvre dans un nouvel onglet) · CREATE INDEX (s’ouvre dans un nouvel onglet) · upsert (s’ouvre dans un nouvel onglet) · RETURNING (s’ouvre dans un nouvel onglet) · transactions (s’ouvre dans un nouvel onglet)
- EXPLAIN QUERY PLAN (s’ouvre dans un nouvel onglet) · shell (s’ouvre dans un nouvel onglet) · sauvegarde (s’ouvre dans un nouvel onglet) · historique (s’ouvre dans un nouvel onglet) · accueil (s’ouvre dans un nouvel onglet)
- PostgreSQL conformité SQL (s’ouvre dans un nouvel onglet) · EXPLAIN (s’ouvre dans un nouvel onglet) · MySQL 8.4 isolation (s’ouvre dans un nouvel onglet) · T-SQL (s’ouvre dans un nouvel onglet)