Warum wird NULL = NULL in SQL Server als falsch ausgewertet?

146

Wenn Sie nullParam=NULLin SQL Server eine where-Klausel haben, wird diese immer als false ausgewertet. Dies ist nicht intuitiv und hat mir viele Fehler verursacht. Ich verstehe die IS NULLund IS NOT NULLSchlüsselwörter sind der richtige Weg, um es zu tun. Aber warum verhält sich SQL Server so?

Byron Whitlock
quelle
166
Ich habe keine Schwester und mein Freund auch nicht. Wenn "NULL = NULL", dann haben wir eine gemeinsame Schwester und sind daher verwandt! :)
Matt Hamilton
11
Es gibt eine lange Kontroverse über SQL-NULL-Werte (siehe zum Beispiel: en.wikipedia.org/wiki/Null_%28SQL%29#Controversy und firstsql.com/inulls.htm ). Der spezifische Punkt hier ist, dass Gleichheit ein seit langem etabliertes mathematisches Konzept ist und SQL es verletzt - Gleichheit ist reflexiv: Für jedes x ist x = x. Das muss immer wahr sein, sonst führt man eine Interpretation der Gleichheit ein, die nicht Standard ist und Verwirrung ist das offensichtliche Ergebnis.
MaD70
14
Es verstößt überhaupt nicht gegen die Mathematik. Ich denke an zwei Zahlen. Ich werde dir aber nicht sagen, was sie sind. Jetzt sagst du mir, sind sie gleich?
Tom H
10
@ Matt, ich stimme deiner Analogie nicht zu. NULL = NULL würde nicht bedeuten, dass Sie eine gemeinsame Schwester haben, es würde bedeuten, dass Ihnen beiden eine Schwester fehlt.
reustmd
5
@ manu08 Nein, die aktuelle Implementierung (dass NULL niemals gleich NULL ist) bedeutet, dass wir beide keine Schwester haben, was mein Punkt war.
Matt Hamilton

Antworten:

205

Stellen Sie sich die Null in diesem Fall als "unbekannt" vor (oder "existiert nicht"). In beiden Fällen können Sie nicht sagen, dass sie gleich sind, da Sie den Wert von beiden nicht kennen. Null = null wird also als nicht wahr ausgewertet (falsch oder null, abhängig von Ihrem System), da Sie die Werte nicht kennen, um zu sagen, dass sie gleich sind. Dieses Verhalten ist im ANSI SQL-92-Standard definiert.

BEARBEITEN: Dies hängt von Ihrer ansi_nulls- Einstellung ab. Wenn Sie ANSI_NULLS deaktiviert haben, wird dies als wahr ausgewertet. Führen Sie den folgenden Code für ein Beispiel aus ...

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
quelle
11
x = x gilt nur, wenn x ein bekannter Wert ist. NULL ist eine Textdarstellung eines unbekannten Werts. Wenn Sie zwei unbekannte Werte haben, können Sie nichts über deren Gleichheit abschließend sagen. Ich glaube, dass dies auch für einige Jahrhunderte gilt.
Dewayne Christensen
4
Da es Dezember ist, verwenden wir ein saisonales Beispiel. Ich habe zwei Geschenke unter dem Baum. Jetzt sagst du mir, ob ich zwei davon habe oder nicht.
Dewayne Christensen
5
SQL NULL unterscheidet sich nicht von IEEE-Gleitkomma-NaN, wo Sie auch haben (NaN == NaN) == false && (NaN != Nan) == false && (NaN < NaN) == false && ...- denn wenn es keine Zahl ist, können Sie einfach nicht viel darüber sagen. Es ist etwas Unbekanntes. Das Konzept ist solide, auch wenn es für Menschen, die es noch nie gesehen haben, nicht intuitiv ist.
Pavel Minaev
8
Hier liegt keine Verletzung der Reflexivität vor, da NULL kein Mitglied der Wertemenge ist (Domäne, relational ausgedrückt). NULL ist kein Wert . Es ist ein Platzhalter für den unbekannten Wert.
Pavel Minaev
9
Mit anderen Worten, jeder NULLin einem SQL-Ausdruck kann als eigenständige mathematische Variable behandelt werden. Ein Ausdruck NULL = NULLsollte also als x = y, wo xund yungebundene Variablen behandelt werden. Wenn dich jemand fragt, welchen Wert hat das x = y? Die einzig vernünftige Antwort ist "einige z". Also haben wir (x = y) = z- oder, es zurück in SQL zu transkribieren , (NULL = NULL) = NULL.
Pavel Minaev
130

Wie alt ist Frank? Ich weiß nicht (null).

Wie alt ist Shirley? Ich weiß nicht (null).

Sind Frank und Shirley gleich alt?

Die richtige Antwort sollte "Ich weiß nicht" (null) sein, nicht "nein", da Frank und Shirley vielleicht gleich alt sind, wir wissen es einfach nicht.

Neil McGuigan
quelle
4
Ich bin nicht der Meinung, dass null "unbekannt" bedeutet. Was es eigentlich bedeutet, ist "keine Daten". Dies kann verwendet werden, um den Fall darzustellen, in dem Informationen nicht bekannt sind, aber es wird tatsächlich eher verwendet, um anzuzeigen, dass etwas nicht existiert. Um Ihr Beispiel fortzusetzen: Wie lautet Franks zweiter Vorname? Er hat keine (null). Was ist Shirleys zweiter Vorname? Sie hat keine (null). Haben Frank und Shirley den gleichen zweiten Vornamen? Ja? Nein? Weiß nicht? Ich kann ein Argument für "Nein" sehen, und ich kann ein Argument für "Weiß nicht" sehen, aber es gibt kein wirkliches Argument für "Ja", es sei denn, Sie sind zu wörtlich.
Richiban
2
@richiban Ich bin anderer Meinung. Das Fehlen einer Zeile bedeutet "keine Daten"
Neil McGuigan
1
@NeilMcGuigan Das stimmt, wenn für Daten, die eine eigene Tabelle haben, aber was ist mit Daten, die in einer Spalte dargestellt werden? Würden Sie nicht 'null' verwenden, um die Tatsache darzustellen, dass die Daten nicht existieren? "Nicht bekannt" ist ein ganz bestimmter Grund für das Fehlen der Daten.
Richiban
3
Aber null = nullRenditen FALSEnicht NULL.
Slartidan
1
@ Slartidan Ich stimme Ihnen zu, aber das ist falsch
Neil McGuigan
28

Hier werde ich hoffentlich meine Position klarstellen.

Das zu NULL = NULLbewerten FALSEist falsch. Hacker und Mister haben richtig geantwortet NULL. Hier ist warum. Dewayne Christensen schrieb mir in einem Kommentar an Scott Ivey :

Da es Dezember ist, verwenden wir ein saisonales Beispiel. Ich habe zwei Geschenke unter dem Baum. Jetzt sagst du mir, ob ich zwei davon habe oder nicht.

Sie können unterschiedlich oder gleich sein, man weiß es nicht, bis man beide Geschenke öffnet. Wer weiß? Sie lud zwei Menschen, die einander nicht kennen und beide haben Sie das gleiche Geschenk gemacht - selten, aber nicht unmöglich § .

Die Frage: Sind diese beiden UNBEKANNTEN gleich (gleich, =)? Die richtige Antwort lautet: UNBEKANNT (dhNULL ).

Dieses Beispiel sollte zeigen, dass ".. ( falseoder null, abhängig von Ihrem System) .." eine richtige Antwort ist - es ist nicht nur NULL in 3VL richtig (oder ist es in Ordnung, ein System zu akzeptieren, das falsche Antworten gibt? )

Eine richtige Antwort auf diese Frage muss diese beiden Punkte hervorheben:

  • Drei-Werte-Logik (3VL) ist nicht intuitiv (siehe unzählige andere Fragen zu diesem Thema auf Stackoverflow und in anderen Foren, um sicherzugehen);
  • SQL-basierte DBMS respektieren häufig nicht einmal 3VL, sie geben manchmal falsche Antworten (wie das ursprüngliche Poster behauptet, SQL Server in diesem Fall).

Also wiederhole ich: SQL zwingt nicht dazu, die reflexive Eigenschaft der Gleichheit zu interpretieren, die besagt, dass:

for any x, x = x §§ (im Klartext: Unabhängig vom Universum des Diskurses ist ein "Ding" immer gleich sich selbst ).

.. in einem 3VL ( TRUE, FALSE, NULL). Die Erwartung der Menschen 2VL entsprechen würde ( TRUE, FALSE, die auch in SQL gilt für alle anderen Werte), dh x = x bewerten immer TRUE , für jeden möglichen Wert von x - ohne Ausnahme.

Beachten Sie auch, dass NULL -Werte gültige Nichtwerte sind " sind (wie ihre Apologeten dies vorgeben), die man als Attributwerte (??) als Teil von Beziehungsvariablen zuweisen kann. Sie sind also akzeptable Werte für jeden Typ (Domäne), nicht nur für den Typ der logischen Ausdrücke.

Und das war mein Punkt : NULLAls Wert ist es ein "seltsames Tier". Ohne Euphemismus sage ich lieber: Unsinn .

Ich denke, dass diese Formulierung viel klarer und weniger umstritten ist - entschuldigen Sie meine schlechten Englischkenntnisse.

Dies ist nur eines der Probleme von NULL. Vermeiden Sie sie nach Möglichkeit besser.

§ Wir sind hier besorgt über Werte , daher ist die Tatsache, dass die beiden Geschenke immer zwei verschiedene physische Objekte sind, kein gültiger Einwand. Wenn Sie nicht überzeugt sind, dass es mir leid tut, ist dies nicht der richtige Ort, um den Unterschied zwischen Wert- und "Objekt" -Semantik zu erklären (Relationale Algebra hat von Anfang an Wertesemantik - siehe Codds Informationsprinzip; ich denke, dass einige SQL DBMS-Implementierer dies nicht tun kümmert sich nicht einmal um eine gemeinsame Semantik).

§§ Meines Wissens ist dies ein Axiom, das seit der Antike akzeptiert wurde (in der einen oder anderen Form, aber immer in einer 2VL interpretiert), und das genau deshalb , weil es so intuitiv ist. 3VLs (ist in Wirklichkeit eine Familie von Logik) ist eine viel neuere Entwicklung (aber ich bin mir nicht sicher, wann sie zum ersten Mal entwickelt wurde).

Randbemerkung: wenn jemand vorstellen Bottom , Einheit und Optionstypen als Versuche SQL NULL - Werte zu rechtfertigen, werde ich erst nach einer sehr detaillierten Prüfung überzeugt sein , das wird zeigt, wie SQL - Implementierungen mit NULL - Werten ein Sound - Typ - System und können klären, schließlich, Was sind NULL-Werte (diese "Werte-nicht-ganz-Werte") wirklich?


Im Folgenden werde ich einige Autoren zitieren. Jeder Fehler oder jede Auslassung stammt wahrscheinlich von mir und nicht von den ursprünglichen Autoren.

Joe Celko über SQL NULLs

Ich sehe Joe Celko oft in diesem Forum zitiert. Anscheinend ist er hier ein sehr angesehener Autor. Also sagte ich mir: "Was hat er über SQL NULLs geschrieben? Wie erklärt er NULLs zahlreiche Probleme?". Einer meiner Freunde hat eine E-Book-Version von Joe Celkos SQL für Smarties: Advanced SQL Programming, 3. Ausgabe . Mal schauen.

Zunächst das Inhaltsverzeichnis. Was mir am meisten auffällt, ist die Häufigkeit, mit der NULL erwähnt wird, und in den unterschiedlichsten Kontexten:

3.4 Arithmetik und NULL-
Werte 109 3.5 Konvertieren von Werten in und von NULL 110
3.5.1 NULLIF () -Funktion 110
6 NULL-Werte: Fehlende Daten in SQL 185
6.4 Vergleichen von NULL- Werten 190
6.5 NULL-Werten und Logik 190
6.5.1 NULL-Werten in Unterabfrage-Prädikaten 191
6.5.2 Standard SQL-Lösungen 193
6.6 Mathematik und NULL-Werte 193
6.7 Funktionen und NULL-Werte 193
6.8 NULL-Werte und Host-Sprachen 194
6.9 Entwurfsempfehlung für NULL-Werte 195
6.9.1 Vermeiden von
NULL-Werten in den Host-Programmen 197 6.10 Hinweis zu mehreren NULL-Werten 198
10.1 IS NULL-Prädikat 241
10.1. 1 NULL-Quellen 242
...

und so weiter. Es klingelt für mich "böser Sonderfall".

Ich werde auf einige dieser Fälle mit Auszügen aus diesem Buch eingehen und versuchen, mich aus urheberrechtlichen Gründen auf das Wesentliche zu beschränken. Ich denke, diese Zitate fallen unter die "Fair Use" -Doktrin und können sogar zum Kauf des Buches anregen - daher hoffe ich, dass sich niemand beschweren wird (andernfalls muss ich das meiste, wenn nicht alle, löschen). Darüber hinaus werde ich aus demselben Grund keine Code-Schnipsel melden. Das tut mir leid. Kaufen Sie das Buch, um mehr über datengesteuertes Denken zu erfahren.

Seitenzahlen in Klammern im Folgenden.

NICHT NULL Einschränkung (11)

Die wichtigste Spaltenbeschränkung ist NOT NULL, wodurch die Verwendung von NULL in einer Spalte verboten wird. Verwenden Sie diese Einschränkung routinemäßig und entfernen Sie sie nur, wenn Sie einen guten Grund haben. Dies hilft Ihnen, die Komplikationen von NULL-Werten zu vermeiden , wenn Sie Abfragen zu den Daten durchführen.

Es ist kein Wert ; Es ist eine Markierung, die eine Stelle enthält, an die ein Wert gehen könnte.

Wieder dieser "Wert aber nicht ganz ein Wert" Unsinn. Der Rest scheint mir ziemlich vernünftig.

(12)

Kurz gesagt, NULL-Werte verursachen in SQL viele unregelmäßige Funktionen, auf die wir später noch eingehen werden. Ihre beste Wette ist es, sich die Situationen und Regeln für NULL-Werte zu merken, wenn Sie sie nicht vermeiden können.

Apropos von SQL, NULLs und unendlich:

(104) KAPITEL 3: NUMERISCHE DATEN IN SQL

SQL hat das IEEE-Modell für Mathematik aus mehreren Gründen nicht akzeptiert.

...

Wenn die IEEE-Regeln für Mathematik in SQL zulässig wären, würden wir Typkonvertierungsregeln für unendlich und eine Möglichkeit benötigen, einen unendlich exakten numerischen Wert nach der Konvertierung darzustellen. Die Leute haben genug Probleme mit NULL, also lasst uns nicht dorthin gehen.

SQL-Implementierungen haben nicht entschieden, was NULL in bestimmten Kontexten wirklich bedeutet:

3.6.2 Exponentialfunktionen (116)

Das Problem ist, dass Logarithmen undefiniert sind, wenn (x <= 0). Einige SQL-Implementierungen geben eine Fehlermeldung zurück, andere NULL und DB2 / 400. Version 3, Version 1, gab als Ergebnis * NEGINF (kurz für „negative Infinity“) zurück.

Joe Celko zitiert David McGoveran und CJ Datum:

6 NULL: Fehlende Daten in SQL (185)

In ihrem Buch A Guide to Sybase und SQL Server sagten David McGoveran und CJ Date: „Nach Ansicht dieses Autors sind NULL-Werte, zumindest wie sie derzeit in SQL definiert und implementiert sind, weitaus schwieriger als sie es wert sind und vermieden werden sollten. Sie zeigen ein sehr seltsames und inkonsistentes Verhalten und können eine reichhaltige Quelle für Fehler und Verwirrung sein. (Bitte beachten Sie, dass diese Kommentare und Kritikpunkte für jedes System gelten, das SQL-artige NULL-Werte unterstützt, nicht nur für SQL Server.) ”

NULL als Drogenabhängigkeit :

(186/187)

Im Rest dieses Buches werde ich Sie auffordern, sie nicht zu verwenden , was widersprüchlich erscheinen mag, aber nicht. Stellen Sie sich einen NULL als Droge vor. Verwenden Sie es richtig und es funktioniert für Sie, aber missbrauchen Sie es und es kann alles ruinieren. Ihre beste Richtlinie ist es, NULL-Werte zu vermeiden, wenn Sie können, und sie ordnungsgemäß zu verwenden, wenn Sie müssen.

Mein einzigartiger Einwand hier ist, "sie richtig zu verwenden", was schlecht mit bestimmten Implementierungsverhalten interagiert.

6.5.1 NULL in Unterabfrageprädikaten (191/192)

Die Leute vergessen, dass eine Unterabfrage oft einen Vergleich mit einem NULL verbirgt. Betrachten Sie diese beiden Tabellen:

...

Das Ergebnis ist leer. Dies ist nicht intuitiv , aber richtig.

(Separator)

6.5.2 Standard-SQL-Lösungen (193)

SQL-92 löste einige der 3VL-Probleme (dreiwertige Logik) durch Hinzufügen eines neuen Prädikats der Form:

<Suchbedingung> IST [NICHT] WAHR | FALSE | UNBEKANNT

UNBEKANNT ist jedoch eine Quelle von Problemen an sich, so dass CJ Date in seinem unten zitierten Buch in Kapitel 4.5 empfiehlt . Vermeiden von Nullen in SQL :

  • Verwenden Sie das Schlüsselwort UNKNOWN in keinem Kontext.

Lesen Sie "ASIDE" auf UNKNOWN, ebenfalls unten verlinkt.

6.8 NULL-Werte und Host-Sprachen (194)

Sie sollten jedoch wissen, wie NULL-Werte behandelt werden, wenn sie an ein Host-Programm übergeben werden müssen. Keine Standardhostsprache, für die eine Einbettung definiert ist, unterstützt NULL-Werte. Dies ist ein weiterer guter Grund, diese nicht in Ihrem Datenbankschema zu verwenden.

(Separator)

6.9 Entwurfsempfehlung für NULL (195)

Es ist eine gute Idee, wenn möglich, alle Basistabellen mit NOT NULL-Einschränkungen für alle Spalten zu deklarieren. NULL-Werte verwirren Leute, die SQL nicht kennen, und NULL-Werte sind teuer.

Einwand: NULL verwirrt auch Leute, die SQL gut kennen, siehe unten.

(195)

NULL-Werte sollten in AUSLÄNDISCHEN SCHLÜSSELN vermieden werden. SQL ermöglicht diese Beziehung "Vorteil des Zweifels", kann jedoch zu einem Informationsverlust bei Abfragen führen, die Verknüpfungen betreffen. Wenn Sie beispielsweise einen Teilenummerncode im Inventar angeben, der von einer Auftragstabelle als AUSLÄNDISCHER SCHLÜSSEL bezeichnet wird, haben Sie Probleme, eine Liste der Teile mit NULL zu erhalten. Dies ist eine obligatorische Beziehung; Sie können kein nicht bestehendes Teil bestellen.

(Separator)

6.9.1 Vermeiden von NULL-Werten aus den Host-Programmen (197)

Mit etwas Programmierdisziplin können Sie vermeiden, NULL-Werte aus den Host-Programmen in die Datenbank aufzunehmen.

...

  1. Bestimmen der Auswirkung fehlender Daten auf Programmierung und Berichterstellung: Numerische Spalten mit NULL-Werten sind ein Problem, da Abfragen mit Aggregatfunktionen irreführende Ergebnisse liefern können.

(Separator)

(227)

Die Summe () einer leeren Menge ist immer NULL. Einer der häufigsten Programmierfehler bei Verwendung dieses Tricks ist das Schreiben einer Abfrage, die mehr als eine Zeile zurückgeben kann. Wenn Sie nicht darüber nachgedacht haben, haben Sie vielleicht das letzte Beispiel geschrieben als: ...

(Separator)

10.1.1 NULL-Quellen (242)

Es ist wichtig, sich daran zu erinnern, wo NULL-Werte auftreten können. Sie sind mehr als nur ein möglicher Wert in einer Spalte . Aggregatfunktionen für leere Mengen, OUTER JOINs, arithmetische Ausdrücke mit NULL-Werten und OLAP-Operatoren geben alle NULL-Werte zurück. Diese Konstrukte werden in VIEWs häufig als Spalten angezeigt.

(Separator)

(301)

Ein weiteres Problem mit NULL-Werten tritt auf, wenn Sie versuchen, IN-Prädikate in EXISTS-Prädikate zu konvertieren.

(Separator)

16.3 Die ALL-Prädikat- und Extrema-Funktionen (313)

Es ist zunächst nicht intuitiv, dass diese beiden Prädikate in SQL nicht identisch sind:

...

Sie müssen sich jedoch die Regeln für die Extrema-Funktionen merken - sie löschen alle NULL-Werte, bevor die größeren oder kleinsten Werte zurückgegeben werden. Das ALL-Prädikat löscht keine NULL-Werte, sodass Sie sie in den Ergebnissen abrufen können.

(Separator)

(315)

Die Definition im Standard ist jedoch negativ formuliert, so dass NULL-Werte den Vorteil des Zweifels erhalten. ...

Wie Sie sehen können, ist es eine gute Idee, NULL-Werte in EINZIGARTIGEN Einschränkungen zu vermeiden.

Diskussion der GRUPPE VON:

NULL-Werte werden so behandelt, als wären sie alle gleich und bilden eine eigene Gruppe. Jede Gruppe wird dann in einer neuen Ergebnistabelle, die die alte ersetzt, auf eine einzelne Zeile reduziert.

Dies bedeutet, dass für die GROUP BY-Klausel NULL = NULL nicht wie in 3VL als NULL ausgewertet wird, sondern als TRUE.

SQL-Standard ist verwirrend:

ORDER BY und NULLs (329)

Ob ein Sortierschlüsselwert, der NULL ist, als größer oder kleiner als ein Nicht-NULL-Wert angesehen wird, ist implementierungsdefiniert, aber ...

... Es gibt SQL-Produkte, die dies so oder so tun.

Im März 1999 stellte Chris Farrar eine Frage eines seiner Entwickler, die ihn veranlasste, einen Teil des SQL-Standards zu untersuchen , den ich zu verstehen glaubte . Chris fand einige Unterschiede zwischen dem allgemeinen Verständnis und dem tatsächlichen Wortlaut der Spezifikation .

Und so weiter. Ich denke ist genug von Celko.

CJ-Datum für SQL-NULL-Werte

CJ Date ist radikaler in Bezug auf NULL-Werte: Vermeiden Sie NULL-Werte in SQL, Punkt. Tatsächlich trägt Kapitel 4 seiner SQL- und relationalen Theorie: Wie schreibe ich genauen SQL-Code den Titel "NO DUPLICATES, NO NULLS" mit den Unterkapiteln "4.4 Was stimmt nicht mit Nullen?" und "4.5 Vermeiden von Nullen in SQL" (folgen Sie dem Link: Dank Google Books können Sie einige Seiten online lesen).

Fabian Pascal über SQL NULLs

Aus seinen praktischen Fragen im Datenbankmanagement - Eine Referenz für den denkenden Praktiker (keine Online-Auszüge, sorry):

10.3 Praktische Implikationen

10.3.1 SQL-NULL-Werte

... SQL leidet unter den Problemen, die 3VL inhärent sind, sowie unter vielen Macken, Komplikationen, Gegenintuitivität und direkten Fehlern [10, 11]; unter ihnen sind die folgenden:

  • Aggregatfunktionen (z. B. SUM (), AVG ()) ignorieren NULL-Werte (außer COUNT ()).
  • Ein skalarer Ausdruck in einer Tabelle ohne Zeilen wird falsch als NULL anstelle von 0 ausgewertet.
  • Der Ausdruck "NULL = NULL" ergibt NULL, ist jedoch in SQL ungültig. ORDER BY behandelt NULL-Werte jedoch als gleich (was auch immer vor oder nach "regulären" Werten steht, bleibt dem DBMS-Anbieter überlassen).
  • Der Ausdruck "x IST NICHT NULL" ist nicht gleich "NICHT (x IST NULL)", wie dies in 2VL der Fall ist.

...

Alle kommerziell implementierten SQL-Dialekte folgen diesem 3VL-Ansatz und zeigen daher nicht nur diese Probleme, sondern auch spezifische Implementierungsprobleme, die je nach Produkt unterschiedlich sind .

MaD70
quelle
4
"Und das war mein Punkt: NULL ist als Wert ein" seltsames Tier "." - Das liegt daran, dass NULLes kein Wert ist.
Pavel Minaev
1
Auch SQL Server gibt nicht (NULL = NULL) -> FALSE. Um die Dokumentation zu zitieren für ANSI_NULLS: "Wenn ON angegeben ist, werden alle Vergleiche mit einem Nullwert als UNBEKANNT ausgewertet . Wenn OFF angegeben ist, werden Vergleiche von Nicht-UNICODE-Werten mit einem Nullwert als TRUE ausgewertet, wenn beide Werte NULL sind."
Pavel Minaev
@ Pavel Minaev: a) und wie WAHR ist besser als FALSCH? b) Wenn es sich nicht um einen Wert handelt, warum wird er als Teil variabler Werte zugewiesen?
MaD70
1
>> Da es Dezember ist, verwenden wir ein saisonales Beispiel. Ich habe zwei Geschenke unter dem Baum. Jetzt sagst du mir, ob ich zwei davon habe oder nicht. ..... ja, Sie haben es getan, da Sie zwei Dinge haben und soweit es Sie betrifft , sind sie nach Ihrem derzeitigen Kenntnisstand für Sie genau gleich
Brad Thomas
3
null = null sollte wahr sein. null ist gut definierten Wert, kann repräsentieren einen unbekannten Wert, aber es kann auch repräsentieren die Abwesenheit eines Werts. Es sollte Sache des Entwicklers sein, zu entscheiden, was null darstellt, aber null selbst ist absolut ein Wert und null ist null = null. Jede andere Implementierung ist für eine Katastrophe bestimmt, da Sie ternäre Logik in Prädikate einfügen, die grundsätzlich boolesch sind. Ich bin entsetzt, dass dies eine dauerhafte Einstellung in SQL Server wird. AUS AUS AUS damit.
Triynko
9

