man sql
SQL — Cheat Sheet : Manipulation de données
Référence rapide pour les opérations DML (Data Manipulation Language) et les requêtes courantes.
Référence rapide pour les opérations DML (Data Manipulation Language) et les requêtes courantes.
Sélection de données
SELECT de base
SELECT colonne1, colonne2 FROM table;SELECT * FROM table;SELECT DISTINCT colonne FROM table; -- valeurs uniquesSELECT colonne AS alias FROM table; -- renommer la colonneFiltrage avec WHERE
SELECT * FROM table WHERE colonne = 'valeur';SELECT * FROM table WHERE age > 18 AND ville = 'Paris';SELECT * FROM table WHERE statut IN ('actif', 'en_attente');SELECT * FROM table WHERE nom LIKE 'A%'; -- commence par ASELECT * FROM table WHERE nom LIKE '%son'; -- finit par "son"SELECT * FROM table WHERE valeur BETWEEN 10 AND 50;SELECT * FROM table WHERE colonne IS NULL;SELECT * FROM table WHERE colonne IS NOT NULL;Tri et pagination
SELECT * FROM table ORDER BY colonne ASC;SELECT * FROM table ORDER BY colonne DESC;SELECT * FROM table ORDER BY col1 ASC, col2 DESC;
SELECT * FROM table LIMIT 10; -- 10 premières lignesSELECT * FROM table LIMIT 10 OFFSET 20; -- page 3 (rows 21-30)Agrégation
Fonctions d’agrégat
| Fonction | Description |
|---|---|
COUNT(*) |
Nombre de lignes |
COUNT(colonne) |
Nombre de valeurs non nulles |
SUM(colonne) |
Somme |
AVG(colonne) |
Moyenne |
MIN(colonne) |
Valeur minimale |
MAX(colonne) |
Valeur maximale |
SELECT COUNT(*), AVG(salaire), MAX(salaire) FROM employes;GROUP BY et HAVING
-- Grouper les résultatsSELECT departement, COUNT(*) AS nb_employesFROM employesGROUP BY departement;
-- Filtrer les groupes (≠ WHERE qui filtre les lignes)SELECT departement, AVG(salaire) AS salaire_moyenFROM employesGROUP BY departementHAVING AVG(salaire) > 3000;Ordre d'exécution
WHERE filtre avant le groupement, HAVING filtre après.
Jointures
-- INNER JOIN : lignes communes aux deux tablesSELECT u.nom, c.montantFROM utilisateurs uINNER JOIN commandes c ON u.id = c.utilisateur_id;
-- LEFT JOIN : toutes les lignes de gauche, nulls à droite si pas de correspondanceSELECT u.nom, c.montantFROM utilisateurs uLEFT JOIN commandes c ON u.id = c.utilisateur_id;
-- RIGHT JOIN : toutes les lignes de droiteSELECT u.nom, c.montantFROM utilisateurs uRIGHT JOIN commandes c ON u.id = c.utilisateur_id;
-- FULL OUTER JOIN : toutes les lignes des deux tablesSELECT u.nom, c.montantFROM utilisateurs uFULL OUTER JOIN commandes c ON u.id = c.utilisateur_id;
-- SELF JOIN : jointure d'une table sur elle-mêmeSELECT a.nom AS employe, b.nom AS managerFROM employes aJOIN employes b ON a.manager_id = b.id;
-- CROSS JOIN : produit cartésienSELECT * FROM taille CROSS JOIN couleur;Insertion de données
-- Insertion d'une ligneINSERT INTO utilisateurs (nom, email, age)VALUES ('Alice', 'alice@example.com', 30);
-- Insertion multipleINSERT INTO utilisateurs (nom, email, age) VALUES ('Bob', 'bob@example.com', 25), ('Carol', 'carol@example.com', 28);
-- Insertion depuis une requêteINSERT INTO archive_utilisateurs (nom, email)SELECT nom, email FROM utilisateurs WHERE actif = false;Mise à jour de données
-- Mettre à jour des lignesUPDATE utilisateursSET email = 'nouveau@example.com', age = 31WHERE id = 42;
-- Mise à jour avec jointure (PostgreSQL / SQL Server)UPDATE commandesSET statut = 'vérifié'FROM utilisateursWHERE commandes.utilisateur_id = utilisateurs.id AND utilisateurs.role = 'admin';Toujours utiliser `WHERE`
Un UPDATE sans clause WHERE modifie toutes les lignes de la table.
Suppression de données
-- Supprimer des lignes filtréesDELETE FROM utilisateurs WHERE actif = false;
-- Vider une table (supprime toutes les lignes)DELETE FROM table; -- supprimable ligne par ligne, transactionnelTRUNCATE TABLE table; -- plus rapide, non transactionnel sur certains SGBDPas de `WHERE` = tout supprimer
Vérifier la clause WHERE avant d’exécuter un DELETE.
Sous-requêtes
-- Dans WHERESELECT nom FROM employesWHERE salaire > (SELECT AVG(salaire) FROM employes);
-- Avec INSELECT nom FROM utilisateursWHERE id IN (SELECT utilisateur_id FROM commandes WHERE montant > 500);
-- Sous-requête corréléeSELECT nom, salaireFROM employes e1WHERE salaire > ( SELECT AVG(salaire) FROM employes e2 WHERE e2.departement = e1.departement);
-- Dans FROM (table dérivée)SELECT dept, salaire_moyenFROM ( SELECT departement AS dept, AVG(salaire) AS salaire_moyen FROM employes GROUP BY departement) AS statsWHERE salaire_moyen > 4000;Expressions de table communes (CTE)
-- CTE simpleWITH employes_seniors AS ( SELECT * FROM employes WHERE anciennete > 5)SELECT departement, COUNT(*) FROM employes_seniorsGROUP BY departement;
-- CTE chaînéesWITH ventes_2024 AS ( SELECT * FROM ventes WHERE YEAR(date) = 2024 ), top_produits AS ( SELECT produit_id, SUM(montant) AS total FROM ventes_2024 GROUP BY produit_id HAVING SUM(montant) > 10000 )SELECT p.nom, t.totalFROM top_produits tJOIN produits p ON t.produit_id = p.id;
-- CTE récursive (ex: hiérarchie)WITH RECURSIVE hierarchie AS ( SELECT id, nom, manager_id, 0 AS niveau FROM employes WHERE manager_id IS NULL
UNION ALL
SELECT e.id, e.nom, e.manager_id, h.niveau + 1 FROM employes e JOIN hierarchie h ON e.manager_id = h.id)SELECT * FROM hierarchie ORDER BY niveau;Fonctions de fenêtrage
-- NumérotationSELECT nom, salaire, ROW_NUMBER() OVER (ORDER BY salaire DESC) AS rang, RANK() OVER (ORDER BY salaire DESC) AS rang_ex_aequo, DENSE_RANK() OVER (ORDER BY salaire DESC) AS rang_denseFROM employes;
-- PartitionnementSELECT nom, departement, salaire, RANK() OVER (PARTITION BY departement ORDER BY salaire DESC) AS rang_deptFROM employes;
-- Agrégats glissantsSELECT date, montant, SUM(montant) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS total_7j, AVG(montant) OVER (PARTITION BY MONTH(date)) AS moy_mensuelleFROM ventes;
-- DécalageSELECT date, montant, LAG(montant, 1) OVER (ORDER BY date) AS montant_precedent, LEAD(montant, 1) OVER (ORDER BY date) AS montant_suivantFROM ventes;Manipulation de chaînes
UPPER(str) -- 'hello' → 'HELLO'LOWER(str) -- 'HELLO' → 'hello'LENGTH(str) -- longueurTRIM(str) -- supprime les espaces en début/finLTRIM(str) / RTRIM(str)SUBSTRING(str, 1, 3) -- extrait 3 caractères depuis la position 1CONCAT(a, ' ', b) -- concaténationREPLACE(str, 'a', 'b') -- remplace toutes les occurrencesPOSITION('sub' IN str) -- position de la sous-chaîneCOALESCE(col, 'défaut') -- retourne la première valeur non nulleManipulation de dates
NOW() / CURRENT_TIMESTAMP -- date et heure actuellesCURRENT_DATE -- date du jourCURRENT_TIME -- heure actuelle
DATE_ADD(date, INTERVAL 7 DAY) -- MySQLdate + INTERVAL '7 days' -- PostgreSQL
DATEDIFF(date1, date2) -- différence en jours (MySQL)date1 - date2 -- différence en jours (PostgreSQL)
EXTRACT(YEAR FROM date) -- extraire l'annéeDATE_FORMAT(date, '%Y-%m') -- formater (MySQL)TO_CHAR(date, 'YYYY-MM') -- formater (PostgreSQL)Opérations sur les ensembles
-- Union (dédoublonnée)SELECT nom FROM clientsUNIONSELECT nom FROM fournisseurs;
-- Union avec doublonsSELECT nom FROM clientsUNION ALLSELECT nom FROM fournisseurs;
-- IntersectionSELECT nom FROM clientsINTERSECTSELECT nom FROM fournisseurs;
-- DifférenceSELECT nom FROM clientsEXCEPT -- PostgreSQL / SQL ServerSELECT nom FROM fournisseurs;-- ou MINUS sur OracleExpressions conditionnelles
-- CASE simpleSELECT nom, CASE statut WHEN 'A' THEN 'Actif' WHEN 'I' THEN 'Inactif' ELSE 'Inconnu' END AS libelle_statutFROM utilisateurs;
-- CASE recherchéSELECT nom, salaire, CASE WHEN salaire < 2000 THEN 'Bas' WHEN salaire < 4000 THEN 'Moyen' ELSE 'Élevé' END AS trancheFROM employes;
-- RaccourcisCOALESCE(a, b, c) -- premier non NULLNULLIF(a, b) -- NULL si a = b, sinon aIIF(condition, a, b) -- SQL Server uniquementTransactions
BEGIN; -- ou START TRANSACTION
UPDATE comptes SET solde = solde - 100 WHERE id = 1;UPDATE comptes SET solde = solde + 100 WHERE id = 2;
COMMIT; -- valider-- ouROLLBACK; -- annuler
-- Point de sauvegardeSAVEPOINT mon_point;ROLLBACK TO mon_point;RELEASE SAVEPOINT mon_point;Propriétés ACID
Une transaction garantit Atomicité, Cohérence, Isolation et Durabilité.
Bonnes pratiques
- Toujours tester un
UPDATE/DELETEavec unSELECTéquivalent d’abord. - Utiliser des transactions pour les opérations multi-étapes critiques.
- Préférer les CTEs aux sous-requêtes imbriquées pour la lisibilité.
- Éviter
SELECT *en production — nommer les colonnes explicitement. - Indexer les colonnes utilisées dans
WHERE,JOIN ONetORDER BY. - Utiliser
EXPLAIN/EXPLAIN ANALYZEpour diagnostiquer les performances.
EXPLAIN ANALYZESELECT u.nom, COUNT(c.id)FROM utilisateurs uLEFT JOIN commandes c ON u.id = c.utilisateur_idGROUP BY u.nom;