¿Por qué NULL = NULL se evalúa como falso en el servidor SQL?

147

En el servidor SQL, si tiene nullParam=NULLuna cláusula where, siempre se evalúa como falsa. Esto es contradictorio y me ha causado muchos errores. Entiendo que IS NULLy las IS NOT NULLpalabras clave son la forma correcta de hacerlo. Pero, ¿por qué el servidor SQL se comporta de esta manera?

Byron Whitlock
fuente
166
No tengo una hermana, y mi amiga tampoco. Si "NULL = NULL", entonces tenemos una hermana común, ¡y por lo tanto estamos relacionados! :)
Matt Hamilton
11
Existe una controversia de larga data sobre los NULL de SQL (ver por ejemplo: en.wikipedia.org/wiki/Null_%28SQL%29#Controversy y firstsql.com/inulls.htm ). El punto específico aquí es que la igualdad es un concepto matemático establecido desde hace mucho tiempo y SQL lo viola; la igualdad es reflexiva: para cada x, x = x. Eso debe ser siempre cierto, de lo contrario se está introduciendo una interpretación de la igualdad que no es estándar y el resultado obvio es la confusión.
MaD70
14
No viola las matemáticas en absoluto. Estoy pensando en dos números. Sin embargo, no voy a decirte cuáles son. Entonces ahora me dices, ¿son iguales?
Tom H
10
@ Matt, no estoy de acuerdo con tu analogía. NULL = NULL no significa que tenga una hermana común, significaría que ambos carecen de una hermana.
reustmd
55
@ manu08 No, la implementación actual (que NULL nunca es igual a NULL) significa que ambos carecemos de una hermana, que era mi punto.
Matt Hamilton

Respuestas:

206

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 ...

set ansi_nulls off

if null = null
    print 'true'
else
    print 'false'


set ansi_nulls ON

if null = null
    print 'true'
else
    print 'false'
Scott Ivey
fuente
11
x = x solo es cierto cuando x es un valor conocido . NULL es una representación textual de un valor desconocido . Si tiene dos valores desconocidos, no puede declarar de manera concluyente nada sobre su igualdad. Creo que eso también fue cierto durante algunos siglos.
Dewayne Christensen el
44
Como es diciembre, usemos un ejemplo estacional. Tengo dos regalos debajo del árbol. Ahora, dime si tengo dos de lo mismo o no.
Dewayne Christensen
55
SQL NULL no es diferente del punto flotante IEEE NaN, donde también lo tiene (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.
Pavel Minaev
8
Aquí no hay violación de la reflexividad, porque NULL no es miembro del conjunto de valores (dominio, en términos relacionales). NULL no es un valor . Es un marcador de posición para el valor que se desconoce.
Pavel Minaev el
9
En otras palabras, cada NULLexpresión de SQL puede tratarse como una variable matemática distinta . Por lo tanto, una expresión NULL = NULLdebe tratarse como x = y, donde xy yson variables independientes. Ahora, si alguien te pregunta, ¿cuál es el valor de x = y? La única respuesta razonable es "algunos z". Así que tenemos (x = y) = z- o, transcribir de nuevo a SQL, (NULL = NULL) = NULL.
Pavel Minaev
131

¿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.

Neil McGuigan
fuente
44
No estoy de acuerdo con que nulo significa "desconocido". Lo que realmente significa es "sin datos". Eso podría usarse para representar el caso en el que no se conoce la información, pero en realidad es más probable que se use para indicar que algo no existe. Para continuar con tu ejemplo: ¿Cuál es el segundo nombre de Frank? Él no tiene uno (nulo). ¿Cuál es el segundo nombre de Shirley? Ella no tiene uno (nulo). ¿Frank y Shirley tienen el mismo segundo nombre? ¿Si? ¿No? No se Puedo ver un argumento para "no", y puedo ver un argumento para "no sé", pero no hay un argumento real para "sí" a menos que sea demasiado literal.
Richiban
2
@richiban No estoy de acuerdo. La falta de existencia de una fila significa 'sin datos'
Neil McGuigan
1
@NeilMcGuigan Eso es cierto para los datos que tienen su propia tabla, pero ¿qué pasa con los datos que se representan en una columna? ¿No usarías 'nulo' para representar el hecho de que los datos no existen? 'No conocido' es una razón muy específica para la ausencia de datos.
Richiban
3
Pero null = nullrinde FALSE, no NULL.
slartidan
1
@slartidan Estoy de acuerdo con usted, sin embargo, eso es incorrecto
Neil McGuigan el
28

Aquí espero aclarar mi posición.

Que NULL = NULLevaluar a FALSEestá mal. Hacker y Mister respondieron correctamente NULL. Aquí es por qué. Dewayne Christensen me escribió, en un comentario a Scott Ivey :

Como es diciembre, usemos un ejemplo estacional. Tengo dos regalos debajo del árbol. Ahora, dime si tengo dos de lo mismo o no.

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 ".. ( falseo null, dependiendo de su sistema) .." es una respuesta correcta, no lo es, solo NULL 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:

  • la lógica de tres valores (3VL) es contraintuitiva (vea innumerables preguntas sobre este tema en Stackoverflow y en otro foro para asegurarse);
  • Los DBMS basados ​​en SQL a menudo no respetan incluso 3VL, a veces dan respuestas incorrectas (como afirma el póster original, SQL Server lo hace en este caso).

Así que reitero: SQL no sirve para obligar a uno a interpretar la propiedad reflexiva de la igualdad, que establece que:

for any x, x = x §§ (en inglés simple: cualquiera que sea el universo del discurso, una "cosa" siempre es igual a sí misma ).

.. en un 3VL ( TRUE, FALSE, NULL). La expectativa de las personas se ajustaría a 2VL ( TRUE, FALSEque incluso en SQL es válido para todos los demás valores), es decir, x = x siempre evalúe a TRUE , 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 :, NULLcomo 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:

3.4 Aritmética y NULL 109
3.5 Conversión de valores hacia y desde NULL 110
3.5.1 Función NULLIF () 110
6 NULL: datos faltantes en SQL 185
6.4 Comparación de NULL 190
6.5 NULL y lógica 190
6.5.1 NULLS en subconsultas Predicados 191
6.5.2 Estándar Soluciones SQL 193
6.6 Matemáticas y NULL 193
6.7 Funciones y NULL 193
6.8 NULL e idiomas de host 194
6.9 Consejos de diseño para NULL 195
6.9.1 Evitar NULL de los programas de host 197
6.10 Una nota sobre múltiples valores NULL 198
10.1 IS NULL Predicate 241
10.1. 1 Fuentes de NULL 242
...

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.

Restricción NO NULA (11)

La restricción de columna más importante es NOT NULL, que prohíbe el uso de NULL en una columna. Use esta restricción de forma rutinaria y elimínela solo cuando tenga una buena razón. Le ayudará a evitar las complicaciones de los valores NULL cuando realice consultas contra los datos.

No es un valor ; Es un marcador que contiene un lugar donde puede ir un valor.

Una vez más, este "valor, pero no es un valor" sin sentido. El resto me parece bastante sensato.

(12)

En resumen, los NULL causan muchas características irregulares en SQL, que discutiremos más adelante. Su mejor opción es memorizar las situaciones y las reglas para NULL cuando no puede evitarlas.

A propósito de SQL, NULL e infinito:

(104) CAPÍTULO 3: DATOS NUMÉRICOS EN SQL

SQL no ha aceptado el modelo IEEE para matemáticas por varias razones.

...

Si las reglas IEEE para matemáticas se permitieran en SQL, entonces necesitaríamos reglas de conversión de tipo para infinito y una forma de representar un valor numérico exacto infinito después de la conversión. La gente tiene suficientes problemas con los NULL, así que no vayamos allí.

Las implementaciones de SQL no decidieron qué significa realmente NULL en contextos particulares:

3.6.2 Funciones exponenciales (116)

El problema es que los logaritmos no están definidos cuando (x <= 0). Algunas implementaciones de SQL devuelven un mensaje de error, algunas devuelven un NULL y DB2 / 400; la versión 3 versión 1 devolvió * NEGINF (abreviatura de "infinito negativo") como resultado.

Joe Celko citando a David McGoveran y CJ Fecha:

6 NULL: datos faltantes en SQL (185)

En su libro A Guide to Sybase and SQL Server , David McGoveran y CJ Date dijeron: “Es la opinión de este escritor que los NULL, al menos tal como se definen e implementan actualmente en SQL, son mucho más problemas de lo que valen y deben evitarse; muestran un comportamiento muy extraño e inconsistente y pueden ser una rica fuente de error y confusión. (Tenga en cuenta que estos comentarios y críticas se aplican a cualquier sistema que admita NULL de estilo SQL, no solo a SQL Server específicamente).

NULL como adicción a las drogas :

(186/187)

En el resto de este libro, te instaré a que no los uses , lo que puede parecer contradictorio, pero no lo es. Piense en un NULL como una droga; úsalo correctamente y funciona para ti, pero abusa de él y puede arruinarlo todo. Su mejor política es evitar los NULL cuando pueda y usarlos adecuadamente cuando sea necesario.

Mi única objeción aquí es "usarlos correctamente", que interactúa mal con comportamientos de implementación específicos.

6.5.1 NULOS en predicados de subconsulta (191/192)

La gente olvida que una subconsulta a menudo oculta una comparación con un NULL. Considere estas dos tablas:

...

El resultado estará vacío. Esto es contraintuitivo , pero correcto.

(separador)

6.5.2 Soluciones SQL estándar (193)

SQL-92 resolvió algunos de los problemas de 3VL (lógica de tres valores) al agregar un nuevo predicado de la forma:

<condición de búsqueda> ES [NO] VERDADERO | FALSO | DESCONOCIDO

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 :

  • No use la palabra clave DESCONOCIDO en ningún contexto.

Lea "ASIDE" en UNKNOWN, también vinculado a continuación.

6.8 NULL e idiomas de host (194)

Sin embargo, debe saber cómo se manejan los NULL cuando se tienen que pasar a un programa host. Ningún lenguaje de host estándar para el que se define una incrustación admite NULL, que es otra buena razón para evitar usarlos en el esquema de su base de datos.

(separador)

6.9 Consejos de diseño para NULL (195)

Es una buena idea declarar todas las tablas base con restricciones NOT NULL en todas las columnas siempre que sea posible. Los NULL confunden a las personas que no conocen SQL, y los NULL son caros.

Objeción: NULL confunde incluso a las personas que conocen bien SQL, ver más abajo.

(195)

Deben evitarse los NULL en las CLAVES EXTRANJERAS. SQL permite esta relación de "beneficio de la duda", pero puede causar una pérdida de información en consultas que involucran uniones. Por ejemplo, dado un código de número de pieza en el inventario al que una tabla de pedidos hace referencia como una LLAVE EXTRANJERA, tendrá problemas para obtener una lista de las piezas que tienen un NULL. Esta es una relación obligatoria; No puede pedir una pieza que no existe.

(separador)

6.9.1 Evitar NULL de los programas de host (197)

Puede evitar poner NULL en la base de datos desde los Programas de host con cierta disciplina de programación.

...

  1. Determine el impacto de los datos faltantes en la programación y los informes: las columnas numéricas con NULL son un problema, porque las consultas que utilizan funciones agregadas pueden proporcionar resultados engañosos.

(separador)

(227)

La SUMA () de un conjunto vacío siempre es NULL. Uno de los errores de programación más comunes cometidos al usar este truco es escribir una consulta que podría devolver más de una fila. Si no lo pensó, podría haber escrito el último ejemplo como: ...

(separador)

10.1.1 Fuentes de NULL (242)

Es importante recordar dónde pueden ocurrir NULL. Son más que un simple valor posible en una columna . Las funciones agregadas en conjuntos vacíos, OUTER JOIN, expresiones aritméticas con NULL y operadores OLAP devuelven NULL. Estas construcciones a menudo aparecen como columnas en VIEWs.

(separador)

(301)

Otro problema con NULL se encuentra cuando intenta convertir predicados IN a predicados EXISTS.

(separador)

16.3 Las funciones ALL Predicate y Extrema (313)

Al principio es contradictorio que estos dos predicados no sean iguales en SQL:

...

Pero debe recordar las reglas para las funciones extremas: eliminan todos los valores NULL antes de devolver los valores mayores o menores. El predicado ALL no elimina NULL, por lo que puede obtenerlos en los resultados.

(separador)

(315)

Sin embargo, la definición en el estándar está redactada en negativo, de modo que los NULL obtienen el beneficio de la duda. ...

Como puede ver, es una buena idea evitar NULL en restricciones ÚNICAS.

Hablando de GROUP BY:

Los NULL se tratan como si fueran todos iguales y forman su propio grupo. Cada grupo se reduce a una sola fila en una nueva tabla de resultados que reemplaza a la anterior.

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:

ORDER BY y NULLs (329)

Si un valor de clave de clasificación que es NULL se considera mayor o menor que un valor no NULL está definido por la implementación, pero ...

... Hay productos SQL que lo hacen de cualquier manera.

En marzo de 1999, Chris Farrar planteó una pregunta de uno de sus desarrolladores que le hizo examinar una parte del Estándar SQL que creí haber entendido . Chris encontró algunas diferencias entre la comprensión general y la redacción real de la especificación .

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):

10.3 Implicaciones prácticas

10.3.1 NULL SQL

... SQL sufre de los problemas inherentes a 3VL, así como de muchas peculiaridades, complicaciones, contra intuición y errores directos [10, 11]; entre ellos están los siguientes:

  • Las funciones agregadas (p. Ej., SUM (), AVG ()) ignoran NULL (excepto COUNT ()).
  • Una expresión escalar en una tabla sin filas se evalúa incorrectamente como NULL, en lugar de 0.
  • La expresión "NULL = NULL" se evalúa como NULL, pero en realidad no es válida en SQL; Sin embargo, ORDER BY trata los NULL como iguales (lo que sea que precedan o sigan valores "normales" se deja al proveedor de DBMS).
  • La expresión "x NO ES NULO" no es igual a "NO (x ES NULO)", como es el caso en 2VL.

...

Todos los dialectos SQL implementados comercialmente siguen este enfoque de 3VL y, por lo tanto, no solo exponen estos problemas, sino que también tienen problemas de implementación específicos, que varían según los productos .

MaD70
fuente
44
"Y este era mi punto: NULL, como valor, es una" bestia extraña "". - Eso NULLes porque no es un valor.
Pavel Minaev
1
Además, SQL Server no da (NULL = NULL) -> FALSE. Para citar la documentación para ANSI_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".
Pavel Minaev
@Pavel Minaev: a) ¿y cómo VERDADERO es mejor que FALSO? b) Si no es un valor, ¿por qué se asigna como parte de valores variables?
MaD70
1
>> Como es diciembre, usemos un ejemplo estacional. Tengo dos regalos debajo del árbol. Ahora, dime si tengo dos de lo mismo o no. ... sí, lo hiciste en la medida en que obtuviste dos cosas y , en lo que a ti respecta en este momento , según tu conocimiento actual, son exactamente lo mismo para ti
Brad Thomas
3
nulo = nulo debe ser verdadero. nulo es un valor bien definido que puede representar un valor desconocido , pero también puede representar la ausencia de un valor. El desarrollador debe decidir qué representa nulo, pero nulo en sí mismo es absolutamente un valor y nulo es nulo = nulo. Cualquier otra implementación está destinada al desastre, porque estás interponiendo lógica ternaria en predicados que son fundamentalmente booleanos. Me APLICA que esto se está convirtiendo en una configuración permanente en el servidor SQL. APAGADO APAGADO APAGADO con él.
Triynko
9

