El NULL de SQL es raro
(jirevwe.github.io)-
En SQL, los valores NULL se manejan de forma particular. Una columna con restricción UNIQUE puede tener varios valores NULL.
- Esto se debe a que cada valor NULL se considera un valor independiente y distinto de cualquier otro NULL.
- SQLite, Postgres y MySQL se comportan igual.
-
Estableciendo la referencia
select '' = ''; -- Returns 1 (true) las cadenas vacías son iguales select 1 = 1; -- Returns 1 (true) los números son iguales select 1 = 0; -- Returns 0 (false) los números son distintos select null = null; -- Returns NULL (null) ¿eh?- Esto se debe a que NULL es un marcador de posición para un "valor desconocido", así que no se considera que dos valores desconocidos sean iguales.
- Si usas el operador
IS, puedes verificar la identidad de NULL. Por ejemplo,null is nulldevuelve TRUE.
-
Sobre la unicidad
- Si una columna con restricción UNIQUE contiene valores NULL, esos NULL se consideran distintos entre sí y no violan la restricción de unicidad.
- Por ejemplo,
('ray@mail.com', NULL)y('ray@mail.com', NULL)se consideran filas distintas.
-
Por qué NULL se maneja así
- SQLite y otras bases de datos compatibles con SQL lo implementan de esta manera para mantener consistencia con otras bases de datos. La documentación del estándar SQL sugiere que NULL debería ser único en todas partes, pero en la práctica la mayoría de los motores SQL no tratan a NULL como único en
SELECT DISTINCToUNION.
- SQLite y otras bases de datos compatibles con SQL lo implementan de esta manera para mantener consistencia con otras bases de datos. La documentación del estándar SQL sugiere que NULL debería ser único en todas partes, pero en la práctica la mayoría de los motores SQL no tratan a NULL como único en
-
Cómo garantizar la unicidad
-
Usar columnas generadas
- Puedes mitigar el problema creando una columna que siempre tenga un valor determinista que no sea NULL. Por ejemplo, puedes usar
COALESCE(deleted_at, '1970-01-01')para reemplazar valores NULL. - Este método puede ocupar espacio al agregar un campo adicional a la tabla.
- Puedes mitigar el problema creando una columna que siempre tenga un valor determinista que no sea NULL. Por ejemplo, puedes usar
-
Usar índices parciales
- Puedes garantizar la unicidad creando un índice parcial sobre
emailsolo cuandodeleted_atsea NULL. - Los índices parciales consumen menos espacio sin ensanchar la tabla, y no generan errores al eliminar repetidamente el mismo par de registros.
- Puedes garantizar la unicidad creando un índice parcial sobre
-
-
Actualización
- Oracle trata las cadenas vacías como NULL.
-
Conclusión
- Cuando usas un ORM no se nota, pero la forma particular en que SQL maneja NULL puede causar confusión. La documentación del estándar SQL no se ofrece públicamente y solo puede obtenerse pagando.
2 comentarios
Todos los
nullson raros.Por eso, el
nullperfectamente normal de SQL termina pareciendo el raro…En el país de los tuertos, el de dos ojos es el anormal…
Comentarios de Hacker News
El
NULLde SQL se basa en la lógica TRUE-FALSE-UNKNOWN de Kleene. Si se leeNULLcomo UNKNOWN, muchas operaciones se entienden de forma más intuitivaNULLes un marcador de posición que representa UNKNOWN, y no se puede decir que dosNULLsean igualesNULLS NOT DISTINCTCuando se introdujo el concepto de
NULLen la década de 1970, se pensó que provocaría mucha confusión en el futuro. Han pasado 45 años y todavía sigue en discusiónUna forma intuitiva de entender
NULL: el valorNULLen una celda específica de una tabla es una manera de indicar “sin valor”. Cuando se quiere un valor único, los casos sin valor no deberían tomarse en cuentaEscepticismo sobre el uso de ORM: los ORM son convenientes, pero han creado una generación que no aprendió cómo funcionan realmente las bases de datos relacionales. El comportamiento de
NULLen SQL coincide con el álgebra relacional básica; el problema es elNULLal estilo de CRecuerda el humor de las comparaciones con
NULLen un diálogo de un episodio de BlackadderParece extraño que en Oracle
NULLsea lo mismo que una cadena vacíaEn un contexto orientado a objetos, "null" es útil para indicar que cierta propiedad no tiene valor. En JavaScript existen
nullyundefined; se puede asumir queundefinedsignifica que no se conoce el valor ynullque no hay valorNULLno es extraño en el sentido de que no haya duplicados. Como losNULLno son iguales entre sí, no pueden considerarse duplicados. Si no te gusta la semántica deNULL, puedes usar un valor centinelaEl
NULLde SQL no es extraño si se considera cómo se quiere que funcione la lógica relacional en registros donde hay valores inexistentes