miércoles, 6 de mayo de 2015

NULO es NULO

Hablemos del NULL, del "nulo", pero en MySQL. Cosas que si alguna vez las he sabido, se me habían olvidado.

Parece ser que la necesidad del nulo surgió del propio día a día que quería representar y gestionar el modelo relacional. Es muy habitual encontrarse con formularios donde falta algún dato, bien por ignorancia o por poca relevancia. Vamos, que casi da igual que lo pongas que no, no es importante. En otros casos incluso podría ser inaplicable, pongamos "color de pelo" si resulta que antes has elegido "piedra". Para eso es el nulo.

NULL es un, llamémosle, valor de difícil implementación. De hecho, no es un valor, es un estado, y un nulo no es igual a otro nulo. En clase solemos decir "no sabemos si tiene valor y, si tiene, no sabemos cuál es". En SQL se nota porque no se puede preguntar x = NULL. El nulo no se puede utilizar en comparaciones con "igual", "menor que" y todos los demás. Tenemos que utilizar un operador específico, x IS NULL o x IS NOT NULL.

Para liarla más autores hay que dicen que, precisamente el nulo, es el mayor error de Codd al definir el modelo relacional (1). Y Codd dice que sin los nulos no hay modelo relacional. Lo cierto es que su aplicación más clara es en las claves ajenas donde la existencia de un nulo se interpreta como ausencia de relación. Por eso la mayoría de los sistemas de gestión de bases de datos lo tratan como "ausencia de valor" o "sin valor". Esto hace las cosas más fáciles ya que el nulo solo puede trabajarse con el mencionado operador IS.

Pues bien, MySQL trata el nulo como lo que es en la teoría.

Supongamos un conjunto, típicamente un resultado de una consulta que contiene uno o varios nulos:

C1 = select a from t1

a
NULL
1
2
3



Otra consulta nos da los siguientes resultados:

C2 = select b from t2

b
 1 
1
4

Y ahora, la prueba. Queremos saber qué valores de la consulta C2 no están en el resultado de la consulta C1.

C3 = select b from t2 where b NOT IN (select a from t1)

 b 
(vacío, sin filas)

Uno espera que el resultado sea "4". Pues no, resultado vacío de filas. Todos los valores, "1" y "4", están en la tabla t1. ¿Cómo  puede ser esto?

Hay que irse a al manual y comprobar las tablas del nulo. Resumiendo, si utilizamos el x IS NULL podremos obtener un valor verdadero o falso —1 o 0— pero si comparamos como toda la vida se ha hecho

x = NULL, x <> NULL, x < NULL 

el resultado es  es siempre NULL, falso, 0. En MySQL dicen que NULL y 0 significan falso. Cualquier otra cosa, cierto. Incluso NULL = NULL da falso.

Simplifiquemos el ejemplo: select 1 not in (2, 3) es lo mismo que

select (1<>2) and (1<>3) = 1 and 1 = cierto AND cierto = CIERTO

Pero select 1 not in (null, 3) es lo mismo que

select (1<>null) and (1<>3) = 0 AND 1 = falso AND cierto = FALSO.


Fácil. Nulo es nulo en MySQL. O sea, que como hay un nulo en el resultado de la subconsulta (select a from t1), ese nulo podría ser cualquier cosa, concretamente podría ser un "4". 

Para más información, la fuente habitual: http://dev.mysql.com/doc/refman/5.0/en/working-with-null.html.

Avisados quedamos.


(1) C.J. Date, An Introduction to Database Systems, ISBN: 0-321-19784-4.