- Lógica booleana: La negación de un conjunto de comparaciones relacionadas por medio de cláusulas OR, resultará en la negación de cada comparación y las cláusulas OR se convierten en AND. Ejemplos:
NOT ( A=B OR C=D OR E=F) es equivalente a (A<>B AND C<>D AND E<>F)
- Los valores NULL sólo deben compararse con las instrucciones IS NULL o IS NOT NULL. Cualquier comparación con operadores clásicos como mayor, mayor o igual, distinto, etc., hace que la comparación falle y traiga como respuesta FALSO.
- El operador IN, compara un elemento contra un conjunto. Si el elemento está en ese conjunto, la comparación resultará VERDADERA. El operador NOT IN hace lo contrario. Si el elemento no está en dicho conjunto, la comparación resultará VERDADERA. Ejemplos:
1 IN (1,2,3): VERDADERO
1 IN (2,3): FALSO
1 NOT IN (2,3): VERDADERO
1 NOT IN (1,2,3): FALSO
- Para afectos prácticos, el elemento se compara con cada uno de los elementos del conjunto. Si el elemento es igual a cualquiera de ellos, la comparación es VERDADERA.
Aclarados los aspectos básicos, supongamos la existencia de las siguientes tablas:
CREATE TABLE detalle
(
identificador INTEGER NOT NULL,
producto_id INTEGER NULL,
cantidad INTEGER NOT NULL,
precio NUMERIC (10.2) NOT NULL
);
ALTER TABLE detalle ADD PRIMARY KEY (identificador);
CREATE TABLE producto
(
producto_id INTEGER NOT NULL,
descripcion CHAR (50) NOT NULL
)
ALTER TABLE producto ADD PRIMARY KEY (producto_id);
¿Por qué podría fallar esta consulta?
SELECT * FROM PRODUCTO WHERE PRODUCTO_ID NOT IN
(SELECT PRODUCTO_ID FROM DETALLE);
Obsérvese que el campo PRODUCTO_ID en la tabla DETALLE puede ser NULL. A efectos de la explicación, supongamos que los valores de este campo son los siguientes: 1, 2, 3 y NULL. Dicho esto, la consulta anterior es equivalente a ésta:
SELECT * FROM PRODUCTO WHERE PRODUCTO_ID NOT IN (1, 2, 3, NULL);
Lo que la hace equivalente a:
SELECT * FROM PRODUCTO WHERE NOT (PRODUCTO_ID IN (1, 2, 3, NULL) )
Lo que es equivalente a:
SELECT * FROM PRODUCTO WHERE NOT
(PRODUCTO_ID = 1 OR PRODUCTO_ID = 2 OR PRODUCTO_ID = 3 OR PRODUCTO_ID = NULL )
Y por lo visto en el apartado de lógica booleana esta consulta es equivalente a:
SELECT * FROM PRODUCTO WHERE
(PRODUCTO_ID <> 1 AND PRODUCTO_ID<>2 AND PRODUCTO_ID<> 3 AND PRODUCTO_ID <> NULL)
Ya que NULL sólo debe compararse con IS NULL o IS NOT NULL, la expresión PRODUCTO_ID <> NULL siempre fallará y por lo tanto, la expresión:
(PRODUCTO_ID <> 1 AND PRODUCTO_ID<>2 AND PRODUCTO_ID<> 3 AND PRODUCTO_ID <> NULL )
también siempre fallará. Como corolario, la consulta jamás traerá registros debido a la presencia de un valor NULL en la consulta anidada.
Para evitar este problema la consulta debe reescribirse de la siguiente manera:
SELECT * FROM PRODUCTO WHERE PRODUCTO_ID NOT IN
(SELECT PRODUCTO_ID FROM DETALLE WHERE PRODUCTO_ID IS NOT NULL);
Esto soluciona el problema de existencia de valores NULL en la consulta anidada.
No hay comentarios:
Publicar un comentario