Écrire du SQL, ce n’est pas difficile ; bien l’écrire, si.
Beekeeper Studio est une interface de base de données gratuite & open source
Le meilleur outil de requêtes & éditeur SQL que j’aie jamais utilisé. Il m’offre tout ce dont j’ai besoin pour gérer ma base de données. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio est rapide, intuitif et facile à utiliser. Beekeeper prend en charge plein de bases de données et fonctionne parfaitement sous Windows, Mac et Linux.
Des requêtes qui marchent très bien en développement commencent à ramer en production. Un ORDER BY oublié renvoie des résultats incohérents, un petit SELECT * casse dès que le schéma change, et des filtres anodins sur un petit jeu de données peuvent tout bloquer à grande échelle.
Avec le temps, tu repères les approches qui tiennent la route et celles qui ne tiennent pas.
Voici donc sept bonnes pratiques SQL, proposées par l’équipe derrière Beekeeper Studio, l’interface de base de données moderne, open source et multiplateforme.
🔖 Aide-mémoire : pendant que tu apprends ces bonnes pratiques, garde notre antisèche du langage SQL sous la main pour retrouver rapidement SELECT, WHERE, les JOIN, les agrégats et d’autres commandes SQL essentielles.
1. Sois précis — évite SELECT *
Récupérer toutes les colonnes avec SELECT * peut sembler rapide et flexible. Pas besoin de choisir les colonnes à renvoyer ou à exclure, et ça marche bien tant que tu explores encore un jeu de données.
Mais cette flexibilité a un prix. À mesure que les schémas évoluent ou que les jointures se multiplient, SELECT * peut ramener des colonnes en double ou inattendues, ralentir tes requêtes et compliquer le débogage.
Choisir des colonnes précises rend ton intention claire et protège ton code des casses silencieuses.
-- Risky
SELECT * FROM user_profiles WHERE user_id = 42;
-- Better
SELECT user_id, display_name, avatar_url
FROM user_profiles
WHERE user_id = 42;
2. Utilise les CTE pour simplifier la logique complexe
Les sous-requêtes imbriquées fonctionnent, mais deviennent vite illisibles. Difficile de voir ce qui est filtré où, et déboguer revient souvent à faire des allers-retours entre des couches de parenthèses.
Les Common Table Expressions (clauses WITH) te permettent de découper une requête en étapes nommées. Chaque étape peut être exécutée et testée isolément, ce qui clarifie l’intention et facilite le traçage des erreurs. Garde juste en tête que certaines bases de données matérialisent les CTE, donc des sous-requêtes inline peuvent être plus rapides dans des boucles serrées.
-- Hard to follow
SELECT customer_id, COUNT(*)
FROM (
SELECT customer_id, created_at
FROM orders
WHERE created_at > now() - interval '7 days'
) o
GROUP BY customer_id;
-- Clearer
WITH recent_orders AS (
SELECT customer_id, created_at
FROM orders
WHERE created_at > now() - interval '7 days'
)
SELECT customer_id, COUNT(*)
FROM recent_orders
GROUP BY customer_id;
3. Commente ton intention, pas ta syntaxe
Les commentaires qui répètent ce que le SQL montre déjà n’apportent pas grand-chose. Le vrai contexte que tu oublieras plus tard, ce n’est pas ce que fait la requête, mais pourquoi elle existe.
Une courte note sur l’objectif ou l’usage facilite la relecture ou la transmission du code plus tard. Écris pour toi dans le futur, ou pour le prochain développeur qui cherchera à comprendre pourquoi cette requête compte.
-- Find users who signed up but never activated
-- Used in the weekly retention cohort report
SELECT u.id, u.email
FROM users u
LEFT JOIN events e
ON u.id = e.user_id
AND e.name = 'account_activated'
WHERE e.id IS NULL
AND u.created_at > now() - interval '7 days';
4. Rends tes filtres compatibles avec les index
Les index n’aident que si tes filtres sont « sargables » (pour Search ARGument ABLE). En pratique, cela signifie que la base de données peut utiliser l’index directement au lieu de parcourir chaque ligne.
Si tu enveloppes une colonne dans une fonction — par exemple LOWER(email) ou DATE(created_at) — l’optimiseur ne peut pas utiliser l’index. Même les conversions de type peuvent avoir cet effet. La requête fonctionne toujours, mais elle ralentit à mesure que tes données grossissent.
-- Not sargable: disables index
WHERE LOWER(email) = 'test@example.com';
-- Sargable: uses existing index
WHERE email = 'test@example.com';
Pour garder des filtres efficaces, écris-les en fonction de la façon dont les données sont stockées. Si tu as besoin d’une comparaison insensible à la casse, stocke les valeurs dans un format cohérent ou ajoute un index fonctionnel. Pour les dates, filtre par plage plutôt que de transformer la colonne — c’est plus clair et l’index reste utilisable.
-- Not sargable
WHERE DATE(created_at) = '2025-08-04';
-- Sargable
WHERE created_at >= '2025-08-04'
AND created_at < '2025-08-05';
5. Filtre avant de joindre
Il est tentant de tout joindre d’abord et de filtrer ensuite, surtout quand tu explores ou prototypes. Mais chaque jointure multiplie les lignes, et chaque ligne inutile rend ta requête plus lente et plus difficile à planifier pour l’optimiseur.
Réduis plutôt chaque table avant de les combiner. Ainsi, la base de données ne joint que les données qui comptent vraiment — moins de mémoire utilisée, un cache plus efficace et un plan d’exécution prévisible.
-- Joins every user, even inactive ones
SELECT e.*
FROM users u
JOIN events e ON e.user_id = u.id;
-- Filter first: only active, recently seen users
WITH active_users AS (
SELECT id
FROM users
WHERE active = true
AND last_seen > now() - interval '90 days'
)
SELECT e.*
FROM active_users u
JOIN events e ON e.user_id = u.id;
6. Préfère EXISTS à IN pour vérifier des relations
Quand tu vérifies si des lignes liées existent, IN fait le travail — jusqu’au jour où ce n’est plus le cas. Il construit une liste complète de valeurs, compare chacune d’elles et traite les NULL d’une façon qui peut masquer des correspondances valides.
EXISTS fonctionne différemment. Il renvoie vrai dès qu’il trouve une correspondance et n’est pas affecté par les NULL de la sous-requête. Résultat : plus rapide et plus fiable, surtout sur de gros jeux de données.
-- Works, but can be slower and NULL-prone
SELECT *
FROM users
WHERE id IN (SELECT user_id FROM orders);
-- Clear and efficient: stops at first match
SELECT *
FROM users u
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.id
);
7. Précise toujours un ORDER BY
SQL ne garantit aucun ordre des lignes si tu ne le demandes pas.
Sans ORDER BY, la base de données est libre de renvoyer les lignes dans l’ordre qui lui convient le mieux, et cet ordre peut changer d’une exécution à l’autre, d’un environnement à l’autre, ou même après une mise à jour mineure.
Ça peut sembler stable en développement, mais dès que les index, les plans d’exécution ou le volume de données évoluent, tu verras apparaître une pagination imprévisible ou des résultats d’API incohérents.
-- Looks fine until it isn't
SELECT id, name
FROM users
WHERE active = true
LIMIT 10;
-- Predictable and reproducible
SELECT id, name
FROM users
WHERE active = true
ORDER BY created_at DESC
LIMIT 10;
Pour résumer
Les meilleures requêtes sont celles que tu comprends encore un an plus tard. Leur intention est claire, leur comportement prévisible, et elles ne cachent aucune surprise.
C’est l’esprit de ces habitudes. Ce sont des pratiques que nous utilisons tous les jours chez Beekeeper Studio pour garder des requêtes lisibles, cohérentes et rapides sur toutes les bases de données avec lesquelles nous travaillons.
Tu peux récupérer gratuitement une version PDF de ce guide pour l’avoir sous la main ou le partager avec ton équipe :
Télécharger 7 SQL Habits for Busy Developers
Avec Beekeeper Studio, tu peux appliquer ces habitudes au quotidien grâce à un éditeur SQL open source, moderne et multiplateforme, conçu pour que tu restes concentré.
- Plus de 20 bases de données prises en charge : Postgres, MySQL, SQLite, SQL Server, MongoDB, Redis et plus encore.
- Éditeur rapide et réactif : autocomplétion qui connaît ton schéma, requêtes en onglets et coloration syntaxique.
- Outils de données visuels : parcours les tables, modifie des lignes et inspecte du JSON sans perdre le fil.
- Assistant IA (respectueux de ta vie privée) : l’outil de code IA qui manquait à ta base de données — il connaît ton schéma, fonctionne avec le LLM de ton choix et t’aide à explorer et affiner tes requêtes plus vite.