Vielleicht hängt es davon ab, aber ich dachte NULL=NULL, NULLdass die meisten Operationen mit NULL als Operand bewertet werden .

Michael Krelin - Hacker
quelle
9

Nur weil Sie nicht wissen, was zwei Dinge sind, heißt das nicht, dass sie gleich sind. Wenn Sie an NULL„NULL“ (Zeichenfolge) denken, möchten Sie wahrscheinlich einen anderen Gleichheitstest wie das IS DISTINCT FROMUND von PostgresqlIS NOT DISTINCT FROM

Aus den PostgreSQL-Dokumenten zu "Vergleichsfunktionen und Operatoren"

Ausdruck IS DISTINCT FROMAusdruck

Ausdruck IS NOT DISTINCT FROMAusdruck

Entspricht für Eingaben ungleich Null IS DISTINCT FROMdem <>Operator. Wenn jedoch beide Eingaben null sind, wird false zurückgegeben, und wenn nur eine Eingabe null ist, wird true zurückgegeben. In ähnlicher Weise IS NOT DISTINCT FROMist es identisch mit =Nicht-Null-Eingaben, aber es gibt true zurück, wenn beide Eingaben null sind, und false, wenn nur eine Eingabe null ist. Somit verhalten sich diese Konstrukte effektiv so, als wäre Null ein normaler Datenwert und nicht "unbekannt".