Tal vez depende, pero pensé que NULL=NULLevalúa la NULLmayoría de las operaciones con NULL como un operando.

Michael Krelin - hacker
fuente
9

El hecho de que no sepas qué son dos cosas no significa que sean iguales. Si cuando piensas en NULLti piensas en "NULL" (cadena), entonces probablemente quieras una prueba de igualdad diferente como la de IS DISTINCT FROMAND de PostgresqlIS NOT DISTINCT FROM

De los documentos de PostgreSQL sobre "Funciones de comparación y operadores"

expresión IS DISTINCT FROMexpresión

expresión IS NOT DISTINCT FROMexpresión

Para entradas no nulas, IS DISTINCT FROMes lo mismo que el <>operador. Sin embargo, si ambas entradas son nulas, devuelve falso, y si solo una entrada es nula, devuelve verdadero. De manera similar, IS NOT DISTINCT FROMes idéntico a =las entradas no nulas, pero devuelve verdadero cuando ambas entradas son nulas y falso cuando solo una entrada es nula. Por lo tanto, estas construcciones actúan efectivamente como si nulo fuera un valor de datos normal, en lugar de "desconocido".

Evan Carroll
fuente
5

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 NULLen SQL es defectuosa (la implementación de SQL Server hace las cosas aún más complicadas debido a su ANSI_NULLSopció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 NULLfunciona en SQL:

NULL= NULLevalúa a UNKNOWN.

UNKNOWN Es un valor lógico.

NULL es un valor de datos

Esto 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 UNKNOWNse trata de manera diferente en SQL DML y SQL DDL respectivamente.

En SQL DML, UNKNOWNhace que las filas se eliminen del conjunto de resultados.

Por ejemplo:

CREATE TABLE MyTable
(
 key_col INTEGER NOT NULL UNIQUE, 
 data_col INTEGER
 CHECK (data_col = 55)
);

INSERT INTO MyTable (key_col, data_col)
   VALUES (1, NULL);

El INSERTtiene éxito para esta fila, aunque la CHECKcondición se resuelva NULL = NULL. Esto se debe definir en el estándar SQL-92 ("ANSI"):

11.6 definición de restricción de tabla

3)

