Documentación Firebird → Base de Datos Firebird → Guía de NULL en Firebird → Trabajando con NULLs |
Esta sección contiene trucos prácticos y ejemplos que pueden ser usados por ti en tu trabajo diario con NULLs.
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 ;-)
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...
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...
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 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.
Documentación Firebird → Base de Datos Firebird → Guía de NULL en Firebird → Trabajando con NULLs |