Evan Carroll
quelle
5

Das Konzept von NULL ist, gelinde gesagt, fraglich. Codd führte das relationale Modell und das Konzept von NULL im Kontext ein (und schlug dann mehr als eine Art von NULL vor!). Die relationale Theorie hat sich jedoch seit Codds ursprünglichen Schriften weiterentwickelt: Einige seiner Vorschläge wurden inzwischen gestrichen (z. B. Primärschlüssel). und andere haben sich nie durchgesetzt (z. B. Theta-Operatoren). In der modernen relationalen Theorie (wirklich relationale Theorie, sollte ich betonen) existiert NULL einfach nicht. Siehe das dritte Manifest. http://www.thethirdmanifesto.com/

Die SQL-Sprache leidet unter dem Problem der Abwärtskompatibilität. NULL hat seinen Weg in SQL gefunden und wir bleiben dabei. Möglicherweise ist die Implementierung NULLin SQL fehlerhaft ( die Implementierung von SQL Server macht die Dinge aufgrund seiner ANSI_NULLSOption noch komplizierter ).

Ich empfehle, die Verwendung von NULL-fähigen Spalten in Basistabellen zu vermeiden.


Obwohl ich vielleicht nicht versucht sein sollte, wollte ich nur meine eigenen Korrekturen bezüglich der Funktionsweise NULLin SQL geltend machen :