Si la restricción de la tabla es una definición de restricción de verificación, entonces deje que SC sea la condición de búsqueda contenida inmediatamente en la definición de restricción de verificación y deje que T sea el nombre de la tabla incluido en el descriptor de restricción de tabla correspondiente; la restricción de la tabla no se cumple si y solo si

EXISTE (SELECCIONE * DE T DONDE NO (SC))

es verdad.

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 UNKNOWNy se le permite pasar.

En SQL DML, la regla de la WHEREcláusula es mucho más fácil de seguir:

La condición de búsqueda se aplica a cada fila de T. El resultado de la cláusula where es una tabla de esas filas de T para las cuales el resultado de la condición de búsqueda es verdadero.

En inglés simple, las filas que evalúan UNKNOWNse eliminan del conjunto de resultados.

un día cuando
fuente
5

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

where (value=@param Or @param is null) And id=@anotherParam

y

  • valor = 1
  • @param es nulo
  • id = 123
  • @ anotherParam = 123

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.

Magnus
fuente
4

Porque NULLsignifica 'valor desconocido' y dos valores desconocidos no pueden ser iguales.

Entonces, si para nuestra lógica NULLN ° 1 es igual a NULLN ° 2, entonces tenemos que decirlo de alguna manera:

SELECT 1
WHERE ISNULL(nullParam1, -1) = ISNULL(nullParam2, -1)

