[Actualité] SQL et logique trivaluée : null vs vide
par
, 29/02/2024 à 16h26 (5910 Affichages)
Il est important de comprendre la différence entre une colonne marquée "Null" et une colonne dont la valeur est vide.
Confondre l'un et l'autre est une source fréquente d'erreurs.
NULL :
- null n'est pas une valeur, mais un marqueur d'absence de valeur ;
- null est applicable sur tout type de colonnes (caractère, numérique, date...) à l'exception bien entendu de celles ayant une contrainte "not null"
mais null est obtenu en cas de jointure externe (OUTER JOIN) non satisfaite, y compris si la colonne concernée est marquée "not null" ;- null est à prendre en compte dans les tables de décision avec les opérateurs AND, OR et NOT (voir plus bas) ;
- comme Null est une absence de valeur, on ne peut pas écrire IF MA_COLONNE = null, car null n'est égal à rien, pas même à null ! On écrira donc IF MA_COLONNE is null ;
- pour remplacer une réponse "Null" par une valeur, on peut utiliser au choix la fonction ISNULL() ou COALESCE().
VIDE :
- vide n'a de sens que pour les types chaînes de caractères (char, varchar, nchar, nvarchar, text) ;
- IF MA_COLONNE = '' est une expression valide puisque vide est une valeur.
L'exemple suivant, applicable sur tous les SGBD à l'exception d'Oracle qui confond allègrement "null" et vide, au mépris des normes SQL et de toute logique , montre bien ces différences entre chaîne vide et marqueur "null" :
Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 -- création d'une table dont toutes les colonnes sont "nullables" -- pour démonstration : null <> vide create table T1 ( T1INTG integer , T1CHA1 char(4) , T1CHA2 char(4) , T1DATE date ) ; insert into T1(T1INTG, T1CHA1, T1CHA2, T1DATE) values (0001, 'TOTO', 'TOTO', '2024-02-27') , (0002, null, '', null ) , (null, 'TITI', 'TOTO', '2024-02-28') ; -- insertion d'une valeur vide dans des colonnes de type char : pas de problème insert into T1(T1INTG, T1CHA1, T1CHA2, T1DATE) values (0004, '' , '', '2024-02-29') , (0005, null , null, '2024-02-29') ; select T1INTG , T1CHA1 , T1CHA2 , T1DATE , case when T1CHA1 = T1CHA2 then 'égal' else 'différent' end as "CHA1/CHA2" from T1 ; -- tentative d'insertion d'une valeur vide dans une colonne d'un autre type : KO insert into T1(T1INTG, T1CHA1, T1CHA2, T1DATE) values (0005, 'XXXX', 'YYYY', '')
Résultat (le message d'erreur de la tentative d'insertion d'un "null" dans une colonne de type non char dépend du SGBD, ici c'est sous MySQL 8.0 :
Table de décision avec les marqueurs "null"