Firebird Documentation IndexGuía de NULL en Firebird → Trabajando con NULLs
Firebird Home Firebird Home Anterior: Colocando un campo o variable a NULLFirebird Documentation IndexSubir: Guía de NULL en FirebirdSiguiente: Sumario

Trabajando con NULLs

Comprobando NULL – si es necesario
Comprobando que los campos son iguales
Substituyendo NULL por un valor

Esta sección contiene trucos prácticos y ejemplos que pueden ser usados por ti en tu trabajo diario con NULLs.

Comprobando NULL – si es necesario

En muchas ocasiones, no tendrás que tomar especiales medidas para campos o variables que puedan ser NULL. Por ejemplo, si haces esto:

select * from Clientes where Ciudad = 'Valencia'

probablemente no quieras ver los clientes cuya ciudad no está especificada. Igualmente:

if (Edad >= 18) then PuedeVotar = 'Si'

no incluye gente que tenga la edad desconocida, que es también defendible. Pero:

if (Edad >= 18) then PuedeVotar = 'Si';
else PuedeVotar = 'No';

no parece correcto: si no sabes la edad de una persona, no puedes explícitamente denegarle el derecho a votar. Peor es esto:

if (Edad < 18) then PuedeVotar = 'No';
else PuedeVotar = 'Si';

que no tiene el mismo efecto que la anterior. Si algunos de las edades NULL son, en realidad, menores de 18, ¡les estás dando derecho a votar!

La manera correcta es comprobar NULL específicamente:

if (Edad is null) then PuedeVotar = 'No definido';
else
  if (Edad >= 18) then PuedeVotar = 'Si';
  else PuedeVotar = 'No';

Nota

else siempre se refiere al último if en el mismo bloque. Pero es a menudo bueno evitar confusiones poniendo las palabras clave begin...end alrededor de grupos de líneas. No lo he hecho aquí para escribir el menor número de líneas posible. Y entonces he compensado esa economización escribiendo esta nota ;-)

Comprobando que los campos son iguales

A veces quieres saber si dos campos o dos variables son lo mismo y quieres considerarlos lo mismo si ambas son NULL. La manera correcta de comprobarlo es esta:

if (A = B or A is null and B is null) then...

O, si quieres situar la preferencia de operaciones explícitamente:

if ((A = B) or (A is null and B is null)) then...

¡Atención!: Si solo una de A o B es NULL, la comparación resulta NULL, no false. Es correcto en una sentencia if, y aún podemos añadir una cláusula else que se ejecutará si A y B no son iguales (incluyendo cuando una es NULL y la otra no):

if (A = B or A is null and B is null) 
  then ...código a añadir si A es igual a B...
  else ...código a añadir si A y B son diferentes...

Pero no tengas la brillante idea de invertir la expresión y usarla en una comparación de no igualdad (como yo hice una vez):

/* ¡No hagas esto! */
if (not(A = B or A is null and B is null))
  then ...código a añadir si A es distinto a B...

El código anterior funciona correctamente si A y B son ambas NULL o ambas no-NULL. Pero falla al ejecutar la cláusula then si sólo una de ellas es NULL.

Si sólo quieres que se haga algo si A y B son diferentes, usa cualquiera de las expresiones correctas anteriores y escribe una instrucción muerta (que no causará ningún efecto) en la cláusula then, o usa esta expresión:

/* Esta es una expresión correcta de no igualdad: */
if (A <> B
    or A is null and B is not null
    or A is not null and B is null) then...

Comprobando que un campo se ha cambiado

En triggers, es a menudo útil saber si cierto campo ha cambiado (incluyendo que se haya convertido de NULL a no-NULL o viceversa) o sigue siendo igual. Esto es sólo un caso especial de comprobar la (des)igualdad de dos campos. Usa New.Nombrecampo y Old.Nombrecampo para A y B.

if (New.Trabajo = Old.Trabajo 
    or New.Trabajo is null and Old.Trabajo is null)
  then ...El campo Trabajo es igual...
  else ...El campo Trabajo ha cambiado...

Substituyendo NULL por un valor

La función COALESCE

Firebird 1.5 tiene una función que puede convertir NULL a casi cualquier otra cosa. Esto te habilita para hacer conversiones “on-the-fly” y usar el resultado en un tratamiento posterior, sin la necesidad de utilizar la construcción “if (MiExpresion is null) then”. La función se llama COALESCE y la puedes llamar así:

COALESCE(Expr1, Expr2, Expr3, ...)

COALESCE devuelve el primer valor no-NULL de la lista de argumentos. Si todas las expresiones son NULL, devuelve NULL.

Así es como puedes usar COALESCE para construir el nombre completo de una persona desde el nombre, segundo nombre y primer apellido, asumiendo que algunos segundos nombres puedan estar en NULL:

select Nombre
       || coalesce(' ' || Nombre2, '')
       || ' ' || Apellido
from Personas

O para crear un nombre tan informal como sea posible de una tabla que incluya también apodos y asumiendo que tanto el apodo como el primer nombre pueden ser NULL:

select coalesce (Apodo, Nombre, 'Sr./Sra.')
       || ' ' || Apellido
from OtrasPersonas

COALESCE te ayudará sólo en situaciones donde NULL puede ser tratado como otros valores posibles del tipo de dato. Si NULL necesita un manejo especial, como en el ejemplo de “derecho a votar” usado anteriormente, tu única opción es usar una construcción “if (MiExpresion is null) then”.

Firebird 1.0: las funciones *NVL

Firebird 1.0 no tiene COALESCE. Sin embargo, puedes usar cuatro UDF's que proveen una buena parte de su funcionalidad. Estas UDF's residen en la librería fbudf y son:

  • iNVL, para argumentos enteros

  • i64NVL, para argumentos enteros largos

  • dNVL, para argumentos de doble precisión

  • sNVL, para argumentos de cadena

Las funciones *NVL tienen exactamente dos argumentos. Como COALESCE, devuelven el primero argumento si es no-NULL; en otro caso, devuelven el segundo. Recuerda por favor, que la librería fbudf – y por tanto las funciones *NVL – sólo están disponibles para Windows.

Anterior: Colocando un campo o variable a NULLFirebird Documentation IndexSubir: Guía de NULL en FirebirdSiguiente: Sumario
Firebird Documentation IndexGuía de NULL en Firebird → Trabajando con NULLs