Null n’est pas une valeur

Cet article s’adresse à tous ceux et celles qui considèrent Null comme une valeur particulière. Je pense notamment aux développeurs C#, pour qui null est une valeur spécifique.

Du point de vue SQL Server, Null n’est pas une valeur, mais reflète la non connaissance d’une information.

Sous SQL Server, Null indique une absence d’information. Prenons par exemple cette liste de Produits.

use tempdb
go
create table Produits (IdProduit int identity,
						Nom varchar(100),
						Prix money)
insert into Produits (Nom,Prix)
	values ('Clavier',10),
			('Ecran', 100),
			('Souris', 15),
			('CPU', Null),
			('Webcam',40)

Si l’on cherche à avoir tous les produits de 50 Euros ou moins, on obtient le clavier, la souris et la webcam.

select *
from Produits
where Prix<=50

Et si l’on cherche à avoir tous les produits de plus de 50 Euros, il n’y a que l’Ecran.

select *
from Produits
where Prix>50

Et où est le CPU dans l’histoire ? Et bien l’assertion “Le prix est inférieur ou égal à 50 Euros” ne peut pas être considérée comme vraie, puisqu’on ne connait pas le prix du CPU. Mais en même temps, l’assertion “Le prix du CPU est supérieur à 50 Euros” ne peut pas non plus être considérée comme vraie. En fait, Null signifie qu’on ne connait pas le prix du CPU, et donc qu’on ne peut comparer quelque chose qu’on ne connait pas à 50 Euros. Est-ce plus cher ? Est-ce moins cher ? On ne sait pas.

Mais ce qu’il est vraiment primordial de comprendre, c’est que, par exemple, l’assertion “Le prix est inférieur ou égal à 50 Euros” n’est pas vraie, mais elle n’en est pas néanmoins fausse pour autant !

select *
from Produits
where NOT (Prix<=50)

En fait, on ne peut pas dire que le prix du CPU est inférieur à 50 Euros, mais on ne peut pas dire non plus qu’il ne l’est pas ! L’état de cette assertion est “Inconnu”.

Et sous SQL Server, les clauses “Where”, de même que les jointures, filtrent les enregistrements pour lesquels le prédicat est vrai. Et par vrai, il est entendu que le prédicat est confirmé comme vérifié.

Attention, toute la subtilité est là : un prédicat vrai, ce n’est pas un prédicat qui n’est pas faux.

Dans notre cas, le fait de dire que l’assertion NOT (Prix<=50) est vraie revient à dire que l’assertion Prix<=50 est fausse. Or nous avons vu que, pour le cas de notre produit CPU, nous ne pouvons pas affirmer que l’assertion Prix<=50 est fausse, car nous ne connaissons pas le prix. Nous ne pouvons rien dire, tout simplement.

Voici au final une requête qui résume la problématique :

select *
from Produits
where	(Prix<=50)
	OR
		(NOT (Prix<=50))

Il nous manque bien notre produit CPU.

Il n’est pas vrai de dire que son prix est inférieur à 50 Euros, mais il n’est pas vrai de dire qu’il est faux de dire que son prix est inférieur à 50 Euros. (ça commence à devenir un peu compliqué, là… :-)  )

Quand on ne sait pas, on n’affirme rien, mais on ne nie rien non plus…

Pour finir, rajoutons quelques produits dans la liste.

insert into Produits (Nom,Prix)
	values ('Tapis souris',10),
			('Carte graphique', 100),
			('Carte mère', Null)

Et regardons les paires de produits ayant le même prix :

select p1.Nom, p2.Nom
from Produits p1
	join Produits p2 on p1.IdProduit < p2.IdProduit
					and p1.Prix=p2.Prix

Les produits Carte Mère et CPU n’ont pas nécessairement le même prix donc, logiquement, on ne les voit pas dans la liste.

Mais si on cherche les prix différents :

select p1.Nom, p2.Nom
from Produits p1
	join Produits p2 on p1.IdProduit < p2.IdProduit
					and p1.Prix<>p2.Prix

Il est très intéressant de voir que ni le CPU, ni la Carte mère ne sont présents dans la liste. Et pour cause, étant donné qu’on ne connait pas leur prix, on ne peut pas affirmer qu’il est différent du prix de tel ou tel autre produit. Et même, tout comme on ne pouvait pas affirmer que ces deux produits avaient le même prix, on ne peut pas affirmer qu’ils sont de prix différents.

Null n’est pas égal à Null, mais Null n’est pas différent de Null.

Au final, Null n’est pas un pointeur vers l’adresse mémoire 0, c’est la marque d’une non-connaissance, et donc la fin de toute assertion.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Contrôle de sécurité *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.