En el servidor SQL, si tiene nullParam=NULL
una cláusula where, siempre se evalúa como falsa. Esto es contradictorio y me ha causado muchos errores. Entiendo que IS NULL
y las IS NOT NULL
palabras clave son la forma correcta de hacerlo. Pero, ¿por qué el servidor SQL se comporta de esta manera?
sql
sql-server
null
Byron Whitlock
fuente
fuente
Respuestas:
Piense en el nulo como "desconocido" en ese caso (o "no existe"). En cualquiera de esos casos, no puede decir que son iguales, porque no conoce el valor de ninguno de ellos. Entonces, null = null se evalúa como no verdadero (falso o nulo, dependiendo de su sistema), porque no conoce los valores para decir que SON iguales. Este comportamiento se define en el estándar ANSI SQL-92.
EDITAR: Esto depende de su configuración ansi_nulls . si tiene ANSI_NULLS desactivado, esto se evaluará como verdadero. Ejecute el siguiente código para ver un ejemplo ...
fuente
(NaN == NaN) == false && (NaN != Nan) == false && (NaN < NaN) == false && ...
, porque, bueno, si no es un número, simplemente no puede decir mucho al respecto; Es algo desconocido. El concepto es sólido, incluso si no es intuitivo para las personas que nunca lo han visto antes.NULL
expresión de SQL puede tratarse como una variable matemática distinta . Por lo tanto, una expresiónNULL = NULL
debe tratarse comox = y
, dondex
yy
son variables independientes. Ahora, si alguien te pregunta, ¿cuál es el valor dex = y
? La única respuesta razonable es "algunosz
". Así que tenemos(x = y) = z
- o, transcribir de nuevo a SQL,(NULL = NULL) = NULL
.¿Cuántos años tiene Frank? No lo sé (nulo).
¿Cuántos años tiene Shirley? No lo sé (nulo).
¿Frank y Shirley tienen la misma edad?
La respuesta correcta debería ser "No sé" (nulo), no "no", ya que Frank y Shirley podrían tener la misma edad, simplemente no lo sabemos.
fuente
null = null
rindeFALSE
, noNULL
.Aquí espero aclarar mi posición.
Que
NULL = NULL
evaluar aFALSE
está mal. Hacker y Mister respondieron correctamenteNULL
. Aquí es por qué. Dewayne Christensen me escribió, en un comentario a Scott Ivey :Pueden ser diferentes o pueden ser iguales, no se sabe hasta que uno abre ambos regalos. ¿Quién sabe? Invitaste a dos personas que no se conocen y ambas te han hecho el mismo regalo: raro, pero no imposible § .
Entonces, la pregunta: ¿estos dos DESCONOCIDOS presentan lo mismo (igual, =)? La respuesta correcta es: DESCONOCIDA (es decir
NULL
).Este ejemplo tenía la intención de demostrar que ".. (
false
onull
, dependiendo de su sistema) .." es una respuesta correcta, no lo es, soloNULL
es correcta en 3VL (¿o está bien que acepte un sistema que da respuestas incorrectas? )Una respuesta correcta a esta pregunta debe enfatizar estos dos puntos:
Así que reitero: SQL no sirve para obligar a uno a interpretar la propiedad reflexiva de la igualdad, que establece que:
.. en un 3VL (
TRUE
,FALSE
,NULL
). La expectativa de las personas se ajustaría a 2VL (TRUE
,FALSE
que incluso en SQL es válido para todos los demás valores), es decir,x = x
siempre evalúe aTRUE
, para cualquier valor posible de x, sin excepciones.Tenga en cuenta también que los NULL son " no valores " válidos (como sus apologistas pretenden que son) que se pueden asignar como valores de atributo (??) como parte de las variables de relación. Por lo tanto, son valores aceptables de cada tipo (dominio), no solo del tipo de expresiones lógicas.
Y este fue mi punto :,
NULL
como valor, es una "bestia extraña". Sin eufemismo, prefiero decir: sin sentido .Creo que esta formulación es mucho más clara y menos discutible, lo siento por mi pobre dominio del inglés.
Este es solo uno de los problemas de los NULL. Es mejor evitarlos por completo, cuando sea posible.
§ aquí nos preocupan los valores , por lo que el hecho de que los dos presentes sean siempre dos objetos físicos diferentes no es una objeción válida; si no está convencido de que lo siento, este no es el lugar para explicar la diferencia entre el valor y la semántica de "objeto" (el álgebra relacional tiene una semántica de valor desde el principio; consulte el principio de información de Codd; creo que algunos implementadores de SQL DBMS no ni siquiera se preocupe por una semántica común).
§§ que yo sepa, este es un axioma aceptado (de una forma u otra, pero siempre interpretado en un 2VL) desde la antigüedad y eso exactamente porque es muy intuitivo. 3VL (es una familia de lógicas en realidad) es un desarrollo mucho más reciente (pero no estoy seguro de cuándo se desarrolló por primera vez).
Nota al margen: si alguien presenta los tipos de fondo , unidad y opción como intentos de justificar los NULL de SQL, solo me convenceré después de un examen bastante detallado que mostrará cómo las implementaciones de SQL con NULL tienen un sistema de tipo de sonido y finalmente aclararán qué son NULL (estos "valores-no-valores-realmente") realmente.
En lo que sigue citaré algunos autores. Cualquier error u omisión es probablemente mío y no de los autores originales.
Joe Celko en SQL NULLs
Veo a menudo a Joe Celko citado en este foro. Aparentemente es un autor muy respetado aquí. Entonces, me dije a mí mismo: "¿qué escribió sobre los NULL de SQL? ¿Cómo explica los numerosos problemas de NULL?". Uno de mis amigos tiene una versión de ebook del SQL de Joe Celko para smarties: programación avanzada de SQL, tercera edición . Veamos.
Primero, la tabla de contenido. Lo que más me sorprende es la cantidad de veces que se menciona NULL y en los contextos más variados:
y así. Suena "desagradable caso especial" para mí.
Voy a entrar en algunos de estos casos con extractos de este libro, tratando de limitarme a lo esencial, por razones de derechos de autor. Creo que estas citas caen dentro de la doctrina del "uso justo" e incluso pueden estimular la compra del libro, por lo que espero que nadie se queje (de lo contrario, tendré que eliminar la mayor parte, si no todas). Además, me abstendré de informar fragmentos de código por el mismo motivo. Lo siento por eso. Compre el libro para leer sobre el razonamiento datailed.
Números de página entre paréntesis en lo que sigue.
Una vez más, este "valor, pero no es un valor" sin sentido. El resto me parece bastante sensato.
A propósito de SQL, NULL e infinito:
Las implementaciones de SQL no decidieron qué significa realmente NULL en contextos particulares:
Joe Celko citando a David McGoveran y CJ Fecha:
NULL como adicción a las drogas :
Mi única objeción aquí es "usarlos correctamente", que interactúa mal con comportamientos de implementación específicos.
(separador)
Pero DESCONOCIDO es una fuente de problemas en sí mismo, por lo que CJ Date, en su libro citado a continuación, recomienda en el capítulo 4.5. Evitar nulos en SQL :
Lea "ASIDE" en UNKNOWN, también vinculado a continuación.
(separador)
Objeción: NULL confunde incluso a las personas que conocen bien SQL, ver más abajo.
(separador)
(separador)
(separador)
(separador)
(separador)
(separador)
Hablando de GROUP BY:
Esto significa que para la cláusula GROUP BY NULL = NULL no se evalúa como NULL, como en 3VL, pero se evalúa como TRUE.
El estándar SQL es confuso:
Y así. Creo que es suficiente por Celko.
Fecha de CJ en NULL de SQL
CJ Date es más radical acerca de los NULL: evite los NULL en SQL, punto. De hecho, el capítulo 4 de su Teoría SQL y Relacional: Cómo escribir un código SQL preciso se titula "SIN DUPLICADOS, SIN NULOS", con subcapítulos "4.4 ¿Qué hay de malo con los nulos?" y "4.5 Evitar nulos en SQL" (siga el enlace: gracias a Google Books, puede leer algunas páginas en línea).
Fabian Pascal en SQL NULLs
De sus problemas prácticos en la gestión de bases de datos: una referencia para el practicante de pensamiento (sin extractos en línea, lo siento):
fuente
NULL
es porque no es un valor.(NULL = NULL) -> FALSE
. Para citar la documentación paraANSI_NULLS
: "Cuando se especifica ON, todas las comparaciones con un valor nulo se evalúan como DESCONOCIDO . Cuando se especifica OFF, las comparaciones de valores no UNICODE con un valor nulo se evalúan como VERDADERO si ambos valores son NULL".Tal vez depende, pero pensé que
NULL=NULL
evalúa laNULL
mayoría de las operaciones con NULL como un operando.fuente
El hecho de que no sepas qué son dos cosas no significa que sean iguales. Si cuando piensas en
NULL
ti piensas en "NULL" (cadena), entonces probablemente quieras una prueba de igualdad diferente como la deIS DISTINCT FROM
AND de PostgresqlIS NOT DISTINCT FROM
De los documentos de PostgreSQL sobre "Funciones de comparación y operadores"
fuente
El concepto de NULL es cuestionable, por decir lo menos. Codd introdujo el modelo relacional y el concepto de NULL en contexto (¡y luego propuso más de un tipo de NULL!) Sin embargo, la teoría relacional ha evolucionado desde los escritos originales de Codd: algunas de sus propuestas han sido descartadas (por ejemplo, clave principal) y otros nunca se entendieron (por ejemplo, operadores theta). En la teoría relacional moderna (realmente la teoría relacional, debería enfatizar) NULL simplemente no existe. Ver El Tercer Manifiesto. http://www.thethirdmanifesto.com/
El lenguaje SQL sufre el problema de la compatibilidad con versiones anteriores. NULL encontró su camino en SQL y estamos atrapados en él. Podría decirse que la implementación de
NULL
en SQL es defectuosa (la implementación de SQL Server hace las cosas aún más complicadas debido a suANSI_NULLS
opción).Recomiendo evitar el uso de columnas NULLable en tablas base.
Aunque tal vez no debería ser tentado, solo quería afirmar mis propias correcciones sobre cómo
NULL
funciona en SQL:NULL
=NULL
evalúa aUNKNOWN
.UNKNOWN
Es un valor lógico.NULL
es un valor de datosEsto es fácil de probar, por ejemplo
SELECT NULL = NULL
genera correctamente un error en SQL Server. Si el resultado fuera un valor de datos, entonces esperaríamos ver
NULL
, como algunas respuestas aquí (erróneamente) sugieren que lo haríamos.El valor lógico
UNKNOWN
se trata de manera diferente en SQL DML y SQL DDL respectivamente.En SQL DML,
UNKNOWN
hace que las filas se eliminen del conjunto de resultados.Por ejemplo:
El
INSERT
tiene éxito para esta fila, aunque laCHECK
condición se resuelvaNULL = NULL
. Esto se debe definir en el estándar SQL-92 ("ANSI"):Lea eso de nuevo cuidadosamente, siguiendo la lógica.
En inglés simple, nuestra nueva fila de arriba recibe el "beneficio de la duda" sobre ser
UNKNOWN
y se le permite pasar.En SQL DML, la regla de la
WHERE
cláusula es mucho más fácil de seguir:En inglés simple, las filas que evalúan
UNKNOWN
se eliminan del conjunto de resultados.fuente
En technet hay una buena explicación de cómo funcionan los valores nulos.
Nulo significa desconocido.
Por lo tanto, la expresión booleana
valor = nulo
no se evalúa como falso, se evalúa como nulo, pero si ese es el resultado final de una cláusula where, no se devuelve nada. Esa es una forma práctica de hacerlo, ya que devolver nulo sería difícil de concebir.
Es interesante y muy importante comprender lo siguiente:
Si en una consulta tenemos
y
luego
"value = @ param" se evalúa como nulo
"@param es nulo" se evalúa como verdadero
"id = @ anotherParam" se evalúa como verdadero
Entonces la expresión a evaluar se convierte en
(nulo o verdadero) y verdadero
Podríamos sentir la tentación de pensar que aquí "nulo o verdadero" se evaluará como nulo y, por lo tanto, toda la expresión se vuelve nula y no se devolverá la fila.
Esto no es asi. ¿Por qué?
Debido a que "nulo o verdadero" se evalúa como verdadero, lo cual es muy lógico, ya que si un operando es verdadero con el operador O, no importa el valor del otro operando, la operación devolverá verdadero. Por lo tanto, no importa que el otro operando sea desconocido (nulo).
Entonces, finalmente tenemos true = true y, por lo tanto, se devolverá la fila.
Nota: con la misma lógica cristalina que "nulo o verdadero" se evalúa como verdadero, "nulo y verdadero" se evalúa como nulo.
Actualización:
Ok, solo para completarlo, quiero agregar el resto aquí también, lo que resulta bastante divertido en relación con lo anterior.
"nulo o falso" se evalúa como nulo, "nulo y falso" se evalúa como falso. :)
Por supuesto, la lógica sigue siendo tan evidente como antes.
fuente
Porque
NULL
significa 'valor desconocido' y dos valores desconocidos no pueden ser iguales.Entonces, si para nuestra lógica
NULL
N ° 1 es igual aNULL
N ° 2, entonces tenemos que decirlo de alguna manera:donde el valor conocido
-1
N ° 1 es igual a-1
N ° 2fuente
nullParam1 = -1
ynullParam2 =NULL
e airplain accidente .... debe serISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
Todas las respuestas aquí parecen provenir de una perspectiva de CS, así que quiero agregar una desde la perspectiva de un desarrollador.
Para un desarrollador, NULL es muy útil. Las respuestas aquí dicen que NULL significa desconocido, y tal vez en la teoría de CS es cierto, no lo recuerdo, ha pasado un tiempo. Sin embargo, en el desarrollo real, al menos en mi experiencia, eso ocurre aproximadamente el 1% del tiempo. El otro 99% se usa para casos en los que el valor no es DESCONOCIDO, pero SE SABE QUE ESTÁ AUSENTE.
Por ejemplo:
Client.LastPurchase
, para un nuevo cliente. No se desconoce, se sabe que aún no ha realizado una compra.Cuando se usa un ORM con una asignación de jerarquía de tabla por clase , algunos valores simplemente no se asignan para ciertas clases.
Al mapear una estructura de árbol, una raíz generalmente tendrá
Parent = NULL
Y muchos más...
Estoy seguro de que la mayoría de los desarrolladores en algún momento escribieron
WHERE value = NULL
, no obtuvieron ningún resultado, y así es como aprendieron sobre laIS NULL
sintaxis. Basta con mirar cuántos votos tiene esta pregunta y los vinculados.Las bases de datos SQL son una herramienta y deben diseñarse de la manera más fácil de entender para sus usuarios.
fuente
NULL no es igual a nada, ni siquiera a sí mismo. Mi solución personal para comprender el comportamiento de NULL es evitar usarlo tanto como sea posible :).
fuente
La pregunta:
¿Un desconocido es igual a otro desconocido?
(NULL = NULL)
Esa pregunta es algo que nadie puede responder, por lo que su valor predeterminado es verdadero o falso, según la configuración de ansi_nulls.
Sin embargo, la pregunta:
¿se desconoce esta variable desconocida?
Esta pregunta es bastante diferente y puede responderse con verdadero.
nullVariable = null está comparando los valores
nullVariable es null está comparando el estado de la variable
fuente
La confusión surge del nivel de indirección (abstracción) que surge del uso de NULL .
Volviendo a la analogía de "lo que está debajo del árbol de Navidad", "Desconocido" describe el estado del conocimiento sobre lo que está en el Cuadro A.
Entonces, si no sabe qué hay en el Cuadro A, dice que es "Desconocido", pero eso no significa que "Desconocido" esté dentro del cuadro . Hay algo distinto de desconocido en la caja, posiblemente algún tipo de objeto, o posiblemente no hay nada en la caja.
Del mismo modo, si no sabe qué hay en el Cuadro B, puede etiquetar su estado de conocimiento sobre los contenidos como "Desconocido".
Así que aquí está el truco: Su estado de conocimiento sobre la caja de A es igual a su estado de conocimiento sobre la Caja B . (Su estado de conocimiento en ambos casos es "Desconocido" o "No sé qué hay en la caja"). Pero el contenido de las cajas puede o no ser igual.
Volviendo a SQL, idealmente solo debería poder comparar valores cuando sepa cuáles son. Desafortunadamente, la etiqueta que describe la falta de conocimiento se almacena en la celda misma , por lo que estamos tentados a usarla como un valor. Pero no debemos usar eso como un valor, ya que conduciría a que "el contenido del cuadro A sea igual al contenido del cuadro B cuando no sabemos qué hay en el cuadro A y / o no sabemos qué hay en el cuadro B. (Lógicamente, la implicación "si no sé qué hay en el cuadro A y si no sé qué hay en el cuadro B, entonces lo que está en el cuadro A = ¿Qué hay en el cuadro B" es falso).
Yay, caballo muerto.
fuente
MSDN tiene un buen artículo descriptivo sobre nulos y la lógica de tres estados que engendran.
En resumen, la especificación SQL92 define NULL como desconocido, y NULL usado en los siguientes operadores causa resultados inesperados para los no iniciados:
fuente
null es desconocido en sql, por lo que no podemos esperar que dos incógnitas sean iguales.
Sin embargo, puede obtener ese comportamiento estableciendo ANSI_NULLS en Off (está activado de forma predeterminada). Podrá usar = operator para nulos
fuente
null
, aprender a entenderlo o simplemente alterar la tabla para tener tipos int y actualizar las columnas.Usted trabaja para el gobierno registrando información sobre ciudadanos. Esto incluye la identificación nacional de cada persona en el país. Un niño fue dejado en la puerta de una iglesia hace unos 40 años, nadie sabe quiénes son sus padres. La identificación del padre de esta persona es
NULL
. Existen dos de esas personas. Cuente las personas que comparten la misma identificación de padre con al menos otra persona (personas que son hermanos). ¿Cuentan ustedes dos también?La respuesta es no, no, porque no sabemos si son hermanos o no.
Supongamos que no tiene una
NULL
opción y, en su lugar, utiliza un valor predeterminado para representar "lo desconocido", tal vez una cadena vacía o el número 0 o un *, etc. Entonces tendría en sus consultas que * = * , 0 = 0 y “” = “”, etc. Esto no es lo que desea (según el ejemplo anterior), y como a menudo puede olvidarse de estos casos (el ejemplo anterior es un caso marginal claro fuera del pensamiento cotidiano ordinario) ), entonces necesita un lenguaje para recordar queNULL = NULL
no es cierto.La necesidad es la madre de la invención.
fuente
Solo una adición a otras maravillosas respuestas:
fuente
Si está buscando una expresión que devuelva verdadero para dos NULL, puede usar:
Es útil si desea replicar datos de una tabla a otra.
fuente
La prueba de igualdad, por ejemplo, en una declaración de caso cuando la cláusula, se puede cambiar de
a
Si quiero tratar los espacios en blanco y la cadena vacía como iguales a NULL, a menudo también uso una prueba de igualdad como:
fuente