NULL= NULLbewertet zu UNKNOWN.

UNKNOWN ist ein logischer Wert.

NULL ist ein Datenwert.

Dies ist leicht zu beweisen, z

SELECT NULL = NULL

generiert korrekt einen Fehler in SQL Server. Wenn das Ergebnis ein Datenwert wäre, würden wir erwarten, dies zu sehen NULL, wie einige Antworten hier (fälschlicherweise) vermuten lassen.

Der logische Wert UNKNOWNwird in SQL DML bzw. SQL DDL unterschiedlich behandelt.

In SQL DML werden UNKNOWNZeilen aus der Ergebnismenge entfernt.

Beispielsweise:

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

Das ist INSERTfür diese Zeile erfolgreich, obwohl die CHECKBedingung in aufgelöst wird NULL = NULL. Dies ist im SQL-92-Standard ("ANSI") definiert:

11.6 Definition der Tabelleneinschränkung

3)

Wenn die Tabellenbeschränkung eine Prüfbeschränkungsdefinition ist, sei SC die Suchbedingung, die unmittelbar in der Prüfbeschränkungsdefinition enthalten ist, und sei T der Tabellenname, der im entsprechenden Tabellenbeschränkungsdeskriptor enthalten ist; Die Tabelleneinschränkung ist nur dann nicht erfüllt, wenn