donde el valor conocido -1N ° 1 es igual a -1N ° 2

armen
fuente
nullParam1 = -1y nullParam2 =NULLe airplain accidente .... debe serISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
Selvin
4

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 la IS NULLsintaxis. 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.

AlexDev
fuente
1
Todo el mundo parece gritar "NULL es desconocido" y luego justifica el comportamiento. Sí, si esa es una premisa, entonces 3VL tal vez sea la respuesta. Pero en casi todos los DB en los que trabajo, NULL significa ausente. Lo siento, tu voz se pierde en el desierto @AlexDev
John Rees
3

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 :).

Chris R. Timmons
fuente
1
bien podría ser igual a todo, como lo es en el caso de las uniones izquierda / derecha / exterior ...
Miguel Ventura
55
Qué respuesta tan tonta e improductiva. Lo mismo podría decirse a los niños de primaria sobre álgebra, pero sin reconocer realmente lo que está tratando de resolver, simplemente sería una tontería, lo que sucedió.
Evan Carroll
2
@Evan: En realidad, evitar NULL es una solución sólida. La lógica de 3 valores no es indiscutible, y muchas personas sienten que SQL estaría mejor sin NULL y toda la complejidad (necesaria) que conlleva.
sleske
3
"Mucha gente" es una palabra de comadreja, y "no incontrovertible" es una forma de encubrir el más simple "controvertido" del que 3VL no lo es.
Evan Carroll
"NULL no es igual a nada, ni siquiera a sí mismo". siguiendo esa lógica, <somevalue>! = NULL debería devolver verdadero. En el extraño universo de SQL, sin embargo, es falso.
Tom Lint
3

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

