NULLIF
La función NULLIF hace lo contrario de lo que podrías esperar por su nombre: en lugar de manejar valores NULL, los genera. Compara dos expresiones y, si son iguales, devuelve NULL. Si son diferentes, devuelve la primera expresión. Puede parecer un comportamiento extraño a primera vista, pero tiene aplicaciones muy prácticas, especialmente para evitar divisiones por cero y para limpiar valores centinela en los datos.
Sintaxis
NULLIF(expresion1, expresion2)MySQL compara las dos expresiones. Si expresion1 = expresion2 es verdadero, devuelve NULL. Si son diferentes, devuelve expresion1. Es equivalente a escribir CASE WHEN expresion1 = expresion2 THEN NULL ELSE expresion1 END, pero de forma mucho más compacta.
Comportamiento básico
Para entender el funcionamiento, observa estos ejemplos directos:
SELECT
NULLIF(10, 10) AS iguales,
NULLIF(10, 20) AS diferentes,
NULLIF('abc', 'abc') AS texto_igual,
NULLIF('abc', 'xyz') AS texto_diff;| iguales | diferentes | texto_igual | texto_diff |
|---|---|---|---|
| NULL | 10 | NULL | abc |
Cuando los dos valores coinciden, el resultado es NULL. Cuando difieren, se devuelve el primer valor sin modificar. Este comportamiento es la base de todos los usos prácticos de NULLIF.
Un caso habitual es detectar valores que deberían tratarse como ausentes. En muchas bases de datos heredadas, se usaba el valor 0 o una cadena vacía para indicar "sin dato" en lugar de NULL. Con NULLIF puedes convertir esos valores centinela en nulos reales:
SELECT
nombre,
telefono_secundario,
NULLIF(telefono_secundario, '') AS telefono_limpio
FROM clientes
LIMIT 4;| nombre | telefono_secundario | telefono_limpio |
|---|---|---|
| María | NULL | |
| Carlos | 612345678 | 612345678 |
| Ana | NULL | |
| Pedro | 698765432 | 698765432 |
Si telefono_secundario contiene una cadena vacía, NULLIF la convierte en NULL. Si contiene un número real, lo devuelve tal cual. Una vez convertido a NULL, puedes aplicar funciones como IFNULL o COALESCE para asignar un valor por defecto.
Caso práctico: prevenir la división por cero
Este es el uso más conocido y probablemente el más importante de NULLIF. En MySQL, dividir entre cero no produce un error sino que devuelve NULL, pero en algunos contextos puede provocar advertencias o resultados inesperados. Con NULLIF puedes proteger tus divisiones de forma elegante:
SELECT
nombre,
ingresos,
gastos,
ROUND(ingresos / NULLIF(gastos, 0), 2) AS ratio_ing_gas
FROM departamentos;| nombre | ingresos | gastos | ratio_ing_gas |
|---|---|---|---|
| Ventas | 450000.00 | 120000.00 | 3.75 |
| Marketing | 280000.00 | 95000.00 | 2.95 |
| Soporte | 0.00 | 85000.00 | 0.00 |
| Innovación | 50000.00 | 0.00 | NULL |
NULLIF(gastos, 0) devuelve NULL cuando los gastos son cero, lo que hace que la división ingresos / NULL produzca NULL en lugar de un resultado incorrecto o una advertencia. Cuando los gastos tienen un valor real, NULLIF los devuelve sin cambios y la división se ejecuta normalmente.
Este patrón es especialmente útil en reportes de porcentaje donde el denominador puede ser cero:
SELECT
c.nombre AS categoria,
COUNT(p.id) AS total_productos,
SUM(CASE WHEN p.stock = 0 THEN 1 ELSE 0 END) AS agotados,
ROUND(
SUM(CASE WHEN p.stock = 0 THEN 1 ELSE 0 END) * 100.0
/ NULLIF(COUNT(p.id), 0),
1
) AS pct_agotados
FROM categorias c
LEFT JOIN productos p ON c.id = p.categoria_id
GROUP BY c.id, c.nombre
ORDER BY pct_agotados DESC;| categoria | total_productos | agotados | pct_agotados |
|---|---|---|---|
| Smartphones | 4 | 0 | 0.0 |
| Portátiles | 3 | 0 | 0.0 |
| Ropa | 4 | 0 | 0.0 |
| Hogar | 4 | 0 | 0.0 |
| Deportes | 3 | 0 | 0.0 |
| Libros | 0 | 0 | NULL |
Las categorías sin productos (como Libros en este ejemplo) tienen un COUNT de 0. Sin NULLIF, la división entre cero produciría un resultado confuso. Con NULLIF, esas categorías muestran NULL en el porcentaje, lo que indica claramente que el cálculo no es aplicable.
Caso práctico: limpiar valores centinela para funciones de agregación
Algunas aplicaciones almacenan 0 o -1 como valor centinela en lugar de NULL. Esto distorsiona las funciones de agregación como AVG o MIN. NULLIF permite neutralizar esos valores:
SELECT
puesto,
COUNT(*) AS empleados,
ROUND(AVG(salario), 2) AS media_con_ceros,
ROUND(AVG(NULLIF(salario, 0)), 2) AS media_real
FROM empleados
GROUP BY puesto;| puesto | empleados | media_con_ceros | media_real |
|---|---|---|---|
| Director | 1 | 55000.00 | 55000.00 |
| Jefe de equipo | 2 | 45000.00 | 45000.00 |
| Desarrollador | 2 | 35000.00 | 35000.00 |
| Vendedor | 2 | 16000.00 | 32000.00 |
En el puesto de Vendedor, hay un registro con salario 0 (quizá un becario o un error de datos). AVG(salario) incluye ese cero en el cálculo, lo que reduce la media artificialmente. AVG(NULLIF(salario, 0)) convierte los ceros en NULL, y como AVG ignora los nulos, calcula la media solo con los valores reales.
Este mismo patrón funciona con SUM, MIN y cualquier otra función de agregación. Es una técnica esencial cuando trabajas con datos importados de sistemas externos que no usan NULL de forma estándar.
Caso práctico: lógica inversa con IFNULL
NULLIF y IFNULL son funciones complementarias que se combinan con frecuencia. NULLIF genera nulos cuando encuentra un valor específico, e IFNULL los reemplaza por otro. Juntas, permiten sustituir un valor concreto por otro:
SELECT
nombre,
estado,
IFNULL(NULLIF(estado, 'cancelado'), 'Requiere nueva orden') AS accion
FROM pedidos
LIMIT 6;| nombre | estado | accion |
|---|---|---|
| María | entregado | entregado |
| Carlos | entregado | entregado |
| Ana | enviado | enviado |
| Pedro | cancelado | Requiere nueva orden |
| Lucía | pendiente | pendiente |
| Javier | cancelado | Requiere nueva orden |
NULLIF(estado, 'cancelado') convierte los estados 'cancelado' en NULL. Luego IFNULL(..., 'Requiere nueva orden') sustituye esos NULL por el mensaje de acción. El resultado final es que los pedidos cancelados muestran un texto de acción, mientras que los demás estados se mantienen sin cambios.
Manejo de NULL
Cuando alguno de los argumentos de NULLIF ya es NULL, el comportamiento sigue la regla de comparación de MySQL: NULL = NULL no es verdadero (es NULL), por lo que NULLIF(NULL, NULL) devuelve NULL pero no porque los valores sean iguales, sino porque el primer argumento ya es NULL:
SELECT
NULLIF(NULL, NULL) AS ambos_null,
NULLIF(NULL, 10) AS primero_null,
NULLIF(10, NULL) AS segundo_null;| ambos_null | primero_null | segundo_null |
|---|---|---|
| NULL | NULL | 10 |
En la práctica, NULLIF rara vez recibe NULL como primer argumento, ya que su propósito principal es convertir valores específicos en NULL, no procesar nulos existentes. Si necesitas comprobar si un valor ya es NULL, usa IS NULL, IFNULL o COALESCE.
Combinación con otras funciones
NULLIF se combina especialmente bien con CONCAT para evitar cadenas vacías en concatenaciones:
SELECT
nombre,
apellidos,
CONCAT(
nombre,
IFNULL(CONCAT(' ', NULLIF(segundo_nombre, '')), ''),
' ',
apellidos
) AS nombre_completo
FROM clientes
LIMIT 4;| nombre | apellidos | nombre_completo |
|---|---|---|
| María | García López | María García López |
| Carlos | Rodríguez Martín | Carlos Alberto Rodríguez Martín |
| Ana | Martínez Ruiz | Ana Martínez Ruiz |
| Pedro | Fernández Castro | Pedro José Fernández Castro |
NULLIF(segundo_nombre, '') convierte los nombres vacíos en NULL. Luego CONCAT(' ', NULL) devuelve NULL, e IFNULL(..., '') convierte ese NULL en una cadena vacía para que no afecte a la concatenación exterior. El resultado es un nombre completo limpio, con o sin segundo nombre, sin espacios dobles ni huecos.
También es habitual combinar NULLIF con ROUND y operaciones de porcentaje en reportes financieros:
SELECT
nombre,
ventas_actual,
ventas_anterior,
ROUND(
(ventas_actual - ventas_anterior)
/ NULLIF(ventas_anterior, 0) * 100,
1
) AS variacion_pct
FROM departamentos;| nombre | ventas_actual | ventas_anterior | variacion_pct |
|---|---|---|---|
| Ventas | 450000 | 380000 | 18.4 |
| Marketing | 280000 | 310000 | -9.7 |
| Soporte | 95000 | 95000 | 0.0 |
| Innovación | 50000 | 0 | NULL |
El departamento de Innovación no tenía ventas el periodo anterior, así que NULLIF convierte el cero en NULL y el resultado es NULL en lugar de un infinito o un error. Los demás departamentos muestran su variación porcentual correctamente.
Practica con NULLIF
Usa el editor para convertir valores específicos en NULL con NULLIF:
En el siguiente artículo veremos COALESCE para elegir el primer valor no nulo de una lista.
Escrito por Eduardo Lázaro
