NULL en SQL est l'une des notions les plus mal comprises par les développeurs et les data analysts. Contrairement à un zéro ou à une chaîne vide, NULL représente l'absence totale de valeur — et cette distinction change radicalement la façon dont vos requêtes se comportent. Ignorer ce principe mène à des résultats faux, des jointures incomplètes et des bugs difficiles à tracer en production.
Dans cet article, vous allez comprendre ce qu'est réellement NULL, comment l'identifier, comment le filtrer et comment le remplacer proprement. Que vous passiez un test technique ou que vous travailliez sur un pipeline de données, maîtriser NULL est non-négociable.
📌 Ce qu'il faut retenir
- NULL n'est pas égal à 0, ni à une chaîne vide : c'est l'absence de donnée
- Toute comparaison avec NULL renvoie UNKNOWN, jamais TRUE ni FALSE
IS NULLetIS NOT NULLsont les seuls opérateurs fiables pour tester NULLCOALESCEetNULLIFpermettent de remplacer ou de produire des NULL proprement
Ce que NULL signifie vraiment en SQL
NULL représente une valeur inconnue ou inapplicable. Ce concept vient de l'algèbre relationnelle définie par Edgar F. Codd dans les années 1970. Le standard SQL ISO intègre cette logique dite ternaire : une condition peut être TRUE, FALSE ou UNKNOWN.
Quand vous écrivez WHERE age = NULL, la condition retourne UNKNOWN — et non FALSE. Le moteur SQL n'inclut donc aucune ligne, même celles où age vaut effectivement NULL. C'est le piège numéro 1 rencontré par les candidats lors des tests techniques.
Pour tester la présence de NULL, vous devez utiliser IS NULL ou IS NOT NULL, jamais = NULL ni <> NULL.
-- Incorrect
SELECT * FROM utilisateurs WHERE email = NULL;
-- Correct
SELECT * FROM utilisateurs WHERE email IS NULL;
La logique ternaire et ses conséquences sur vos requêtes
La logique ternaire impacte bien plus que les simples clauses WHERE. Elle se propage dans les jointures, les agrégats et les expressions conditionnelles. Comprendre ses effets vous évitera des heures de débogage.
NULL dans les agrégats
Les fonctions d'agrégat comme SUM, AVG, COUNT ignorent silencieusement les valeurs NULL. COUNT(*) compte toutes les lignes, mais COUNT(colonne) exclut les lignes où colonne est NULL — une différence qui peut fausser vos métriques.
-- Compte toutes les lignes : 1000
SELECT COUNT(*) FROM commandes;
-- Compte uniquement les lignes avec un montant renseigné : 847
SELECT COUNT(montant) FROM commandes;
Pour approfondir les subtilités des fonctions d'agrégat, consultez notre guide sur les fonctions d'agrégat SQL : SUM, COUNT, AVG, MIN, MAX.
NULL dans les jointures
Un NULL dans une colonne de jointure ne correspond jamais à un autre NULL. Deux lignes dont la clé de jointure est NULL ne seront donc pas associées, même en LEFT JOIN. Ce comportement est souvent source de pertes de données silencieuses dans les pipelines ETL.
⚠️ Attention
Dans une condition de jointure, NULL n'est jamais égal à NULL. Si vos colonnes de clé contiennent des NULL, les lignes correspondantes seront perdues sans aucun message d'erreur. Nettoyez vos données en amont ou utilisez COALESCE pour substituer une valeur sentinelle.
NULL dans les expressions arithmétiques
Toute opération arithmétique impliquant NULL retourne NULL. 100 + NULL = NULL, NULL * 5 = NULL. Si votre calcul de revenu utilise une colonne partiellement renseignée, le résultat sera NULL pour toutes les lignes concernées.
Les outils SQL pour traiter les NULL
SQL propose plusieurs fonctions natives pour gérer les valeurs manquantes de façon propre et lisible.
COALESCE : remplacer NULL par une valeur par défaut
COALESCE(expr1, expr2, ..., exprN) retourne la première valeur non-NULL de la liste. C'est la fonction la plus utilisée pour sécuriser les calculs.
-- Remplace un montant NULL par 0 avant de calculer
SELECT
id_commande,
COALESCE(montant, 0) AS montant_securise
FROM commandes;
Vous pouvez enchaîner plusieurs alternatives : COALESCE(prix_promo, prix_standard, 0) cherche d'abord un prix promotionnel, puis le prix standard, puis retourne 0.
NULLIF : produire NULL sous condition
NULLIF(expr1, expr2) retourne NULL si les deux expressions sont égales, sinon retourne expr1. Son usage le plus courant : éviter les divisions par zéro.
-- Évite la division par zéro
SELECT
chiffre_affaires / NULLIF(nombre_transactions, 0) AS panier_moyen
FROM stats_mensuelles;
Sans NULLIF, une division par zéro lèverait une erreur et interromprait votre requête.
CASE WHEN pour une logique conditionnelle avancée
Quand la logique de remplacement est complexe, CASE WHEN offre plus de flexibilité que COALESCE. Vous pouvez combiner les deux pour des traitements élaborés.
SELECT
utilisateur_id,
CASE
WHEN statut IS NULL THEN 'Non défini'
WHEN statut = '' THEN 'Vide'
ELSE statut
END AS statut_propre
FROM utilisateurs;
Pour aller plus loin sur les expressions conditionnelles, lisez notre article sur CASE WHEN en SQL : syntaxe, exemples et cas pratiques.
Tableau comparatif des fonctions de gestion des NULL
| Fonction | Syntaxe | Cas d'usage principal | Compatibilité |
|---|---|---|---|
| IS NULL | colonne IS NULL |
Filtrer les lignes sans valeur | Tous les SGBD |
| COALESCE | COALESCE(val1, val2, ...) |
Remplacer NULL par une valeur par défaut | Tous les SGBD |
| NULLIF | NULLIF(expr1, expr2) |
Produire NULL pour éviter erreurs (ex. div/0) | Tous les SGBD |
| IFNULL | IFNULL(val, defaut) |
Équivalent COALESCE à 2 arguments | MySQL, SQLite |
| NVL | NVL(val, defaut) |
Équivalent COALESCE à 2 arguments | Oracle uniquement |
| ISNULL | ISNULL(val, defaut) |
Équivalent COALESCE à 2 arguments | SQL Server uniquement |
