Firebird Documentation Index → Guía de NULL en Firebird → NULL en expresiones |
Como muchos de nosotros hemos encontrado, para nuestro disgusto,
NULL
es contagioso: úsalo en una expresión numérica,
texto o fecha/hora y el resultado siempre es NULL
.
Úsalo en una expresión lógica y el resultado depende del tipo de operación
y el resto de valores implicados.
Por cierto, nota que en versiones anteriores a Firebird 2.0 es
normalmente ilegal usar la constante NULL
directamente en operaciones o comparaciones. Cuando veas
NULL
en las expresiones siguientes, léelas como
“un campo, variable u otra expresión que resuelve en
NULL
”.
Las expresiones en esta lista siempre
devuelven NULL
:
1 + 2 + 3 +
NULL
'Hogar ' || 'dulce ' ||
NULL
MiCampo =
NULL
MiCampo <>
NULL
NULL
=
NULL
not (
NULL
)
Si tienes dificultades en entender por qué, recuerda que
NULL
significa “desconocido”. Además
mira en la siguiente tabla donde hay explicaciones por caso. En la
tabla, no hemos escrito NULL
en las expresiones
(como ya hemos dicho, es, a menudo, ilegal); en vez de ello, hemos usado
dos entidades A y B que son ambas NULL
. A y B
pueden ser campos, variables o subexpresiones enteras en su derecho –
como son NULL
, se comportan de la misma manera que
expresiones cerradas.
Tabla 1. Operaciones sobre entidades NULL
A y
B
Si A y B son NULL, entonces: | Es: | Porque: |
---|---|---|
1 + 2 + 3 + A |
|
Si A es desconocido, entonces 6+A también es desconocido. |
'Hogar ' || 'dulce ' || A |
|
Si A es desconocido, entonces 'Hogar dulce ' || A es también desconocido. |
MiCampo = A |
|
Si A es desconocido, no puedes decir que MiCampo tenga el mismo valor… |
MiCampo <> A |
|
...ni puedes decir que MiCampo tenga distinto valor! |
A = B |
|
Con A y B desconocidos, es imposible saber si son iguales. |
not (A) |
|
Si A es desconocido, su inverso también. |
Hemos visto que not(
devuelve NULL
)NULL
. Para los operadores
and
y or
, las cosas son un poco
más complicadas:
NULL
or
false
=
NULL
NULL
or
true
=
true
NULL
or
NULL
=
NULL
NULL
and
false
=
false
NULL
and
true
=
NULL
NULL
and
NULL
=
NULL
El SQL de Firebird no tiene un dato de tipo booleano (lógico); no
hay unas constantes true
o
false
existentes. En la columna de la izquierda de
la siguiente tabla (true)
y
(false)
representan expresiones que devuelven
true
/false
.
Tabla 2. Operaciones lógicas (booleanas) sobre una entidad
NULL
A
Si A es NULL ,
entonces:
|
Es: | Porque: |
---|---|---|
A or (false) |
|
“A or
” siempre tiene el
valor de A, que es desconocido.
|
A or (true) |
|
“A or
” siempre es
true . El valor de A no importa.
|
A or A |
|
“A or A ” siempre equivale
a A, que es NULL .
|
A and (false) |
|
“A and
” es siempre
false . El valor de A no importa.
|
A and (true) |
|
“A and
” siempre tiene el
valor de A, el cuál es desconocido.
|
A and A |
|
“A and A ” siempre
equivale a A, que es NULL .
|
Todos estos resultados están en concordancia con la lógica
booleana. El hecho de que, para calcular “X or
” y “true
X and
”, simplemente no necesites
saber el valor de X, es también la base de una característica que
conocemos en varios lenguajes de programación: evaluación de circuitos
cortos booleanos.
false
Los resultados de circuitos cortos obtenidos arriba, pueden llevarte a las siguientes ideas:
0 veces x
equivale a 0 para cada
x
. Por tanto, igual que el valor de
x
es desconocido, 0 * x
es 0.
(Nota: esto sólo sucede si el tipo de dato de x
sólo contiene números, no NaN
o
infinitos).
La cadena vacía está ordenada lexicográficamente antes de cada
otra cadena. Por tanto S >= ''
es verdad
siempre independientemente del valor de S.
Cada valor equivale a sí mismo, independientemente de si es
desconocido o no. Por tanto, aunque A = B
justificadamente se devuelve NULL
si A y B son
entidades NULL
diferentes, A =
A
siempre debería devolver true
,
igual que A es NULL
.
¿Cómo está esto implementado en el SQL de Firebird? Bueno, siento
informarte que, a pesar de esta convincente lógica – y la analogía con
los resultados explicados arriba – las siguientes expresiones se
resuelven todas con NULL
:
0 * NULL
NULL
>= ''
'' <=
NULL
A = A
(con A como un campo o variable
NULL
)
Demasiado para la coherencia.
En funciones agregadas como COUNT
,
SUM
, AVG
,
MAX
, y MIN
,
NULL
se maneja de manera diferente: para calcular
el resultado, sólo se tienen en consideración los campos con valores
no-NULL
. Esto es, si tienes esta tabla:
ID | Nombre | Sueldo |
---|---|---|
1 | Juan | 37 |
2 | Perico | <NULL >
|
3 | Andrés | 5 |
4 | Roberto | 12 |
5 | Antonio | <NULL >
|
...la sentencia select sum(Sueldo) from
MiTabla
devuelve 54, que es 37+5+12. Si sumáramos todos los
valores, el resultado debería haber sido NULL
. Para
AVG
, los campos no-NULL
son
sumados y la suma dividida entre el número de campos
no-NULL
.
Hay una excepción en esta regla: COUNT(*)
devuelve el número de todas las filas, incluidas todas aquellas con
campos en NULL
. Pero
COUNT
(NombreDeCampo
) se
comporta como las otras funciones agregadas y cuenta aquellas filas que
tienen campos con contenido no-NULL
.
Otra cosa a tener en cuenta: COUNT(*)
y
COUNT
(NombreDeCampo
) jamás
devuelven NULL
: si no hay filas en el grupo, ambas
funciones devuelven 0. Además,
COUNT
(NombreDeCampo
)
devuelve 0 si todos los campos NombreDeCampo
del
grupo son NULL
. Las otras funciones agregadas
devuelven NULL
en tales casos. Ten en cuenta que
SUM
devuelve NULL
si se usa en
un grupo de registros vacío, lo que es contrario a la lógica
común.
Firebird Documentation Index → Guía de NULL en Firebird → NULL en expresiones |