ISNULL
La función ISNULL comprueba si una expresión es NULL y devuelve 1 (verdadero) o 0 (falso). A diferencia de IFNULL y COALESCE, que sustituyen valores nulos, ISNULL simplemente los detecta. Su resultado numérico la hace especialmente útil en expresiones aritméticas, condiciones complejas y como parte de cálculos más elaborados.
Es importante no confundir la función ISNULL(expr) con el operador IS NULL. Aunque ambos detectan nulos, se usan en contextos diferentes y tienen comportamientos sutilmente distintos que explicaremos en este artículo.
Sintaxis
ISNULL(expresion)MySQL evalúa la expresión. Si el resultado es NULL, devuelve el entero 1. Si no es NULL, devuelve el entero 0. No importa el tipo de dato de la expresión: funciona con números, cadenas, fechas y cualquier otro tipo.
Comportamiento básico
Para ver ISNULL en acción con diferentes tipos de valores:
SELECT
ISNULL(NULL) AS nulo,
ISNULL(0) AS cero,
ISNULL('') AS vacio,
ISNULL('texto') AS texto,
ISNULL(42) AS numero;| nulo | cero | vacio | texto | numero |
|---|---|---|---|---|
| 1 | 0 | 0 | 0 | 0 |
Solo el valor NULL real produce un 1. El cero, la cadena vacía y cualquier otro valor devuelven 0. Este comportamiento es coherente con el de MySQL: NULL no es igual a cero ni a una cadena vacía, es la ausencia de valor.
Aplicado a una tabla, ISNULL permite identificar rápidamente qué registros tienen datos faltantes:
SELECT
nombre,
apellidos,
telefono_secundario,
ISNULL(telefono_secundario) AS falta_tel_alt
FROM clientes
LIMIT 6;| nombre | apellidos | telefono_secundario | falta_tel_alt |
|---|---|---|---|
| María | García López | NULL | 1 |
| Carlos | Rodríguez Martín | 612345678 | 0 |
| Ana | Martínez Ruiz | NULL | 1 |
| Pedro | Fernández Castro | 698765432 | 0 |
| Lucía | Sánchez Moreno | NULL | 1 |
| Javier | López García | 678901234 | 0 |
La columna falta_tel_alt muestra un indicador binario claro: 1 para los clientes que no proporcionaron un teléfono alternativo y 0 para los que sí. Este tipo de columna calculada es muy útil para exportar datos a herramientas de análisis o para alimentar dashboards.
Caso práctico: calcular completitud de datos
Una aplicación frecuente de ISNULL es medir qué tan completos están los registros de una tabla. Al devolver 0 o 1, puedes sumar estos valores para contar campos vacíos o calcular porcentajes de completitud:
SELECT
nombre,
apellidos,
(4 - ISNULL(email) - ISNULL(telefono) - ISNULL(direccion) - ISNULL(ciudad)) AS campos_completos,
ROUND(
(4 - ISNULL(email) - ISNULL(telefono) - ISNULL(direccion) - ISNULL(ciudad)) / 4 * 100,
0
) AS pct_completitud
FROM clientes
ORDER BY campos_completos ASC
LIMIT 6;| nombre | apellidos | campos_completos | pct_completitud |
|---|---|---|---|
| Sandra | Blanco Calvo | 2 | 50 |
| Fernando | Díaz Navarro | 3 | 75 |
| María | García López | 4 | 100 |
| Carlos | Rodríguez Martín | 4 | 100 |
| Ana | Martínez Ruiz | 4 | 100 |
| Pedro | Fernández Castro | 4 | 100 |
Cada ISNULL(campo) devuelve 1 si el campo es nulo. Al restarlo del total de campos (4), obtenemos cuántos campos están completos. Dividiendo entre 4 y multiplicando por 100, calculamos el porcentaje de completitud. Este enfoque escala fácilmente a cualquier número de campos y es útil para priorizar qué registros necesitan actualización.
Para obtener un resumen agregado de toda la tabla:
SELECT
COUNT(*) AS total_clientes,
SUM(ISNULL(email)) AS sin_email,
SUM(ISNULL(telefono)) AS sin_telefono,
SUM(ISNULL(direccion)) AS sin_direccion,
ROUND(SUM(ISNULL(email)) / COUNT(*) * 100, 1) AS pct_sin_email
FROM clientes;| total_clientes | sin_email | sin_telefono | sin_direccion | pct_sin_email |
|---|---|---|---|---|
| 20 | 2 | 1 | 3 | 10.0 |
SUM(ISNULL(campo)) suma todos los 1 generados por ISNULL, lo que equivale a contar cuántos registros tienen ese campo vacío. Esta consulta ofrece una vista panorámica de la calidad de los datos y ayuda a identificar qué campos necesitan más atención en la recogida de información.
Caso práctico: ISNULL en expresiones condicionales
Como ISNULL devuelve un valor numérico, puedes usarlo directamente en expresiones aritméticas sin necesidad de IF o CASE:
SELECT
nombre,
precio,
coste,
precio - coste * (1 - ISNULL(coste)) AS margen
FROM productos
WHERE categoria_id = 6;| nombre | precio | coste | margen |
|---|---|---|---|
| iPhone 15 Pro | 1299.99 | 850.00 | 449.99 |
| Samsung Galaxy S24 | 899.99 | 580.00 | 319.99 |
| Google Pixel 8 | 699.00 | NULL | 699.00 |
| Xiaomi 14 | 599.99 | 390.00 | 209.99 |
Cuando coste tiene valor, ISNULL(coste) devuelve 0, por lo que 1 - 0 = 1 y el cálculo es precio - coste * 1, es decir, el margen normal. Cuando coste es NULL, ISNULL(coste) devuelve 1, por lo que 1 - 1 = 0 y el cálculo se convierte en precio - NULL * 0. Pero atención: NULL * 0 sigue siendo NULL, así que precio - NULL da NULL. En este caso particular, es mejor usar IFNULL(coste, 0).
El uso aritmético directo de ISNULL funciona mejor para ponderar o contar. Por ejemplo, para crear un sistema de puntuación donde los campos completos otorgan puntos:
SELECT
nombre,
(1 - ISNULL(email)) * 25 +
(1 - ISNULL(telefono)) * 25 +
(1 - ISNULL(direccion)) * 25 +
(1 - ISNULL(ciudad)) * 25 AS puntuacion_perfil
FROM clientes
ORDER BY puntuacion_perfil ASC
LIMIT 5;| nombre | puntuacion_perfil |
|---|---|
| Sandra | 50 |
| Fernando | 75 |
| María | 100 |
| Carlos | 100 |
| Ana | 100 |
Cada campo completo aporta 25 puntos. (1 - ISNULL(campo)) vale 1 cuando el campo tiene dato y 0 cuando es NULL, así que el multiplicador se activa solo para los campos presentes. Puedes asignar pesos diferentes a cada campo si algunos son más importantes que otros.
Caso práctico: diferencia entre ISNULL y IS NULL
La función ISNULL(expr) y el operador IS NULL detectan nulos, pero se usan en contextos diferentes:
-- ISNULL como función: devuelve 0 o 1, útil en SELECT y expresiones
SELECT
nombre,
ISNULL(telefono_secundario) AS indicador
FROM clientes
WHERE ISNULL(telefono_secundario) = 1
LIMIT 3;| nombre | indicador |
|---|---|
| María | 1 |
| Ana | 1 |
| Lucía | 1 |
-- IS NULL como operador: devuelve TRUE/FALSE, natural en WHERE
SELECT
nombre,
telefono_secundario
FROM clientes
WHERE telefono_secundario IS NULL
LIMIT 3;| nombre | telefono_secundario |
|---|---|
| María | NULL |
| Ana | NULL |
| Lucía | NULL |
Ambas consultas filtran los mismos registros, pero la forma con IS NULL en el WHERE es más legible y es la opción recomendada para filtrar filas. ISNULL brilla en el SELECT para crear indicadores numéricos y en expresiones aritméticas donde necesitas un 0 o 1.
Hay una diferencia técnica adicional: el operador IS NULL puede aprovechar índices de la tabla para filtrar eficientemente, mientras que ISNULL(columna) = 1 en un WHERE puede impedir el uso de índices porque envuelve la columna en una función. Por rendimiento, siempre prefiere IS NULL en las cláusulas WHERE.
Manejo de NULL
Dado que el propósito de ISNULL es precisamente detectar NULL, su comportamiento con nulos es totalmente predecible. Sin embargo, hay un caso sutil con expresiones que pueden producir NULL indirectamente:
SELECT
ISNULL(1 / 0) AS division_cero,
ISNULL(NULL + 5) AS aritmetica_null,
ISNULL(CONCAT(NULL, 'hola')) AS concat_null;| division_cero | aritmetica_null | concat_null |
|---|---|---|
| 1 | 1 | 1 |
La división entre cero en MySQL produce NULL (no un error). La suma con NULL produce NULL. La concatenación con NULL produce NULL. En los tres casos, ISNULL detecta correctamente el resultado nulo. Esto es útil para verificar si una expresión compleja produjo un resultado válido antes de usarlo en otro cálculo.
Combinación con otras funciones
ISNULL se combina bien con SUM y GROUP BY para generar reportes de calidad de datos por categoría:
SELECT
cat.nombre AS categoria,
COUNT(*) AS productos,
SUM(ISNULL(p.coste)) AS sin_coste,
SUM(ISNULL(p.peso)) AS sin_peso,
SUM(ISNULL(p.descripcion)) AS sin_descripcion,
ROUND(
(1 - (SUM(ISNULL(p.coste)) + SUM(ISNULL(p.peso)) + SUM(ISNULL(p.descripcion)))
/ (COUNT(*) * 3.0)) * 100,
1
) AS pct_completitud
FROM productos p
JOIN categorias cat ON p.categoria_id = cat.id
GROUP BY cat.id, cat.nombre
ORDER BY pct_completitud ASC;| categoria | productos | sin_coste | sin_peso | sin_descripcion | pct_completitud |
|---|---|---|---|---|---|
| Accesorios electrónicos | 3 | 1 | 2 | 0 | 66.7 |
| Deportes | 3 | 0 | 1 | 1 | 77.8 |
| Smartphones | 4 | 1 | 0 | 0 | 91.7 |
| Portátiles | 3 | 0 | 0 | 0 | 100.0 |
| Ropa | 4 | 0 | 0 | 0 | 100.0 |
| Hogar | 4 | 0 | 0 | 0 | 100.0 |
Este reporte muestra, para cada categoría, cuántos productos tienen datos faltantes en cada campo y calcula un porcentaje global de completitud. SUM(ISNULL(...)) cuenta los nulos en cada columna, y la fórmula final divide el total de nulos entre el máximo posible (productos por campos) para obtener el porcentaje. Este tipo de análisis es fundamental para equipos de datos que necesitan priorizar la limpieza de registros.
También puedes usar ISNULL junto con IF para crear etiquetas más descriptivas:
SELECT
nombre,
IF(ISNULL(email) + ISNULL(telefono) = 0,
'Contacto completo',
CONCAT('Faltan ', ISNULL(email) + ISNULL(telefono), ' dato(s)')
) AS estado_contacto
FROM clientes
LIMIT 5;| nombre | estado_contacto |
|---|---|
| María | Contacto completo |
| Carlos | Contacto completo |
| Ana | Contacto completo |
| Sandra | Faltan 1 dato(s) |
| Fernando | Faltan 1 dato(s) |
La suma ISNULL(email) + ISNULL(telefono) cuenta cuántos campos de contacto faltan. Si la suma es 0, todos los campos están completos. Si es mayor, CONCAT genera un mensaje indicando cuántos faltan. Este patrón aprovecha la naturaleza numérica de ISNULL para construir lógica condicional compacta.
En la siguiente sección veremos las expresiones regulares en MySQL para búsquedas avanzadas con patrones.
Escrito por Eduardo Lázaro
