Firebird Documentation Index → Guide Firebird et NULL → NULL dans les expressions |
Combien d'entre nous ont appris à leurs dépends que
NULL
est contagieux: utilisez le dans une expression
numérique, de chaîne de caractère ou de date/heure, et le résultat sera
toujours NULL
. Utilisez le dans une expression
booléenne, et le résultat dépendra du type d' opération et des autres
valeurs impliquées.
Notez au passage que dans les versions de Firebird avant 2.0, il est
le plus souvent illégal d'utiliser la constante NULL
directement dans des opérations ou comparaisons. Partout où vous verrez
NULL
dans les instructions suivantes, lisez le comme
« un champ, une variable ou une autre expression renvoyant
NULL
».
Les expressions dans cette liste renvoient
toujours NULL
:
1 + 2 + 3 +
NULL
'Home ' || 'sweet ' ||
NULL
MyField =
NULL
MyField <>
NULL
NULL
=
NULL
not (
NULL
)
Si vous avez des difficultés à comprendre pourquoi, souvenez vous
que NULL
signifie « indéterminé ».
Regardez aussi le tableau suivant où des explications sont données au
cas par cas. Dans le tableau nous n'écrivons pas
NULL
dans les expressions (comme dit plus haut,
c'est souvent interdit); à la place, nous utilisons deux entités A et B
qui sont toutes deux NULL
. A et B peuvent être des
champs, des variables, ou des sous-expressions - du moment quelles sont
NULL
, elles ont le même comportement dans les
expressions utilisées.
Tableau 1. Opérations des entités A et B null
Si A et B sont NULL, alors: | Est: | Parce que: |
---|---|---|
1 + 2 + 3 + A |
|
Si A est indéterminée, alors 6 + A est aussi indéterminée. |
'Home ' || 'sweet ' || A |
|
Si A est indéterminée, 'Home sweet ' || A est aussi indéterminée. |
MonChamp = A |
|
Si A est indéterminée, vous ne pouvez dire si MonChamp à la même valeur... |
MonChamp <> A |
|
...mais vous ne pouvez non plus dire si MonChamp à une valeur différente ! |
A = B |
|
Avec A et B indéterminées, il est impossible de savoir si elles sont égales. |
not (A) |
|
Si A est indéterminée, sa négation est aussi indéterminée. |
Non avons déjà vu que
not(
renvoie
NULL
)NULL
. Pour les opérateurs and
et
or
, les choses sont un peu plus compliquées :
NULL
or
false
=
NULL
NULL
or
true
=
true
NULL
or
NULL
=
NULL
NULL
and
false
=
false
NULL
and
true
=
NULL
NULL
and
NULL
=
NULL
Le SQL Firebird n'a pas de type booléen; les constantes
true
et false
n'existent pas.
Dans la colonne de gauche du tableau suivant, (true)
et (false)
représentent des expressions renvoyant
true
/false
.
Tableau 2. Opérations booléennes sur une entité A null
Si A est NULL ,
alors:
|
Est: | Parce que: |
---|---|---|
A or (false) |
|
« A or
» a toujours la même
valeur que A - qui est indéterminée.
|
A or (true) |
|
« A or
» est toujours
true - la valeur de A n'a pas
d'importance.
|
A or A |
|
« A or A » est toujours
égal à A - qui est NULL .
|
A and (false) |
|
« A and
» est toujours
false - la valeur de A n'a pas
d'importance.
|
A and (true) |
|
« A and
» a toujours la même
valeur que A - qui est indéterminée.
|
A and A |
|
« A and A » est toujours
égal à A - qui est NULL .
|
Tous ces résultats sont en accord avec la logique booléenne. Le
fait que, pour calculer « X or
» et « true
X and
», vous n'ayez simplement pas
besoin de connaitre la valeur de X, fait partie des
bases d'une fonctionnalité que nous connaissons dans divers langages de
programmation : l'évaluation booléenne rapide.
false
Les résultats obtenus ci-dessus pourraient vous mener aux idées suivantes :
0 fois x
égal 0 pour tout
x
. En conséquence, même si la valeur de
x
est indéterminée, 0 * x
égal
0. (Note: ceci seulement si x
est d'un type
n'acceptant que des nombres, pas NaN
ou
infini.)
Un chaîne vide est classée lexicographiquement avant toute
autre chaîne. Donc, S >= ''
est vrai quelque
soit la valeur de S.
Chaque valeur est égale à elle même, qu'elle soit connue ou
pas. Donc, bien que A = B
renvoie
NULL
si A et B sont des entités
NULL
différentes, A = A
devrait toujours retourner true
, même si A est
NULL
.
Comment cela est-il implémenté dans le SQL de Firebird ? Et bien,
je suis désolé de vous dire qu'en dépit de toute cette logique - et les
analogies avec les résultats booléens discutés ci-dessus - toutes ces
expressions renvoient NULL
:
0 * NULL
NULL
>= ''
'' <=
NULL
A = A
(avec A comme champ ou variable
null)
Et voilà pour la logique.
Dans des fonctions d'agrégat comme COUNT
,
SUM
, AVG
,
MAX
, et MIN
,
NULL
est géré différemment: pour calculer le
résultat, seuls les champs non-NULL
sont pris en
considération. C'est à dire que, si vous avez cette table:
ID | Name | Amount |
---|---|---|
1 | John | 37 |
2 | Jack | <NULL >
|
3 | Joe | 5 |
4 | Josh | 12 |
5 | Jay | <NULL >
|
...l'instruction select sum(Amount) from
MyTable
renvoie 54, qui est 37 + 5 + 12. Si les cinq champs
avaient été additionnés, le résultat aurait été
NULL
. Pour AVG
, les champs
non-NULL
sont additionnés et la somme est divisée
par le nombre de champs non-NULL
.
Il y a seulement une exception à cette règle:
COUNT(*)
renvoie le dénombrement de toutes les
lignes, même celles pour lesquelles les champs sont
NULL
. Mais
COUNT
(FieldName
) se comporte
comme les autres fonctions d'agrégat et ne compte que les
enregistrements pour lesquels le champ spécifié est non
NULL
.
Une autre chose à savoir est que COUNT(*)
et
COUNT(
ne
renvoient jamais FieldName
)NULL
: s'il n'y a pas
d'enregistrement dans l'ensemble de données les deux fonctions renvoient
0. Ainsi, COUNT(
renvoie 0 si tous les champs FieldName
)FieldName
dans
l'ensemble de données sont NULL
. Les autres
fonctions d'agrégat renvoient NULL
dans ce cas.
Faites attention que même SUM
renvoie
NULL
s'il est utilisé sur un ensemble vide, ce qui
est contraire à la logique commune.
Firebird Documentation Index → Guide Firebird et NULL → NULL dans les expressions |