EXISTS (SELECT * FROM T WHERE NOT (SC))

ist wahr.

Lesen Sie das noch einmal sorgfältig durch und folgen Sie dabei der Logik.

Im Klartext erhält unsere neue Zeile oben den "Vorteil des Zweifels" über das Sein UNKNOWNund das Bestehen.

In SQL DML ist die Regel für die WHEREKlausel viel einfacher zu befolgen:

Die Suchbedingung wird auf jede Zeile von T angewendet. Das Ergebnis der where-Klausel ist eine Tabelle der Zeilen von T, für die das Ergebnis der Suchbedingung wahr ist.

Im Klartext werden Zeilen, die als ausgewertet UNKNOWNwerden, aus der Ergebnismenge entfernt.

eines Tages, wenn
quelle
5

Bei technet gibt es eine gute Erklärung dafür, wie Nullwerte funktionieren.

Null bedeutet unbekannt.

Daher der Boolesche Ausdruck

Wert = null

wird nicht als falsch ausgewertet, sondern als null. Wenn dies jedoch das Endergebnis einer where-Klausel ist, wird nichts zurückgegeben. Dies ist ein praktischer Weg, da die Rückgabe von Null schwer vorstellbar wäre.

Es ist interessant und sehr wichtig , Folgendes zu verstehen:

