Firebird Documentation IndexGuida sull'uso di NULL nel linguaggio SQL di Firebird → NULL nelle espressioni
Firebird Home Firebird Home Indietro: Come Firebird supporta il NULL nel linguaggio SQLFirebird Documentation IndexRisali: Guida sull'uso di NULL nel linguaggio SQL di FirebirdAvanti: Funzioni interne ed altre direttive

NULL nelle espressioni

Operazioni matematiche e con stringhe
NULL nelle operazioni logiche
Ancora logica (anche se non sembra)

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.

Operazioni matematiche e con stringhe

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 NULL Se A è sconosciuto, allora anche 6 + A è sconosciuto.
5 * A - 7 NULL Se A è sconosciuto, allora lo è anche 5 * A. Sottrargli 7 finisce per dare un altra quantità sconosciuta.
'Casa ' || 'dolce ' || A NULL Se A è sconosciuto, 'Casa dolce ' || A è sconosciuto.
MioCampo = A NULL Se A è sconosciuto, non si può dire se MioCampo ha lo stesso valore...
MioCampo <> A NULL ...ma non si può neanche dire se MioCampo ha un valore differente!
A = B NULL 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.

NULL nelle operazioni logiche

Nota

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) NULL Se A è sconosciuto, è sconosciuto anche il suo inverso (o la sua negazione).
A or (false) NULL «A or false» ha sempre il valore di A - che è sconosciuto.
A or (true) true «A or true» è sempre true, perchè il valore di A non ha importanza.
A or A NULL «A or A» è sempre A, che è sconosciuto, cioè NULL.
A and (false) false «A and false» è sempre falso, perchè il valore di A non conta.
A and (true) NULL «A and true» ha sempre il valore di A - che è sconosciuto.
A and A NULL «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 true» e «X and false» è alla base di una caratteristica nota in molti linguaggi di programmazione col nome di 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:

Disgiunzioni («A or B or C or D or ...»)
  1. Se almeno un operando è true, il risultato è true.

  2. Altrimenti, se almeno un operando è NULL, il risultato è NULL.

  3. Altrimenti (cioè se tutti gli operandi sono false) il risultato è false.

Congiunzioni («A and B and C and D and ...»)
  1. Se almeno un operando è false, il risultato è false.

  2. Altrimenti, se almeno un operando è NULL, il resto è NULL.

  3. 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.

Ancora logica (anche se non sembra)

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.

Indietro: Come Firebird supporta il NULL nel linguaggio SQLFirebird Documentation IndexRisali: Guida sull'uso di NULL nel linguaggio SQL di FirebirdAvanti: Funzioni interne ed altre direttive
Firebird Documentation IndexGuida sull'uso di NULL nel linguaggio SQL di Firebird → NULL nelle espressioni