Ensemble Firebird Doc → Firebird Docs → 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 | NULL | Si A est indéterminée, alors 6 + A est aussi indéterminée. |
'Home ' || 'sweet ' || A | NULL | Si A est indéterminée, 'Home sweet ' || A est aussi indéterminée. |
MonChamp = A | NULL | Si A est indéterminée, vous ne pouvez dire si MonChamp à la même valeur... |
MonChamp <> A | NULL | ...mais vous ne pouvez non plus dire si MonChamp à une valeur différente ! |
A = B | NULL | Avec A et B indéterminées, il est impossible de savoir si elles sont égales. |
not (A) | NULL | Si A est indéterminée, sa négation est aussi indéterminée. |
Non avons déjà vu que not(NULL) renvoie 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) | NULL | « A or false » a toujours la même valeur que A - qui est indéterminée. |
A or (true) | true | « A or true » est toujours true - la valeur de A n'a pas d'importance. |
A or A | NULL | « A or A » est toujours égal à A - qui est NULL. |
A and (false) | false | « A and false » est toujours false - la valeur de A n'a pas d'importance. |
A and (true) | NULL | « A and true » a toujours la même valeur que A - qui est indéterminée. |
A and A | NULL | « 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 true » et « X and false », 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.
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:
MyTable
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(FieldName) ne renvoient jamais NULL: s'il n'y a pas d'enregistrement dans l'ensemble de données les deux fonctions renvoient 0. Ainsi, COUNT(FieldName) renvoie 0 si tous les champs 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.
Ensemble Firebird Doc → Firebird Docs → Guide Firebird et NULL → NULL dans les expressions |