Wenn in einer Abfrage haben wir

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

und

  • Wert = 1
  • @param ist null
  • id = 123
  • @ anotherParam = 123

dann

"value = @ param" ergibt null
"@param ist null" ergibt true
"id = @ anotherParam" ergibt true

So wird der auszuwertende Ausdruck

(null oder wahr) Und wahr

Wir könnten versucht sein zu glauben, dass hier "null oder wahr" zu null ausgewertet wird und somit der gesamte Ausdruck null wird und die Zeile nicht zurückgegeben wird.

Das ist nicht so. Warum?

Da "null oder wahr" als wahr ausgewertet wird, was sehr logisch ist, da, wenn ein Operand mit dem Or-Operator wahr ist, die Operation unabhängig vom Wert des anderen Operanden true zurückgibt. Somit spielt es keine Rolle, dass der andere Operand unbekannt ist (null).

Wir haben also endlich true = true und somit wird die Zeile zurückgegeben.

Hinweis: Mit derselben kristallklaren Logik, die "null oder wahr" als wahr ergibt, wird "null und wahr" als null ausgewertet.

Update:
Ok, nur um es zu vervollständigen, möchte ich auch hier den Rest hinzufügen, was in Bezug auf das oben Genannte ziemlich lustig ist.

"null oder falsch" ergibt null, "null und falsch" ergibt falsch. :) :)

