NULL-Wert Selbstvergleich in einer Tabelle

13

Ich bin immer verwirrt über ein mysteriöses T-SQL-Verhalten wie das folgende

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

Hierbei geht es nicht darum, wie alle Zeilen in einer Tabelle abgerufen werden, und auch nicht darum, die Verwendung von ANSI_NULLS zu vermeiden.

Ich möchte nur einige Einblicke gewinnen, warum sich t-sql so verhält.

jyao
quelle

Antworten:

13

Dies ist ein überraschendes Verhalten, aber von der MSDN-Seite können SET ANSI_NULLSwir zumindest wissen, dass dies das erwartete Verhalten ist. Ein Grund mehr, niemals zu benutzen ANSI_NULLS OFF:

SET ANSI_NULLSwirkt sich nur dann auf einen Vergleich aus, wenn einer der Operanden des Vergleichs entweder eine Variable NULLoder ein Literal ist NULL. Wenn beide Seiten des Vergleichs Spalten oder zusammengesetzte Ausdrücke sind, hat die Einstellung keine Auswirkungen auf den Vergleich.

ypercubeᵀᴹ
quelle
8

Obwohl es aus der MSDN-Dokumentation nicht ganz klar hervorgeht, glaube ich, dass Sie Folgendes für richtig halten werden

"SET ANSI_NULLS ON wirkt sich nur auf einen Vergleich aus, wenn einer der Operanden des Vergleichs entweder eine Variable mit dem Wert NULL oder ein Literal mit dem Wert NULL ist. Wenn beide Seiten des Vergleichs Spalten oder zusammengesetzte Ausdrücke sind, wirkt sich die Einstellung nicht auf den Vergleich aus."

Siehe hierzu /programming/2866714/how-does-ansi-nulls-work-in-tsql

Scott Hodgin
quelle
Vielen Dank an Scott und ypercube, beide Antworten stimmen mit diesem Verhalten überein. Ich habe beide Antworten positiv bewertet.
Jyao
Ypercube war zuerst :)
Scott Hodgin
4

Robert Sheldon im folgenden Beitrag aus dem Jahr 2015 erläutert NULL-Verhalten und warum sie manchmal (aber nicht immer) fehlschlagen

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

Er beschreibt 13 NULL-Fehler, über die ein Programmierer leicht stolpern kann.

Fehler Nr. 1: Keine Ahnung, was NULL bedeutet

Erläuterung: NULL ist ein nicht vorhandener Wert. Es ist nicht Null. Es ist keine leere Zeichenfolge. Ein Wert kann nicht gleich NULL sein. Keine zwei NULL-Werte sind gleich .

Das ist das Grundproblem, aber lesen Sie auch die anderen Fehler.

Ja, frühere Versionen (Pre-SQL Server 7, glaube ich) haben sich anders verhalten, eher so, wie Sie es sich wünschen.

Wenn Sie jedoch nach dem Problem in Stack Overflow und Stack Exchange suchen, finden Sie viele lange Threads, in denen die Probleme behandelt werden.

RLF
quelle
3
Ich habe einmal den verlinkten Beitrag von Robert Sheldon gelesen, aber es gibt (IMHO) keine Theorie oder Beweise, die das Verhalten meines Beispiels erklären.
Jyao
1
Msgstr "Keine zwei NULL - Werte sind gleich." OK, aber auch die Leute, die wissen, dass das Gegenteil zu erwarten wäre, wenn ansi nulls ausgeschaltet ist. Vor allem, weil WHERE NULL = NULLsich bei der Einstellung von true ergibt.
Ypercubeᵀᴹ
1

Um die Diskussion zu erweitern, kann die Definition von NULL des SQL92- Standards mehrdeutig interpretiert werden. Hier ist eine gute Zusammenfassung der NULL-Behandlung und -Interpretation von verschiedenen DBMS mit freundlicher Genehmigung von sqlite.org.

OFFENLEGUNG : Ich erinnere mich, dass ich etwas über die "Mehrdeutigkeit" von SQL92 aus einer älteren Version (wie vor 6-8 Jahren) der oben verlinkten sqlite.org-Seite gelesen habe, aber diese Seite wurde seitdem aktualisiert.

Die obige Antwort von RLF hat ein gutes Zitat, aber wenn ich mit Robert Sheldon nicht einverstanden bin, dann nur, weil ich "etwas, das nicht existiert" (dh eine NULL ) als philosophisch und englischsprachig-semantisch äquivalent zu "etwas anderem , das nicht existiert" betrachte ". Wenn ich Sheldons Logik verstehen will, könnte man erklären, dass die Definition von NULL auch NULL ist. (Wenn es nicht existiert, wie können wir es dann definieren? Gruselig, oder?)

Ich sehe eine Variation von Russells Paradox- Brauen ( und Kopfschmerzen). : - \

Aber auch dies ist eine Diskussion über die englische Sprachsemantik ( NICHT SQL) und die philosophische Debatte gehört hierher . :-)

pr1268
quelle
PS: Ich bin neu in dieser SE-Community. Wenn dies bereits ad nauseum besprochen wurde , entschuldige ich mich.
Pr1268
1
Wo genau liegt die Mehrdeutigkeit in der Norm?
Ypercubeᵀᴹ
@ ypercubeᵀᴹ: Ich glaube, die Mehrdeutigkeit lag im Versuch, eine 3VL in einen Booleschen Wert zu "passen" . Tabellenverknüpfungen mit NULL-Vergleichen können auf verschiedene Arten interpretiert werden.
PR1268,
In Bezug auf Inkonsistenz würde ich zustimmen, nicht aber in Bezug auf Mehrdeutigkeit.
ypercubeᵀᴹ
1
@ ypercubeᵀᴹ: Fair genug ... Ich habe nur eine ältere Version der sqlite.org-Seite zitiert, die ich oben verlinkt habe ("SQL92 ist in Bezug auf NULL-Behandlung und Interpretation mehrdeutig" oder etwas sehr Ähnliches). Aber ich will nicht streiten. Vielleicht war die sqlite.org-Seite selbst irreführend und / oder durch und durch falsch. Was wahrscheinlich erklärt, warum es aktualisiert wurde.
pr1268