2011-11-07 14 views
24

Esto es solo una pregunta por curiosidad, pero estoy mirando una base de datos y extrayendo datos de una tabla con una consulta en una de las columnas. La columna tiene cuatro valores posibles null, 0, 1, 2. Cuando ejecuto la consulta como:SQL no muestra valores nulos en una consulta no igual?

SELECT * FROM STATUS WHERE STATE != '1' AND STATE != '2'; 

consigo los mismos resultados que en ejecución:

SELECT * FROM STATUS WHERE STATE = '0'; 

es decir, las filas con un valor nulo en el comando superior en la columna consultada parecen omitirse de los resultados, ¿esto siempre ocurre en SQL?

Estoy ejecutando mis comandos a través de Oracle SQL Developer.

+4

"siempre pasa esto en SQL?" - respuesta corta: no. SQL exhibe [lógica de tres valores (3VL)] (http: //en.wikipedia.org/wiki/Three-valued_logic). Digo "exhibits" muy deliberadamente porque las especificaciones para SQL 3VL son inconsistentes e incompletas. Simplemente tiene que aprender todos los casos extremos. El mejor enfoque de IMO es evitar nulos en SQL. – onedaywhen

+1

Sé que esto no agrega ninguna idea, pero ¿debería el 'O 'ser un' Y'? – user123444555621

+0

De lo que puedo recordar cuando estaba haciendo esto como OR es correcto, es decir, solo quería filas de ESTADO 0 pero también recibía filas NULAS. No estaba al tanto de la lógica de tres valores como @Vash describe en su respuesta. Debería haber usado ESTADO NO EN ('1', '2') como señaló Michael Durrant. Mi SQL es mucho mejor que en ese entonces jajaja. –

Respuesta

20

En varios idiomas, NULL se maneja de manera diferente: la mayoría de la gente conoce la lógica de dos valores donde true y false son los únicos valores comparables en booleano ex pressions (incluso es falso se define como 0 y verdadero como cualquier otra cosa).

En SQL estándar tienes que pensar en three-valued logic. NULL no se trata como un valor real, podrías llamarlo "desconocido". Entonces, si el valor es desconocido, no está claro si en su caso state es 0, 1 o cualquier otra cosa. Entonces, NULL != 1 da como resultado NULL nuevamente.

Esto concluye que dondequiera que filtre algo que puede ser NULO, tiene que tratar los valores NULL por su cuenta. Tenga en cuenta que la sintaxis también es diferente: los valores NULL solo se pueden comparar con x IS NULL en lugar de x = NULL. Ver Wikipedia para una tabla de verdad que muestra los resultados de las operaciones lógicas.

+0

Ya veo, aplausos por la respuesta rápida Vash :) Definitivamente lo tendré en cuenta en el futuro. –

+1

Creo que en stackexchange recibirás respuestas muy rápido en general. Si intenta responder preguntas usted mismo, descubrirá que es difícil encontrar una pregunta sin respuesta que pueda responder y desee responder. Sin embargo, esta también fue una respuesta corta, y ahora que estoy en casa la actualizaré también, para reflejar la lógica de tres valores. – Alex

7

Yest es normal, puede tal vez poner una configuración de base de datos fijo que

pero se podía modificar su código y hacer algo así:

SELECT * FROM STATUS WHERE STATE != '1' OR STATE != '2' or STATE is null; 

Mira esto para más información: http://www.w3schools.com/sql/sql_null_values.asp

3

múltiples or con where pueden volverse difíciles de leer e inseguros en cuanto a los resultados.

Recomendaría un paréntesis adicional más el uso de la declaración IN (NOT IN en este caso), p.

SELECT * FROM STATUS WHERE (STATE NOT IN ('1', '2')) or STATE is null;

Implmentations pueden variar entre los proveedores de bases de datos, pero la sintaxis explícita anterior debe asegurarse de los resultados.

0

creé script para research Oracle comportamiento:

create table field_values 
(
is_user_deletable VARCHAR2(1 CHAR), 
resource_mark VARCHAR2(3 CHAR) 
) 

insert into field_values values (NULL, NULL); 
insert into field_values values ('Y', NULL); 
insert into field_values values ('N', NULL); 

select * from field_values; -- 3 row 

-- 1 row, bad 
update field_values set resource_mark = 'D' where is_user_deletable = 'Y'; 
update field_values set resource_mark = 'D' where is_user_deletable <> 'N'; 
update field_values set resource_mark = 'D' where is_user_deletable != 'N'; 
update field_values set resource_mark = 'D' where is_user_deletable not in ('Y'); 

-- 2 rows, good, but needs more SQL and more comparisons. Does DB optimizes? 
update field_values set resource_mark = 'D' where is_user_deletable = 'N' or is_user_deletable is null; 

-- it better to have ('Y' and NULL) or ('N' and NULL), but not 'Y' and 'N' and NULL (avoid quires with https://en.wikipedia.org/wiki/Three-valued_logic) 
-- adding new column which is 'Y' or 'N' only into existing table may be very long locking operation on existing table (or running long DML script) 

0

uso NVL así: SELECT * FROM STATUS WHERE NVL(STATE,'X') != '1' AND NVL(STATE,'X')!= '2';

Cuestiones relacionadas