Die Logik ist natürlich immer noch so selbstverständlich wie zuvor.

Magnus
quelle
4

Weil NULLbedeutet "unbekannter Wert" und zwei unbekannte Werte können nicht gleich sein.

Wenn also nach unserer Logik NULLN ° 1 gleich NULLN ° 2 ist, müssen wir das irgendwie sagen:

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

wobei der bekannte Wert -1N ° 1 gleich -1N ° 2 ist

armen
quelle
nullParam1 = -1und nullParam2 =NULLund Flugzeugabsturz .... sollte seinISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
Selvin
4

Die Antworten hier scheinen alle aus einer CS-Perspektive zu kommen, daher möchte ich eine aus Entwicklersicht hinzufügen.

Für einen Entwickler ist NULL sehr nützlich. Die Antworten hier sagen, dass NULL unbekannt bedeutet, und vielleicht ist das in der CS-Theorie wahr, erinnere dich nicht, es ist eine Weile her. In der tatsächlichen Entwicklung geschieht dies jedoch, zumindest nach meiner Erfahrung, in etwa 1% der Fälle. Die anderen 99% werden für Fälle verwendet, in denen der Wert nicht UNBEKANNT ist, aber bekanntermaßen nicht vorhanden ist.

Beispielsweise:

  • Client.LastPurchasefür einen neuen Kunden. Es ist nicht unbekannt, es ist bekannt, dass er noch keinen Kauf getätigt hat.

  • Wenn es mit einem mit Hilfe eines ORM Tabelle pro Klasse Hierarchie Mapping, sind einige Werte nicht nur für bestimmte Klassen zugeordnet.

  • Bei der Zuordnung einer Baumstruktur hat normalerweise eine WurzelParent = NULL

  • Und viele mehr...

Ich bin sicher, dass die meisten Entwickler irgendwann geschrieben WHERE value = NULLhaben, keine Ergebnisse erzielt haben und so etwas über die IS NULLSyntax gelernt haben . Schauen Sie sich nur an, wie viele Stimmen diese und die verknüpften Fragen haben.

SQL-Datenbanken sind ein Werkzeug, und sie sollten so gestaltet sein, dass sie für ihre Benutzer am einfachsten zu verstehen sind.

AlexDev
quelle
1
Jeder scheint zu schreien "NULL ist unbekannt" und dann das Verhalten zu rechtfertigen. Ja, wenn das eine Voraussetzung ist, dann ist 3VL vielleicht die Antwort. Aber in fast allen DBs, an denen ich arbeite, bedeutet NULL abwesend. Entschuldigung, Ihre Stimme ist in der Wildnis verloren @AlexDev
John Rees
3

NULL ist nichts gleich, nicht einmal sich selbst. Meine persönliche Lösung, um das Verhalten von NULL zu verstehen, besteht darin, es so weit wie möglich zu vermeiden :).

Chris R. Timmons
quelle
1
könnte genauso gut für alles gleich sein, wie es bei linken / rechten / äußeren Verbindungen der Fall ist ...
Miguel Ventura
5
Was für eine dumme unproduktive Antwort. Das Gleiche könnte man für Grundschulkinder über Algebra sagen, aber ohne wirklich anzuerkennen, was zu lösen versucht, würde es einfach als albern herauskommen, was es auch tat.
Evan Carroll
2
@Evan: Eigentlich ist das Vermeiden von NULL eine gute Lösung. 3-wertige Logik ist nicht unumstritten, und viele Leute glauben, dass SQL ohne NULL und die damit verbundene (notwendige) Komplexität besser dran wäre.
Sleske
3
"Viele Leute" ist ein Wieselwort, und "nicht unumstritten" ist ein Weg, das einfachere "umstrittene" zu verschleiern, von dem 3VL nicht ist.
Evan Carroll
"NULL ist nichts gleich, nicht einmal sich selbst." Nach dieser Logik sollte <somevalue>! = NULL true zurückgeben. Im seltsamen Universum von SQL ist es jedoch falsch.
Tom Lint
3

Die Frage:
Entspricht ein Unbekannter einem anderen Unbekannten?
(NULL = NULL)
Diese Frage kann niemand beantworten, daher ist sie abhängig von Ihrer ansi_nulls-Einstellung standardmäßig true oder false.

Allerdings die Frage:
Ist diese unbekannte Variable unbekannt?
Diese Frage ist ganz anders und kann mit wahr beantwortet werden.

nullVariable = null vergleicht die Werte
nullVariable ist null vergleicht den Status der Variablen

user224385
quelle
3

Die Verwirrung ergibt sich aus der Indirektionsebene (Abstraktion), die durch die Verwendung von NULL entsteht .

Zurück zu der Analogie "Was ist unter dem Weihnachtsbaum?" Beschreibt "Unbekannt" den Wissensstand darüber, was sich in Kasten A befindet.

Wenn Sie also nicht wissen, was sich in Box A befindet, sagen Sie, dass es "Unbekannt" ist, aber das bedeutet nicht, dass sich "Unbekannt" in der Box befindet . In der Box befindet sich etwas anderes als Unbekanntes, möglicherweise eine Art Objekt, oder möglicherweise befindet sich nichts in der Box.

Wenn Sie nicht wissen, was in Feld B enthalten ist, können Sie Ihren Wissensstand über den Inhalt als "Unbekannt" kennzeichnen.

