Valores NULL de SQL explicados: IS NULL, COALESCE, NULLIF y las trampas que se deben evitar
NULL causa algunos de los errores más silenciosos en SQL, con consultas que se ejecutan sin errores pero pierden filas o distorsionan los promedios. Aprenda cómo se comporta realmente NULL, con ejemplos probados, y cómo manejarlo de forma segura.
- NULL significa un valor faltante o desconocido. No es cero y no es una cadena vacía.
- Pruébelo con
IS NULL, porque= NULLnunca coincide con nada. - La mayoría de los cálculos con NULL dan NULL y
WHEREmantiene solo las filas que son definitivamente verdaderas. - Los agregados omiten los NULL, lo que puede cambiar silenciosamente un promedio.
Una consulta se ejecuta sin errores y devuelve un número que parece razonable, pero faltan filas y el promedio es incorrecto. Los valores SQL NULL suelen ser la causa. NULL no se comporta como ningún valor normal y eso sorprende tanto a principiantes como a desarrolladores experimentados.
Esta guía muestra exactamente cómo se comporta NULL. Ejecutamos todas las consultas en SQLite 3.50 y los resultados mostrados provienen de esa ejecución. La mayor parte de este comportamiento es SQL estándar, y observamos dónde difieren las bases de datos, como el orden de clasificación NULL y el tratamiento de cadenas vacías por parte de Oracle.
¿Qué es NULO?
NULL es un marcador que significa que falta un valor o se desconoce. No es un valor en el sentido habitual, por lo que son cosas diferentes:
| Valor | Significado | Ejemplo de una columna telefónica |
|---|---|---|
NULO |
Desconocido o no proporcionado | No sabemos el numero |
'' |
Un valor de texto vacío conocido | Enviado en blanco |
0 |
el numero cero | No es relevante para el texto, pero es real para las cantidades. |
La diferencia es especialmente importante en el caso de las cantidades. Una bonificación de 0 significa que la persona no recibió nada. Una bonificación NULL significa que nadie lo sabe todavía.
La tabla de muestra
CREATE TABLE employees (
id INT, name TEXT, phone TEXT, bonus INT, manager_id INT
);
INSERT INTO employees VALUES
(1,'Meera','555-0101',500,NULL),
(2,'Arjun',NULL,300,1),
(3,'Sara','',NULL,1),
(4,'Ravi',NULL,NULL,2);
Observe que Sara tiene una cadena vacía para el teléfono, mientras que Arjun y Ravi tienen NULL. Los dos reciben un trato muy diferente.
Prueba de NULL
Este es el error que casi todo el mundo comete al principio:
SELECT name FROM employees WHERE phone = NULL;
-- (no rows)
SELECT name FROM employees WHERE phone IS NULL;
-- Arjun
-- Ravi
SELECT name FROM employees WHERE phone IS NOT NULL;
-- Meera
-- Sara
La primera consulta es SQL válida y no da ningún error. Simplemente no devuelve nada, porque comparar algo con NULL nunca es cierto. Sara aparece debajo de IS NOT NULL, ya que una cadena vacía es un valor real. Sin embargo, en Oracle una cadena vacía se trata como NULL, lo cual es una excepción notable.
Lógica de tres valores
En la mayoría de los lenguajes de programación, una condición es verdadera o falsa. SQL agrega un tercer resultado: desconocido. Si no conoce un valor, no puede decir si es igual a 5. Y no se sabe que dos valores desconocidos sean iguales, razón por la cual NULL = NULL no es cierto. En nuestra prueba, todos estos arrojaron NULL:
SELECT NULL = NULL, NULL <> 1, 1 + NULL, 'a' || NULL;
-- NULL | NULL | NULL | NULL
La combinación de condiciones sigue reglas cuidadosas. Estos son los resultados de nuestra ejecución, donde 1 es verdadero y 0 es falso:
| expresión | Resultado | ¿Por qué? |
|---|---|---|
VERDADERO Y NULO |
NULO | Depende de la parte desconocida |
FALSO Y NULO |
Falso | Falso sea lo que sea lo desconocido |
VERDADERO O NULO |
Verdadero | Cierto sea lo que sea lo desconocido |
FALSO O NULO |
NULO | Depende de la parte desconocida |
NO NULO |
NULO | Lo contrario de desconocido es desconocido |
Filas que desaparecen de DONDE
WHERE mantiene una fila solo si su condición es verdadera. Las filas en las que se desconoce el resultado se eliminan, junto con las que son falsas. Esto lleva a resultados sorprendentes:
SELECT name FROM employees WHERE phone <> '555-0101';
-- Sara
Es de esperar que aparezcan Arjun y Ravi, ya que su teléfono ciertamente no es ese número. Pero se desconoce su teléfono, por lo que se desconoce el resultado y desaparecen. Para incluirlos, dígalo explícitamente: WHERE phone <> '555-0101' OR phone IS NULL. La negación tampoco ayuda:
SELECT name FROM employees WHERE NOT (bonus > 400);
-- Arjun
Sara y Ravi no tienen bonificación, por lo que no aparecen ni en bonus > 400 ni en su opuesto. Es fundamental recordar esto: una condición y su negación no siempre cubren todas las filas.
COALESCER: proporcionar un respaldo
COALESCE devuelve el primer valor no NULL de su lista y funciona en todas las bases de datos principales:
SELECT COALESCE(NULL, NULL, 'third', 'fourth');
-- third
SELECT name, COALESCE(phone, 'no phone') FROM employees;
-- Meera | 555-0101
-- Arjun | no phone
-- Sara |
-- Ravi | no phone
Sara todavía aparece en blanco porque una cadena vacía no es NULL. Existen funciones similares, como IFNULL en MySQL y SQLite, ISNULL en SQL Server y NVL en Oracle. COALESCE es la opción portátil. Nuestro punto anterior sobre los cálculos también se aplica aquí. bonus + 100 da NULL para cualquier persona sin bonificación, así que escriba COALESCE(bonus, 0) + 100 si tratar una bonificación faltante como cero es correcto para su negocio.
NULLIF: convierte un valor en NULL
NULLIF(a, b) devuelve NULL si los dos valores son iguales y, en caso contrario, devuelve a. Dos usos son especialmente útiles. Puede limpiar los valores de los marcadores de posición:
SELECT name, NULLIF(phone, '') FROM employees WHERE id = 3;
-- Sara | NULL
SELECT name FROM employees
WHERE COALESCE(NULLIF(phone, ''), '') = '';
-- Arjun
-- Sara
-- Ravi
Esa segunda consulta es una forma práctica de encontrar valores que “faltan o están en blanco”. También puede proteger contra la división por cero, lo que genera un error en muchas bases de datos:
SELECT total / NULLIF(quantity, 0) FROM sales;
Cuando quantity es 0, esto da NULL en lugar de fallar. En nuestra prueba, SELECT 100 / NULLIF(0, 0) devolvió NULL.
Los agregados omiten NULL
Aquí es donde NULL causa más daño a los informes:
SELECT COUNT(*), COUNT(bonus), SUM(bonus), AVG(bonus),
AVG(COALESCE(bonus, 0))
FROM employees;
-- 4 | 2 | 800 | 400.0 | 200.0
| expresión | Resultado | lo que significa |
|---|---|---|
COUNT(*) |
4 | Todas las filas |
COUNT(bonus) |
2 | Sólo filas con bonificación |
SUM(bonus) |
800 | Los NULL se ignoran |
AVG(bonus) |
400 | 800 dividido por 2, no por 4 |
PROMEDIO(FUSIONAR(bonificación, 0)) |
200 | 800 dividido por 4 |
Entonces, ¿cuál es el bono promedio, 400 o 200? Depende de lo que significa NULL en sus datos. Si NULL significa “no se pagó ningún bono”, entonces 200 es correcto. Si significa “aún no decidido”, entonces 400 puede tener razón. La base de datos no puede tomar esta decisión por usted, por lo que la pregunta debe dirigirse a alguien que conozca el negocio.
Una trampa relacionada: SUM sin valores es NULL en lugar de 0. Cuando sumamos solo las filas sin bonificación, obtuvimos NULL, mientras que COUNT devolvió 0. El código de la aplicación que espera un número puede fallar en esto, así que envuélvalo: COALESCE(SUM(bonus), 0).
Consejo: Cuando el total de un informe parezca incorrecto, compare COUNT(*) con COUNT(column). Cualquier espacio entre ellos le indica de inmediato cuántos NULL tiene esa columna.
GRUPO POR, clasificación y DISTINTO
Aunque los NULL “no son iguales” en las comparaciones, estas operaciones los tratan como un grupo:
SELECT bonus, COUNT(*) FROM employees GROUP BY bonus ORDER BY bonus;
-- NULL | 2
-- 300 | 1
-- 500 | 1
SELECT DISTINCT bonus FROM employees;
-- 500, 300, NULL
Consulte SQL GROUP BY y HAVING para obtener más información sobre la agrupación. El orden de clasificación es donde realmente difieren las bases de datos. SQLite y MySQL tratan a NULL como el valor más pequeño, mientras que PostgreSQL y Oracle lo tratan como el más grande. Entonces el mismo ORDER BY bonus DESC puede poner los NULL al final en uno y al principio en otro. PostgreSQL, Oracle y SQLite moderno le permiten indicar esto directamente, usando NULLS FIRST o NULLS LAST.
Se une
Una condición de unión que utiliza = nunca coincide con NULL, por lo que las filas con una clave NULL salen de una unión interna:
SELECT e.name FROM employees e
JOIN employees m ON m.id = e.manager_id;
-- Arjun, Sara, Ravi (Meera is gone)
SELECT e.name, m.name FROM employees e
LEFT JOIN employees m ON m.id = e.manager_id;
-- Meera | NULL
-- Arjun | Meera
-- Sara | Meera
-- Ravi | Arjun
Meera no tiene administrador, por lo que una combinación interna elimina esa fila silenciosamente. Un LEFT JOIN lo mantiene y también crea sus propios NULL para el lado que falta. Lea más en Explicación de uniones SQL.
La trampa NO ENTRAR
Un solo NULL en una lista NOT IN borra todos los resultados:
SELECT name FROM employees WHERE manager_id NOT IN (1);
-- Ravi
SELECT name FROM employees WHERE manager_id NOT IN (1, NULL);
-- (no rows)
La segunda forma significa manager_id <> 1 AND manager_id <> NULL, y esa última parte nunca puede ser cierta. Esto es particularmente peligroso con las subconsultas, donde un NULL puede pasar desapercibido. Utilice NOT EXISTS en su lugar, como se explica en nuestro tutorial de subconsultas SQL. Meera también falta en el primer resultado, ya que el manager_id de esa fila es NULL.
Diseñando con NULL
- Utilice
NOT NULLde forma predeterminada. Permita NULL solo cuando realmente pueda faltar un valor. - Agregue valores predeterminados sensatos. Por ejemplo,
quantity INT NOT NULL DEFAULT 0. - No utilice valores mágicos. Una fecha de 1900-01-01 o una edad de -1 en lugar de “desconocido” corromperá sus cálculos.
- Conozca el comportamiento ÚNICO. La mayoría de las bases de datos permiten varios NULL en una columna
UNIQUEy nuestra prueba insertó dos sin error. SQL Server es una excepción, ya que normalmente lo permite. - Recuerde que una clave principal no puede ser NULL. Consulte clave principal versus clave externa.
- Prueba con NULL. Los datos de prueba sin NULL ocultan estos errores. Inclúyalos a propósito, como lo haría con otros casos extremos.
Conclusión
Trate a NULL como “desconocido” y la mayor parte de su comportamiento comenzará a tener sentido: desconocido más uno es desconocido, y desconocido es igual a desconocido no se sabe que sea verdadero. Audite uno de sus propios informes esta semana. Verifique las columnas que aceptan valores NULL usando COUNT(*) contra COUNT(column), busque cualquier NOT IN y decida qué debería significar NULL en cada promedio.
Preguntas frecuentes
¿Qué es NULL en SQL?
NULL es un marcador de un valor faltante o desconocido. Es diferente de cero y de una cadena vacía y necesita un manejo especial en las comparaciones.
¿Por qué = NULL no funciona?
Comparar cualquier cosa con NULL da como resultado desconocido en lugar de verdadero, por lo que WHERE descarta la fila. Utilice IS NULL o IS NOT NULL para comprobarlo.
¿Cuál es la diferencia entre COALESCE e ISNULL?
COALESCE es SQL estándar y acepta muchos argumentos. ISNULL es específico de SQL Server y requiere dos. Para código portátil, prefiera COALESCE.
¿COUNT incluye valores NULL?
COUNT(*) cuenta todas las filas, incluidas aquellas con NULL. COUNT(columna) cuenta solo las filas donde esa columna no es NULL, lo que puede dar un número menor.
¿NULL es lo mismo que una cadena vacía?
No, en la mayoría de las bases de datos. Una cadena vacía es un valor conocido sin caracteres y NULL significa desconocido. Oracle es una excepción notable, ya que trata las cadenas vacías como NULL.
sigue aprendiendo
¿Necesitas ayuda con pruebas, WordPress o SEO?
Ayudamos a los equipos a enviar mejor software y hacer crecer sus sitios. Cuéntenos en qué está trabajando y le sugeriremos un siguiente paso claro.
Más guías sobre testing, IA y desarrollo moderno
¿Te gustó este artículo? Elige un tema y salta directo a nuestros tutoriales más recientes.
Explicación de las alucinaciones de la IA: por qué los modelos de lenguaje inventan cosas y cómo reducirlas
Se explicaron las alucinaciones de la IA: qué son, por qué los modelos de lenguaje las producen, tipos comunes, cómo reducirlas con conexión a tierr…
Leer artículo →DevOpsExplicación de las variables de entorno: archivos .env, secretos y configuración bien hechos
Variables de entorno explicadas con ejemplos de Python que ejecutamos: leerlas y configurarlas, por qué cada valor es una cadena, archivos .env, her…
Leer artículo →Desarrollo de softwareExplicación de la limitación de velocidad de API: algoritmos, encabezados y manejo de errores 429
La limitación de la tasa de API se explica con una simulación que ejecutamos: depósito de tokens, ventana fija, ventana deslizante, 429 respuestas, …
Leer artículo →Automatización de pruebasBurlarse en Python: unittest.mock, patch y los errores que hacen que las pruebas mientan
Burlarse en Python con unittest.mock, probado: Mock y return_value, side_effect, parches donde se usa un nombre, especificación y autospec, fechas d…
Leer artículo →Pruebas de softwareExplicación de la cobertura del código: cobertura de línea versus sucursal y lo que realmente significa 100%
Cobertura del código explicada con una ejecución real de cobertura.py: cobertura de línea, rama y condición, lectura de un informe, por qué una cobe…
Leer artículo →Bases de datos y SQLDELETE vs TRUNCATE vs DROP en SQL: diferencias, reversión y cuándo usar cada uno
DELETE vs TRUNCATE vs DROP explicado con SQL probado: qué elimina cada uno, reversión, activadores, restablecimiento de identidad, velocidad y en qu…
Leer artículo →Bases de datos y SQLVistas SQL explicadas: cree, use y evite los errores, con ejemplos
Vistas SQL explicadas con consultas que ejecutamos: creación de una vista, resultados en vivo, ocultación de columnas, rendimiento, vistas actualiza…
Leer artículo →Desarrollo de softwareInterfaz TypeScript versus tipo: diferencias reales, probadas con el compilador
Interfaz TypeScript versus tipo, verificado con el compilador real: qué pueden hacer ambos, qué puede hacer solo uno, fusión de declaraciones, exten…
Leer artículo →Desarrollo de softwarePython *args y **kwargs explicados: funciones flexibles con ejemplos claros
Python *args y **kwargs explicados con el código que ejecutamos: empaquetado y desempaquetado, orden de parámetros, argumentos solo de palabras clav…
Leer artículo →Desarrollo de softwareFunciones Lambda de Python: sintaxis, usos reales y cuándo no utilizarlas
Funciones lambda de Python explicadas con el código que ejecutamos: sintaxis, clasificación con clave, mapa y filtro, cierres, trampa de enlace tard…
Leer artículo →Inteligencia artificial¿Qué son los agentes de IA? Cómo funcionan, con un bucle de agente simple que puedes ejecutar
¿Qué son los agentes de IA? Una guía sencilla sobre el bucle del agente, las herramientas, la memoria y las barreras de seguridad, con un pequeño bu…
Leer artículo →DevOpsMonitoreo versus observabilidad: la verdadera diferencia, con registros, métricas y seguimientos
Explicación del monitoreo versus observabilidad: fallas conocidas y desconocidas, registros, métricas y seguimientos, un recorrido por incidentes de…
Leer artículo →DevOpsDocker Volumes versus Bind Mounts: persistir los datos del contenedor de la manera correcta
Se explican los volúmenes de Docker frente a los montajes de enlace: por qué desaparecen los datos del contenedor, volúmenes con nombre, montajes de…
Leer artículo →Automatización de pruebasTDD vs BDD: diferencias clave, una función creada en ambos sentidos y cuándo usar cada una
TDD vs BDD explicado con una característica de descuento construida en ambos sentidos: refactor rojo-verde con el código que ejecutamos, escenarios …
Leer artículo →Pruebas de softwarePruebas de Aceptación de Usuario (UAT): Proceso, Lista de Verificación y Ejemplos Reales
Explicación de las pruebas de aceptación del usuario: quién las ejecuta, en qué se diferencia del control de calidad, un proceso de siete pasos, una…
Leer artículo →Bases de datos y SQLValores NULL de SQL explicados: IS NULL, COALESCE, NULLIF y las trampas que se deben evitar
Los valores NULL de SQL se explican con las consultas que ejecutamos: lógica de tres valores, IS NULL, COALESCE, NULLIF, cómo los agregados, las uni…
Leer artículo →Bases de datos y SQLDeclaración SQL CASE WHEN: sintaxis, ejemplos reales y errores comunes
CASO SQL CUANDO se explicó con las consultas que ejecutamos: formularios simples y buscados, orden de condiciones, pivotes con SUMA, trucos COUNT, c…
Leer artículo →Desarrollo de software¿Qué es JWT? Tokens web JSON explicados con un ejemplo práctico
¿Qué es JWT? JSON Web Tokens explicó: las tres partes, un token creado y manipulado en el código que ejecutamos, JWT vs sesiones, almacenamiento, to…
Leer artículo →Desarrollo de softwareExplicación del bucle de eventos de JavaScript: pila de llamadas, microtareas y temporizadores con ejemplos
El bucle de eventos de JavaScript explicado con el código que ejecutamos: pila de llamadas, colas de tareas y microtareas, por qué setTimeout 0 no e…
Leer artículo →Desarrollo de softwareExplicación de los generadores y el rendimiento de Python: ahorre memoria con ejemplos reales
Los generadores de Python y el rendimiento se explican con el código que ejecutamos: cómo se pausan y reanudan, midieron el ahorro de memoria, canal…
Leer artículo →Inteligencia artificial¿Qué son las incrustaciones? Los vectores y la similitud del coseno se explican de forma sencilla
¿Qué son las incrustaciones? Una guía en lenguaje sencillo sobre vectores, similitud de cosenos y búsqueda semántica, con un pequeño ejemplo que eje…
Leer artículo →DevOpsImplementación azul-verde versus implementación canaria: diferencias, compensaciones y cómo elegir
Explicación de la implementación azul-verde versus canaria: cómo funciona cada uno, costo, riesgo y reversión, agrupación estable de usuarios que pr…
Leer artículo →Automatización de pruebasPruebas inestables: qué las causa y cómo solucionarlas para siempre
Pruebas inestables explicadas con demostraciones que realizamos: las causas principales, cómo confirmar y diagnosticar una, correcciones adecuadas p…
Leer artículo →Pruebas de softwarePruebas de carga frente a pruebas de estrés: diferencias, métricas y ejemplos de k6
Explicación de las pruebas de carga frente a las pruebas de estrés: qué prueba cada una, pruebas de picos y de absorción, las métricas que importan,…
Leer artículo →Pruebas de softwareCaso de prueba frente a escenario de prueba: diferencias clave, ejemplos y cuándo utilizar cada uno
Caso de prueba versus escenario de prueba explicado: definiciones claras, una tabla en paralelo, una función de restablecimiento de contraseña tomad…
Leer artículo →Bases de datos y SQLOptimización de consultas SQL: lea planes de ejecución y corrija consultas lentas, con tiempos
Optimización de consultas SQL probada en un millón de filas: lea planes de ejecución, agregue los índices correctos, corrija filtros no sargables, u…
Leer artículo →Bases de datos y SQLSQL UNION vs UNION ALL: diferencias, ejemplos y rendimiento probado
SQL UNION vs UNION ALL explicado con consultas que ejecutamos: duplicados, las reglas que siguen ambos, un error de datos real, rendimiento medido, …
Leer artículo →Desarrollo de softwareTutorial de JavaScript Fetch API: GET, POST, manejo de errores y tiempos de espera
Un tutorial de JavaScript Fetch API probado en un servidor local: GET y POST, por qué 404 no arroja, un asistente reutilizable, cadenas de consulta,…
Leer artículo →Desarrollo de softwareManejo de archivos Python: lectura, escritura, CSV, JSON y pathlib con ejemplos
El manejo de archivos Python se explica con el código que ejecutamos: modos abiertos, lectura de archivos grandes, CSV, JSON, pathlib, archivos bina…
Leer artículo →Desarrollo de softwareClases y objetos de Python: tutorial de programación orientada a objetos con ejemplos reales
Clases y objetos de Python explicados con el código que ejecutamos: __init__, métodos, atributos de clase versus instancia, herencia, propiedades, m…
Leer artículo →Inteligencia artificial¿Qué es un modelo de lenguaje grande? Cómo funcionan los LLM, explicados sin exageraciones
¿Qué es un modelo de lenguaje grande? Los LLM explicados en lenguaje sencillo: tokens, incrustaciones, atención, entrenamiento, ventanas de temperat…
Leer artículo →DevOpsComandos de Linux para principiantes: la guía esencial de terminal con ejemplos
Comandos de Linux para principiantes, agrupados por tarea: navegación, archivos, visualización de registros, grep, canalizaciones, permisos, proceso…
Leer artículo →Automatización de pruebasSelenium vs Playwright: diferencias clave, comparación de códigos y cuál elegir
Comparación de Selenium vs Playwright: arquitectura, espera, soporte de navegador e idioma, depuración, la misma prueba en ambas herramientas, conse…
Leer artículo →Pruebas de softwarePartición de equivalencia: técnica de diseño de pruebas explicada con ejemplos resueltos
Explicación de la partición de equivalencia: cómo encontrar particiones válidas e inválidas, ejemplos prácticos para edades, contraseñas y cupones, …
Leer artículo →Pruebas de softwareSeveridad vs Prioridad en Pruebas de Software: Diferencias, Matriz y Ejemplos Reales
Explicación de gravedad versus prioridad en las pruebas de software: definiciones claras, una matriz de cuatro vías con ejemplos, escalas de niveles…
Leer artículo →Bases de datos y SQLTutorial de subconsultas SQL: tipos, subconsultas correlacionadas y EXISTENCIAS con ejemplos
Un tutorial de subconsultas SQL con consultas que ejecutamos: subconsultas escalares, IN, FROM y SELECT, subconsultas correlacionadas, EXISTS, la tr…
Leer artículo →Bases de datos y SQLTransacciones SQL y ACID explicados: COMMIT, ROLLBACK y niveles de aislamiento
Transacciones SQL y ACID explicadas con una transferencia bancaria que ejecutamos: COMMIT, ROLLBACK, puntos de guardado, bloqueos, niveles de aislam…
Leer artículo →Desarrollo de softwareGit merge vs rebase: diferencias, ejemplos y cuándo usar cada uno
Git merge vs rebase explicado con salida real del log, una tabla comparativa, la regla de oro del rebase y un flujo de trabajo seguro para equipos.
Leer artículo →Desarrollo de softwareList comprehension en Python: sintaxis, ejemplos y cuándo evitarla
List comprehension en Python explicada: sintaxis, filtros, if-else, bucles anidados, tiempos medidos y cuándo es mejor un bucle for normal.
Leer artículo →