usuario224385
fuente
3

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.

TomEberhard
fuente
3

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:

= operator NULL   true   false 
NULL       NULL   NULL   NULL
true       NULL   true   false
false      NULL   false  true

and op     NULL   true   false 
NULL       NULL   NULL   false
true       NULL   true   false
false      false  false  false

or op      NULL   true   false 
NULL       NULL   true   NULL
true       true   true   true
false      NULL   true   false
Paul Wagland
fuente
Pero la pregunta no es sobre 3VL (lógica de tres valores), sino sobre la propiedad reflexiva de la igualdad.
MaD70
Para ser más precisos, como finalmente detallé en mi respuesta, surgen problemas cuando la igualdad se interpreta en un 3VL, de modo que la propiedad reflexiva de la igualdad no siempre se evalúa como verdadera.
MaD70
1

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

SET ANSI_NULLS off
if null=null
print 1
else 
print 2
set ansi_nulls on
if null=null
print 1
else 
print 2
PD.
fuente
2
Esto es todo tipo de no . El mundo tiene una definición de null, aprender a entenderlo o simplemente alterar la tabla para tener tipos int y actualizar las columnas.
Evan Carroll
3
Realmente no recomendé SET ANSI_NULLS apagado. Me enteré de ANSI_NULLS por las malas. Pero siempre es bueno conocer todas las opciones disponibles, especialmente cuando se encuentra con una línea que dice Where SomeId = null ¿Cómo entendería esa línea sin conocer ANSI_NULLS? Desde mi punto de vista, mi publicación fue útil ... :)
ps.
1

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 NULLopció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 que NULL = NULLno es cierto.

La necesidad es la madre de la invención.

Rashad Saleh
fuente
0

Solo una adición a otras maravillosas respuestas:

AND: The result of true and unknown is unknown, false and unknown is false,
while unknown and unknown is unknown.

OR: The result of true or unknown is true, false or unknown is unknown, while unknown or unknown is unknown.

NOT: The result of not unknown is unknown
Kiren Siva
fuente
0

Si está buscando una expresión que devuelva verdadero para dos NULL, puede usar:

SELECT 1 
WHERE EXISTS (
    SELECT NULL
    INTERSECT
    SELECT NULL
)

Es útil si desea replicar datos de una tabla a otra.

Piotr
fuente
0

La prueba de igualdad, por ejemplo, en una declaración de caso cuando la cláusula, se puede cambiar de

XYZ = NULL 

a

XYZ IS NULL

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:

(NULLIF(ltrim( XYZ ),'') IS NULL)
Allan F
fuente