2009-12-02 21 views
21

que estaba leyendo este artículo: Get null == null in SQLpor qué no es nulo igual a null falsa

Y el consenso es que cuando se trata de probar la igualdad entre dos (anulables) columnas SQL, el enfoque correcto es:

where ((A=B) OR (A IS NULL AND B IS NULL)) 

Cuando A y B son NULL, (A = B) aún devuelve FALSE, ya que NULL no es igual a NULL. Es por eso que se requiere un cheque adicional.

¿Qué pasa cuando se prueban las desigualdades? Después de la discusión anterior, que me hizo pensar que a la desigualdad prueba que tendría que hacer algo como:

WHERE ((A <> B) OR (A IS NOT NULL AND B IS NULL) OR (A IS NULL AND B IS NOT NULL)) 

Sin embargo, me di cuenta de que eso no es necesario (al menos no en Informix 11.5), y puedo solo hazlo:

where (A<>B) 

Si A y B son NULL, esto devuelve FALSE. Si NULL no es igual a NULL, entonces, ¿no debería ser TRUE?

EDITAR
Todas estas son buenas respuestas, pero creo que mi pregunta era un poco vago. Permítanme expresarlo de otro modo:

Teniendo en cuenta que ya sea A o B puede ser nulo, ¿es suficiente para comprobar su desigualdad con

where (A<>B) 

o tengo que comprobar de forma explícita así:

WHERE ((A <> B) OR (A IS NOT NULL AND B IS NULL) OR (A IS NULL AND B IS NOT NULL)) 

CONSULTE este thread para la respuesta a esta pregunta.

+0

En resumen, ' anything = NULL' es NULL (ni verdadero ni falso). y 'anything <> NULL' es NULL también. –

Respuesta

25

expresiones relacionales con NULL realidad dió NULL nuevo

edición

aquí, <> representa operador binario arbitrario, NULL es el marcador de posición de SQL, y value es cualquier valor (NULL es no una valor):

  • NULL <> value ->NULL
  • NULL <> NULL ->NULL

la lógica es: NULL significa "ningún valor" o "valor desconocido", y por lo tanto cualquier comparación con cualquier valor real no tiene sentido.

es X = 42 verdadera, falsa o desconocida, dado que usted no sabe qué valor (si cualquier) X vale? SQL dice que es desconocido. es X = Y verdadero, falso o desconocido, dado que ambos son desconocidos? SQL dice que el resultado es unknown. y lo dice para cualquier operación relacional binaria, que solo es lógica (incluso si tener NULLs en el modelo no está en primer lugar).

SQL también proporciona dos operadores de sufijo unarios, IS NULL y IS NOT NULL, éstos vuelven VERDADERO o FALSO en función de su operando.

  • NULL IS NULL ->TRUE
  • NULL IS NOT NULL ->FALSE
+0

Oye, después de leer tu explicación, me aparece un "error de compilación en la cabeza". Quiero decir, ¿por qué la comparación binaria está permitida entonces? Si escribo 'select * from A donde A.xxx <> null' obtengo un conjunto de resultados vacío. Sin embargo, si escribo 'select * from A where null', esto es un error sintáctico. Entonces, algo no funciona para mí con la explicación de "valor <> nulo => nulo" ... ¿pueden ayudarme a pensar de la manera "correcta" sobre esto? – dingalapadum

+0

podría ser, ¿tendría más sentido pensar en ello como 'value <> null => false' y' value = null => false' también? Esto evitaría el tipo de error del que estoy hablando. Además de esto, uno puede razonar sobre el significado de algo como 'value <> null AND 1 = 1', mientras que' null AND 1 = 1' sería nuevamente sintácticamente extraño ... como dije, solo estoy intentando para envolver mi cabeza alrededor de esto – dingalapadum

+0

'foo OP NULL' está permitido porque SQL está roto. –

3

La respuesta corta es ... NULLs son extraños, en realidad no se comportan como era de esperar.

