Auto-comparaison de valeur NULL dans une table


13

Je suis toujours perplexe concernant un comportement mystérieux de T-sql, comme le suivant

-- Create table t and insert values.  
use tempdb
CREATE TABLE dbo.t (a INT NULL);  
-- insert 3 values
INSERT INTO dbo.t values (NULL),(0),(1);  
GO  
set ansi_nulls off -- purposely turn off, so we can allow NULL comparison, such as null = null
go
-- expect 3 rows returned but only 2 returned (without null value row)
select * from dbo.t where a = a 

Il ne s'agit pas de récupérer toutes les lignes d'une table et pas non plus d'éviter d'utiliser ANSI_NULLS.

Je veux juste demander quelques éclaircissements pourquoi t-sql se comporte comme ça.

Réponses:


13

C'est un comportement surprenant mais à partir de la page MSDN SET ANSI_NULLS, nous pouvons au moins savoir que c'est le comportement attendu. Une raison de plus pour ne jamais utiliser ANSI_NULLS OFF:

SET ANSI_NULLSaffecte une comparaison uniquement si l'un des opérandes de la comparaison est une variable qui est NULLou un littéral NULL. Si les deux côtés de la comparaison sont des colonnes ou des expressions composées, le paramètre n'affecte pas la comparaison.


8

Bien que cela ne soit pas clair dans la documentation msdn, je pense que vous trouverez ce qui suit vrai

"SET ANSI_NULLS ON n'affecte une comparaison que si l'un des opérandes de la comparaison est soit une variable NULL soit un NULL littéral. Si les deux côtés de la comparaison sont des colonnes ou des expressions composées, le paramètre n'affecte pas la comparaison."

Voir ce /programming/2866714/how-does-ansi-nulls-work-in-tsql


Merci Scott et ypercube, vos réponses sont toutes les deux à la hauteur de ce comportement, donc je vote pour vos deux réponses.
jyao

Ypercube était le premier :)
Scott Hodgin

4

Robert Sheldon dans l'article suivant de 2015 discute des comportements NULL et pourquoi ils échouent parfois (mais pas toujours)

https://www.simple-talk.com/sql/t-sql-programming/how-to-get-nulls-horribly-wrong-in-sql-server/

Il décrit 13 échecs NULL qu'un programmeur peut facilement déclencher.

Échec # 1: ne pas savoir ce que signifie NULL

Explication: NULL est une non-valeur, une valeur inexistante. Ce n'est pas zéro. Ce n'est pas une chaîne vide. Une valeur ne peut pas être égale à NULL. Il n'y a pas deux valeurs NULL égales .

C'est le problème de base, mais assurez-vous de lire les autres échecs.

Oui, les versions antérieures (pré-SQL Server 7 je crois) se comportaient différemment, plus comme ce que vous vouliez.

Cependant, si vous recherchez le problème sur Stack Overflow et Stack Exchange, vous trouverez de nombreux longs fils de discussion sur les problèmes.


3
J'ai lu une fois le message lié de Robert Sheldon, mais il (à mon humble avis) n'a aucune théorie ou preuve qui explique le comportement de mon exemple.
jyao

1
"Il n'y a pas deux valeurs NULL égales." D'accord, mais même les gens qui le savent s'attendraient à l'inverse lorsque ansi nulls est désactivé. Surtout parce que WHERE NULL = NULLdonne vrai lorsque le réglage est sur.
ypercubeᵀᴹ

1

Pour ajouter à la discussion, la définition de la norme SQL92 de NULL peut être interprétée de manière ambiguë. Voici un bon résumé de la gestion NULL et de l'interprétation de divers SGBD avec l'aimable autorisation de sqlite.org.

DIVULGATION : Je me souviens un peu d'avoir lu sur "l'ambiguïté" de SQL92 à partir d'une ancienne version (comme 6-8 ans) de la page sqlite.org liée ci-dessus, mais cette page a été mise à jour depuis.

La réponse de RLF ci-dessus a une bonne citation, mais si je ne suis pas d'accord avec Robert Sheldon, c'est uniquement parce que je considère que "quelque chose qui n'existe pas" (c'est-à-dire un NULL ) est philosophiquement et sémantiquement équivalent à "quelque chose d' autre qui n'existe pas". ". Si je veux comprendre la logique de Sheldon, alors on pourrait déclarer que la définition de NULL est également NULL. (S'il n'existe pas, comment pouvons-nous le définir? Creepy, hein?)

Je vois une variation du brassage Paradox de Russell ( et un mal de tête). : - \

Mais encore une fois, il s'agit d'une discussion sur la sémantique de la langue anglaise ( PAS SQL) et le débat sur la philosophie appartient ici . :-)


PS Je suis nouveau ici dans cette communauté SE; si cela a déjà été discuté ad nauseum , je m'en excuse.
pr1268

1
Où est exactement l'ambiguïté de la norme?
ypercubeᵀᴹ

@ ypercubeᵀᴹ: Je pense que l'ambiguïté résidait dans la tentative de "faire entrer" un 3VL dans un booléen. Les jointures de table avec des comparaisons NULL peuvent être interprétées de plusieurs manières différentes.
pr1268

Je serais d'accord sur l'incohérence mais pas sur l'ambiguïté.
ypercubeᵀᴹ

1
@ ypercubeᵀᴹ: Très bien ... Je ne faisais que citer ce qu'une ancienne version de la page sqlite.org que j'ai liée ci-dessus disait ("SQL92 est ambigu en ce qui concerne la gestion et l'interprétation NULL" ou quelque chose de très similaire). Mais je ne veux pas discuter. Peut-être que la page sqlite.org était elle-même trompeuse et / ou complètement incorrecte. Ce qui explique probablement pourquoi il a été mis à jour.
pr1268
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.