¿Por qué NULL = NULL se evalúa como falso en el servidor SQL?
En el servidor SQL, si tiene nullParam=NULL
una cláusula donde, siempre se evalúa como falso. Esto es contradictorio y me ha causado muchos errores. Entiendo que las palabras clave IS NULL
y IS NOT NULL
son la forma correcta de hacerlo. Pero, ¿por qué el servidor SQL se comporta de esta manera?
Piense en el nulo como "desconocido" en ese caso (o "no existe"). En cualquiera de esos casos, no puedes decir que son iguales porque no conoces el valor de ninguno de ellos. Entonces, null=null se evalúa como falso (falso o nulo, dependiendo de su sistema), porque no conoce los valores para decir que SON iguales. Este comportamiento está definido 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 como 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'
¿Cuántos años tiene franco? 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.
Aquí espero aclarar mi posición.
Esa NULL = NULL
evaluación FALSE
está mal. Hacker y Mister respondieron correctamente NULL
. He aquí 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 iguales o no.
Pueden ser diferentes o pueden ser iguales, no lo sabes hasta que abres ambos regalos. ¿Quién sabe? Has invitado a dos personas que no se conocen y ambas te han hecho el mismo regalo: raro, pero no imposible § .
Entonces la pregunta: ¿son estos dos regalos DESCONOCIDOS iguales (iguales, =)? La respuesta correcta es: DESCONOCIDA (es decir NULL
).
Este ejemplo tenía como objetivo demostrar que "...( false
o 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 contradictoria (consulte muchas otras preguntas sobre este tema en Stackoverflow y en otros foros para asegurarse);
- Los DBMS basados en SQL a menudo no respetan ni siquiera 3VL, a veces dan respuestas incorrectas (como afirma el cartel original, SQL Server lo hace en este caso).
Entonces reitero: SQL no sirve de nada obligando a interpretar la propiedad reflexiva de la igualdad, que establece que:
for any x, x = x
§§ (en lenguaje sencillo: 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
,, FALSE
que incluso en SQL es válido para todos los demás valores), es decir, x = x
siempre se evaluaría como 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 sean) que se pueden asignar como valores de atributo (??) como parte de las variables de relación. Por lo que son valores aceptables de todo tipo (dominio), no sólo del tipo de expresiones lógicas.
Y este era mi punto : NULL
, como valor, es una "bestia extraña". Sin eufemismos prefiero decir: tonterías .
Creo que esta formulación es mucho más clara y menos discutible; perdón por mi pobre dominio del inglés.
Este es sólo 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, lo siento, no es este el lugar para explicar la diferencia entre la semántica de valor y "objeto" (el álgebra relacional tiene semántica de valor desde el principio; consulte el principio de información de Codd; creo que algunos implementadores de DBMS SQL no Ni siquiera me importa 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 precisamente porque es tan intuitivo. 3VLs (en realidad es una familia de lógicas) es un desarrollo mucho más reciente (pero no estoy seguro de cuándo se desarrolló por primera vez).
Nota al margen: si alguien introduce los tipos Bottom , Unit y Option como intentos de justificar los NULL de SQL, estaré convencido solo después de un examen bastante detallado que mostrará cómo las implementaciones de SQL con NULL tienen un sistema de tipos sólido y aclarará, finalmente, qué son realmente los NULL (estos "valores-no-del todo-valores").
A continuación citaré algunos autores. Cualquier error u omisión probablemente sea mío y no de los autores originales.
Joe Celko sobre SQL NULL
Veo que Joe Celko se cita a menudo en este foro. Al parecer 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 los NULL?". Uno de mis amigos tiene una versión de libro electrónico del SQL de Joe Celko para sabelotodos: programación SQL avanzada, tercera edición . Vamos a ver.
Primero, el índice. Lo que más me llama la atención es la cantidad de veces que se menciona NULL y en los más variados contextos:
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 NULL en predicados de subconsulta 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 y lenguajes host 194
6.9 Consejos de diseño para NULL 195
6.9.1 Evitar NULL de los programas host 197
6.10 Una nota sobre múltiples valores NULL 198
10.1 Predicado IS NULL 241
10.1. 1 Fuentes de NULL 242
...
etcétera. Me suena a "caso especial desagradable".
Abordaré algunos de estos casos con extractos de este libro, intentando limitarme a lo esencial, por razones de derechos de autor. Creo que estas citas entran dentro de la doctrina del "uso legítimo" e incluso pueden estimular a comprar el libro, así que espero que nadie se queje (de lo contrario, tendré que eliminar la mayor parte, si no todo). Además, me abstendré de informar fragmentos de código por el mismo motivo. Lo lamento. Compre el libro para leer sobre el razonamiento basado en datos.
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. Utilice esta restricción de forma rutinaria y elimínela sólo cuando tenga una buena razón. Le ayudará a evitar las complicaciones de los valores NULL cuando realice consultas sobre los datos.
No es un valor ; es un marcador que mantiene un lugar donde podría ir un valor.
De nuevo esta tontería de "valor pero no exactamente valor". El resto me parece bastante sensato.
(12)
En resumen, los NULL causan muchas características irregulares en SQL, que discutiremos más adelante. Lo mejor que puede hacer es simplemente memorizar las situaciones y las reglas para los NULL cuando no pueda evitarlos.
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 matemáticas de IEEE estuvieran permitidas en SQL, entonces necesitaríamos reglas de conversión de tipos para infinito y una forma de representar un valor numérico exacto infinito después de la conversión. La gente ya tiene suficientes problemas con los NULL, así que no entremos en eso.
Implementaciones de SQL indecisas sobre lo que realmente significa 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, otras devuelven 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 Date:
6 NULL: datos faltantes en SQL (185)
En su libro Una guía para Sybase y SQL Server , David McGoveran y CJ Date dijeron: “En opinión de este escritor, los NULL, al menos tal como se definen e implementan actualmente en SQL, son mucho más problemáticos 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, le instaré a que no los utilice , lo que puede parecer contradictorio, pero no lo es. Piense en un NULL como una droga; úsalo correctamente y funcionará para ti, pero abusa de él y puede arruinarlo todo. Su mejor política es evitar los NULL cuando pueda y utilizarlos correctamente cuando sea necesario.
Mi única objeción aquí es "usarlos correctamente", lo que interactúa mal con comportamientos de implementación específicos.
6.5.1 NULLS 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 contradictorio , 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) agregando un nuevo predicado de la forma:
<condición de búsqueda> [NO] ES 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 utilice la palabra clave DESCONOCIDO en ningún contexto.
Lea "APARTE" en DESCONOCIDO, también vinculado a continuación.
6.8 NULL y lenguajes de host (194)
Sin embargo, debe saber cómo se manejan los NULL cuando deben pasarse a un programa host. Ningún lenguaje host estándar para el cual se define una incrustación admite NULL, lo cual 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 son caros.
Objeción: los valores NULL confunden incluso a las personas que conocen bien SQL, ver más abajo.
(195)
Se deben evitar los NULL en las CLAVEES EXTRANJERAS. SQL permite esta relación de "beneficio de la duda", pero puede provocar 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 CLAVE EXTRANJERA, tendrá problemas para obtener una lista de las piezas que tienen un valor NULL. Esta es una relación obligatoria; No se puede pedir una pieza que no existe.
(separador)
6.9.1 Evitar valores NULL de los programas host (197)
Puede evitar colocar valores NULL en la base de datos desde los programas host con cierta disciplina de programación.
...
- Determinar el impacto de los datos faltantes en la programación y los informes: las columnas numéricas con valores NULL son un problema, porque las consultas que utilizan funciones agregadas pueden proporcionar resultados engañosos.
(separador)
(227)
La SUM() de un conjunto vacío es siempre NULL. Uno de los errores de programación más comunes que se cometen al utilizar este truco es escribir una consulta que podría devolver más de una fila. Si no lo pensaste, es posible que hayas escrito el último ejemplo como: ...
(separador)
10.1.1 Fuentes de NULL (242)
Es importante recordar dónde pueden ocurrir los NULL. Son más que simplemente un 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 las VISTAS.
(separador)
(301)
Otro problema con los NULL se encuentra cuando se intenta convertir predicados IN en predicados EXISTS.
(separador)
16.3 TODAS las funciones predicadas y extremas (313)
Al principio resulta contradictorio que estos dos predicados no sean iguales en SQL:
...
Pero hay que recordar las reglas para las funciones extremas: eliminan todos los NULL antes de devolver los valores mayores o menores. El predicado ALL no descarta NULL, por lo que puede obtenerlos en los resultados.
(separador)
(315)
Sin embargo, la definición del estándar está redactada en negativo, por lo que los NULL obtienen el beneficio de la duda. ...
Como puede ver, es una buena idea evitar NULL en restricciones UNIQUE.
Discutiendo GRUPO POR:
Los NULL se tratan como si fueran todos iguales entre sí y forman su propio grupo. Luego, 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 NULL (329)
Si un valor de clave de clasificación que es NULL se considera mayor o menor que un valor que no es 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 llevó a examinar una parte del estándar SQL que creía entender . Chris encontró algunas diferencias entre la comprensión general y la redacción real de la especificación .
Etcétera. Creo que es suficiente con Celko.
C. J. Date on SQL NULLs
C. J. Date is more radical about NULLs: avoid NULLs in SQL, period. In fact, chapter 4 of his SQL and Relational Theory: How to Write Accurate SQL Code is titled "NO DUPLICATES, NO NULLS", with subchapters "4.4 What's Wrong with Nulls?" and "4.5 Avoiding Nulls in SQL" (follow the link: thanks to Google Books, you can read some pages on-line).
Fabian Pascal on SQL NULLs
From its Practical Issues in Database Management - A Reference for the Thinking Practitioner (no excerpts on-line, sorry):
10.3 Pratical Implications
10.3.1 SQL NULLs
... SQL suffers from the problems inherent in 3VL as well as from many quirks, complications, counterintuitiveness, and outright errors [10, 11]; among them are the following:
- Aggregate functions (e.g., SUM(), AVG()) ignore NULLs (except for COUNT()).
- A scalar expression on a table without rows evaluates incorrectly to NULL, instead of 0.
- The expression "NULL = NULL" evaluates to NULL, but is actually invalid in SQL; yet ORDER BY treats NULLs as equal (whatever they precede or follow "regular" values is left to DBMS vendor).
- The expression "x IS NOT NULL" is not equal to "NOT(x IS NULL)", as is the case in 2VL.
...
All commercially implemented SQL dialects follow this 3VL approach, and, thus, not only do they exibits these problems, but they also have spefic implementation problems, which vary across products.