Aquí hay un excelente documento sobre cómo funcionan los NULL en SQL. Creo que ayudará a mejorar su comprensión del tema. Creo que las secciones sobre el manejo de valores nulos en expresiones serán especialmente útiles para usted.

http://www.oracle.com/technology/oramag/oracle/05-jul/o45sql.html

7

Todas las comparaciones que involucran null no están definidos, y como resultado false. Esta idea, que es la que impide que null se evalúe como equivalente a null, también impide que null se evalúe como NO equivalente a null.

+1

No estoy seguro de quién votó en contra de esto. Cualquier comparación que implique 'null's distinto de' is' VOLVERÁ falso en un DB que sigue el estándar SQL. – Donnie

+0

@Donnie: Gracias, me preguntaba dónde me equivoqué. –

+3

Lo hice. cualquier comparación que implique nulo devolverá NULL –

33

Debido a que el comportamiento de la siguiente manera establecieron ternary logic donde NULL se considera un valor desconocido.

Si se piensa en NULL como desconocido, se vuelve mucho más intuitivo:

Es unknown a igual a unknown b? No hay forma de saberlo, así que: unknown.

+3

¡Gran perspectiva! Otra forma de verlo es que si "desconocido a" equivale a "b desconocido", entonces no pueden ser realmente desconocidos, ya que sabes algo sobre ellos. Tipo de mecánica cuántica-y. – womp

+0

@womp: De hecho, sabes que no sabes;) –

3

El comportamiento predeterminado (ANSI) de nulos dentro de una expresión dará como resultado un nulo (hay suficientes otras respuestas con los casos de eso).

Sin embargo, hay algunos casos extremos y advertencias que me gustaría plantear cuando se trata de MS Sql Server que no están en la lista.

  • Los valores nulos dentro de una declaración que agrupe valores se considerarán iguales y se agruparán.
  • Los valores nulos dentro de una sentencia que los ordena se considerarán iguales.
  • valores nulos seleccionados dentro de una instrucción que está utilizando distinto serán consideradas igual al evaluar el aspecto distinto de la consulta

Es posible en SQL Server para anular la lógica expresión con respecto a la Null específica = prueba Null, utilizando SET ANSI_NULLS OFF, que le dará la igualdad entre valores nulos; este no es un movimiento recomendado, pero sí existe.

SET ANSI_NULLS OFF 

select result = 
    case 
     when null=null then 'eq' 
     else 'ne' 
    end 

SET ANSI_NULLS ON 

select result = 
    case 
     when null=null then 'eq' 
     else 'ne' 
    end 
0

"No se sabe a desconocido b? No hay forma de saberlo, entonces: desconocido".

La pregunta era: ¿por qué la comparación arroja FALSO?

Dada la lógica de tres valores, sería razonable que la comparación arroje UNKNOWN (no FALSE). Pero SQL produce FALSE, y no DESCONOCIDO.

Una de las miríadas de perversidades en el lenguaje SQL.

Además, el siguiente debe tenerse en cuenta:

Si "desconocido" es un valor lógico en la lógica ternaria, a continuación, que debería ser el caso de que una comparación de igualdad entre dos valores lógicos que tanto sucede estar (el valor de) "desconocido", entonces esa comparación debería arrojar TRUE.

Si el valor lógico es en sí mismo desconocido, entonces obviamente eso no se puede representar poniendo el valor "desconocido" allí, porque eso implicaría que se conoce el valor lógico (que es "desconocido"). Es decir, a.o., cómo la teoría relacional demuestra que la implementación de la lógica de 3 valores plantea el requisito de una lógica de 4 valores, que una lógica de 4 valores conduce a la necesidad de una lógica de 5 valores, etc. etc. hasta el infinito.

2

Aquí es una solución rápida

ISNULL (A, 0) = ISNULL (B, 0)

0 se puede cambiar a algo que nunca puede suceder en sus datos

Cuestiones relacionadas