Firebird Documentation Index → Guida sull'uso di NULL nel linguaggio SQL di Firebird → NULL nelle espressioni |
Come molti di noi hanno scoperto con sconforto,
NULL
è contagioso: usato in una espressione numerica,
di stringhe, o data/ora, il risultato sarà sempre e comunque
NULL
. Usandolo invece in una operazione logica, il
risultato dipende dal tipo dell'operazione e degli altri valori
coinvolti.
Notare, inoltre, che nelle versioni di Firebird precedenti alla 2.0
è abbastanza illegale utilizzare NULL
direttamente
nelle operazioni o nei confronti. Dovunque si vede
NULL
nelle seguenti espressioni, va letto come
«un campo, una variabile o altra espressione che vale
NULL
». In Firebird 2 e successivi questa
espressione può anche essere un NULL
letterale.
Le espressioni nella seguente lista riportano sempre e
comunque tutte NULL
:
1 + 2 + 3 +
NULL
5 *
NULL
- 7
'Casa ' || 'dolce ' ||
NULL
IlMioCampo =
NULL
IlMioCampo <>
NULL
NULL
=
NULL
Se si ha proprio difficoltà a capire perchè, basta rammentare che
NULL
significa «sconosciuto».
Guardiamo ora nella seguente tabella, dove sono spiegate caso per caso
tutte le precedenti espressioni. In questa tabella non usiamo
NULL
nelle espressioni (come già accennato, questo
è spesso illegale); invece usiamo due entità, diciamo A e B, che sono
entrambe NULL
. A e B possono essere campi,
variabili, od intere sottoespressioni, le quali, fintantochè sono di
valore NULL
, si comportano sempre allo stesso modo
nelle espressioni mostrate.
Tabella 1. Operazioni sulle entità null A and B
Se A e B sono NULL, allora: | vale | per questo motivo |
---|---|---|
1 + 2 + 3 + A |
|
Se A è sconosciuto, allora anche 6 + A è sconosciuto. |
5 * A - 7 |
|
Se A è sconosciuto, allora lo è anche 5 * A. Sottrargli 7 finisce per dare un altra quantità sconosciuta. |
'Casa ' || 'dolce ' || A |
|
Se A è sconosciuto, 'Casa dolce ' || A è sconosciuto. |
MioCampo = A |
|
Se A è sconosciuto, non si può dire se MioCampo ha lo stesso valore... |
MioCampo <> A |
|
...ma non si può neanche dire se MioCampo ha un valore differente! |
A = B |
|
Se A e B sono sconosciuti, è impossibile sapere se sono uguali. |
Questa è la lista completa degli operatori matematici e su
stringhe che riportano NULL
se almeno uno degli
operandi è NULL
:
+
,
-
, *
,
/
,
e
%
!=
,
~=
,
e ^=
(sinonimo di <>
)
<
,
<=
,
>
,
e
>=
!<
,
~<
,
e
^<
(bassa precedenza, sinonimo di
>=
)
!>
,
~>
,
e
^>
(bassa precedenza, sinonimo di
<=
)
||
[NOT] BETWEEN
[NOT] STARTING WITH
[NOT] LIKE
[NOT] CONTAINING
Ogni spiegazione segue lo stesso schema: se A è sconosciuto, non si può dire che sia maggiore di B; se la stringa S1 è sconosciuta, non si può dire che contiene la stringa S2; e così via.
Usare LIKE con carattere di escape
NULL
fa in modo da mandare in crash il server nelle
versioni Firebird fino alla 1.5 inclusa. Questo problema è stato risolto
nella versione 1.5.1. Da quella versione in poi un tale comando riporta
un insieme di record vuoto.
Nel seguito indicheremo spesso con la coppia di termini inglesi
true
e false
, usate
abitualmente in informatica, le relativa coppia di condizioni logiche
«vero» e «falso».
Tutti gli operatori fin qui visti riportano
NULL
se qualche operando è
NULL
. Con gli operatori logici booleani, le cose
sono un po' più complicate:
not
NULL
=
NULL
NULL
or
false
=
NULL
NULL
or
true
=
true
NULL
or
NULL
=
NULL
NULL
and
false
=
false
NULL
and
true
=
NULL
NULL
and
NULL
=
NULL
Firebird SQL non ha un tipo di dato boolean; nè
true
o false
sono costanti
definite. Nella colonna a sinistra della tabella successiva,
«true
» e
«false
» rappresentano delle espressioni
con campi, variabili, ecc.., che valgono true
oppure false
(ad esempio: 1=1 è sempre
«vero», 1=0 è sempre «falso»).
Tabella 2. Operazioni logiche sull'entità di valore null A
Se A è NULL ,
allora
|
vale | per questo motivo |
---|---|---|
not (A) |
|
Se A è sconosciuto, è sconosciuto anche il suo inverso (o la sua negazione). |
A or (false) |
|
«A or
» ha sempre il valore
di A - che è sconosciuto.
|
A or (true) |
|
«A or
» è sempre
true , perchè il valore di A non ha
importanza.
|
A or A |
|
«A or A » è sempre A, che
è sconosciuto, cioè NULL .
|
A and (false) |
|
«A and
» è sempre falso,
perchè il valore di A non conta.
|
A and (true) |
|
«A and
» ha sempre il valore
di A - che è sconosciuto.
|
A and A |
|
«A and A » è sempre A, che
è sconosciuto, cioè NULL .
|
Tutti questi risultati sono in accordo con la logica booleana. Il
fatto che non si ha la necessità di conoscere il valore di X per
calcolare «X or
» e «true
X and
» è alla base di una
caratteristica nota in molti linguaggi di programmazione col nome di
false
short-circuit boolean evaluation
(valutazione logica
cortocircuitata).
I risultati precedenti possono essere generalizzati come segue per
le espressioni con un tipo di operatore binario booleano
(and
| or
) e qualsiasi numero di
operandi:
Se almeno un operando è true
, il
risultato è true
.
Altrimenti, se almeno un operando è
NULL
, il risultato è
NULL
.
Altrimenti (cioè se tutti gli operandi sono
false
) il risultato è
false
.
Se almeno un operando è false
, il
risultato è false
.
Altrimenti, se almeno un operando è
NULL
, il resto è
NULL
.
Altrimenti (cioè se tutti gli operandi sono
true
) il risultato è
true
.
O, più brevemente:
TRUE
sovrasta NULL
nelle disgiunzioni (operazioni OR);
FALSE
sovrasta NULL
nelle congiunzioni (operazioni AND);
In tutti gli altri casi, vince
NULL
.
Se si fatica nel ricordare chi sovrasta che cosa in che operazione, meglio memorizzare la regoletta della seconda lettera: tRue vince con oR — fAlse con And.
I risultati determinati dai cortocircuiti logici booleani di cui sopra possono suggerire le seguenti idee:
0 per x
è uguale a 0 per qualsiasi
x
. Pertanto, anche se x
è
sconosciuto, 0 * x
vale 0. (N.B.: questo solo se
il tipo di dato di x
può contenere solo numeri,
non NaN
o infiniti.)
La stringa vuota è in ordine lessicografico prima di ogni
altra stringa. Pertanto, S >= ''
è vero per
qualsiasi valore di S.
Ogni valore è uguale a sé stesso, sia conosciuto che
incognito. Così, sebbene sia giustificato che A =
B
sia NULL
quando A e B sono entità
diverse di valore NULL
, invece A =
A
dovrebbe sempre riportare true
,
anche quando A è NULL
. Lo stesso vale per
A <= A
e A >= A
.
Analogicamente, A <> A
dovrebbe
sempre essere false
così come A <
A
e A > A
.
Ogni stringa contiene sé stessa,
comincia con sé stessa ed è
come sé stessa. Così, «S
CONTAINING S
», «S STARTING WITH
S
» e «S LIKE S
»
dovrebbero sempre essere, o meglio valere,
true
.
Ebbene, come viene implementato questo in Firebird SQL? È mio
dovere informare che, contrariamente al buon senso e all'analogia con i
risultati dell'algebra booleana mostrati sopra, tutte le seguenti
espressioni valgono NULL
:
0 * NULL
NULL
>= ''
e
'' <=
NULL
A = A
,
A <=
A
e
A
>= A
A <> A
,
A < A
e
A > A
S CONTAINING S
,
S STARTING WITH S
e
S LIKE S
Il fatto è che non vanno confusi gli operatori logici (quali
OR
e AND
) con gli operatori quali
la moltiplicazione ed il confronto che sono operatori aritmetici che
hanno risultati rispettivamente numerici o booleani.
Firebird Documentation Index → Guida sull'uso di NULL nel linguaggio SQL di Firebird → NULL nelle espressioni |