Also hier ist der Kicker: Ihr Stand des Wissens über Box A gleich Ihren Stand des Wissens über Box B . (Ihr Wissensstand ist in beiden Fällen "Unbekannt" oder "Ich weiß nicht, was sich in der Box befindet".) Der Inhalt der Boxen kann jedoch gleich sein oder auch nicht.

Wenn Sie zu SQL zurückkehren, sollten Sie im Idealfall nur dann Werte vergleichen können, wenn Sie wissen, was sie sind. Leider ist das Etikett, das einen Mangel an Wissen beschreibt, in der Zelle selbst gespeichert , sodass wir versucht sind, es als Wert zu verwenden. Wir sollten dies jedoch nicht als Wert verwenden, da dies dazu führen würde, dass "der Inhalt von Box A dem Inhalt von Box B entspricht, wenn wir nicht wissen, was in Box A enthalten ist und / oder wir nicht wissen, was in Box B enthalten ist." (Logischerweise ist die Implikation "Wenn ich nicht weiß, was in Box A ist und wenn ich nicht weiß, was in Box B ist, dann ist was in Box A = Was ist in Box B" falsch.)

Ja, totes Pferd.

TomEberhard
quelle
3

MSDN hat einen schönen beschreibenden Artikel über Nullen und die Drei-Zustands-Logik, die sie erzeugen.

Kurz gesagt, die SQL92-Spezifikation definiert NULL als unbekannt, und NULL, das in den folgenden Operatoren verwendet wird, führt zu unerwarteten Ergebnissen für Uneingeweihte:

= 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
quelle
Bei der Frage geht es jedoch nicht um 3VL (dreiwertige Logik), sondern um die reflexive Eigenschaft der Gleichheit.
MaD70
Genauer gesagt, wie ich schließlich in meiner Antwort ausführlich dargelegt habe, treten Probleme auf, wenn Gleichheit in einer 3VL interpretiert wird, so dass die reflexive Eigenschaft der Gleichheit nicht immer als wahr bewertet wird.
MaD70
1

null ist in SQL unbekannt, daher können wir nicht erwarten, dass zwei Unbekannte gleich sind.

Sie können dieses Verhalten jedoch erreichen, indem Sie ANSI_NULLS auf Off setzen (standardmäßig aktiviert). Sie können den Operator = für Nullen verwenden

SET ANSI_NULLS off
if null=null
print 1
else 
print 2
set ansi_nulls on
if null=null
print 1
else 
print 2
ps.
quelle
2
Das sind alle Arten von Nein . Die Welt hat eine Definition von null, lernt sie zu verstehen oder ändert einfach die Tabelle, um int-Typen zu haben und die Spalten zu aktualisieren.
Evan Carroll
3
Ich habe SET ANSI_NULLS wirklich nicht empfohlen. Ich habe auf die harte Tour von ANSI_NULLS erfahren. Es ist jedoch immer gut, alle verfügbaren Optionen zu kennen, insbesondere wenn Sie auf eine Zeile stoßen, in der Where SomeId = null steht. Wie würden Sie diese Zeile verstehen, ohne ANSI_NULLS zu kennen? So wie ich es sehe, war mein Beitrag nützlich .. :)
ps.
1

Sie arbeiten für die Regierung und registrieren Informationen über Bürger. Dies beinhaltet die nationale ID für jede Person im Land. Ein Kind wurde vor etwa 40 Jahren an der Tür einer Kirche zurückgelassen, niemand weiß, wer seine Eltern sind. Der Vaterausweis dieser Person lautet NULL. Es gibt zwei solche Leute. Zählen Sie Personen, die denselben Vaterausweis mit mindestens einer anderen Person teilen (Geschwister). Zählst du auch diese beiden?

Die Antwort ist nein, Sie nicht, weil wir nicht wissen, ob sie Geschwister sind oder nicht.

Angenommen, Sie haben keine NULLOption und verwenden stattdessen einen vordefinierten Wert, um „das Unbekannte“ darzustellen, möglicherweise eine leere Zeichenfolge oder die Zahl 0 oder ein * -Zeichen usw. Dann hätten Sie in Ihren Abfragen * = * , 0 = 0 und "" = "" usw. Dies ist nicht das, was Sie wollen (wie im obigen Beispiel), und wie Sie diese Fälle oft vergessen (das obige Beispiel ist ein klarer Randfall außerhalb des normalen Alltagsdenkens ), dann brauchen Sie die Sprache, an die Sie sich erinnern müssen, die NULL = NULLnicht wahr ist.

Notwendigkeit ist die Mutter der Erfindung.

Rashad Saleh
quelle
0

Nur eine Ergänzung zu anderen wunderbaren Antworten:

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

Wenn Sie nach einem Ausdruck suchen, der für zwei NULL-Werte true zurückgibt, können Sie Folgendes verwenden:

SELECT 1 
WHERE EXISTS (
    SELECT NULL
    INTERSECT
    SELECT NULL
)

Es ist hilfreich, wenn Sie Daten von einer Tabelle in eine andere replizieren möchten.

Piotr
quelle
0

Der Gleichheitstest kann beispielsweise in einer case-Anweisung when-Klausel von geändert werden

XYZ = NULL 

zu

XYZ IS NULL

Wenn ich Leerzeichen und leere Zeichenfolgen als NULL behandeln möchte, verwende ich häufig auch einen Gleichheitstest wie:

(NULLIF(ltrim( XYZ ),'') IS NULL)
Allan F.
quelle