Wenn Sie nullParam=NULL
in 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 NULL
und IS NOT NULL
Schlüsselwörter sind der richtige Weg, um es zu tun. Aber warum verhält sich SQL Server so?
sql
sql-server
null
Byron Whitlock
quelle
quelle
Antworten:
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 ...
quelle
(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.NULL
in einem SQL-Ausdruck kann als eigenständige mathematische Variable behandelt werden. Ein AusdruckNULL = NULL
sollte also alsx = y
, wox
undy
ungebundene Variablen behandelt werden. Wenn dich jemand fragt, welchen Wert hat dasx = y
? Die einzig vernünftige Antwort ist "einigez
". Also haben wir(x = y) = z
- oder, es zurück in SQL zu transkribieren ,(NULL = NULL) = NULL
.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.
quelle
null = null
RenditenFALSE
nichtNULL
.Hier werde ich hoffentlich meine Position klarstellen.
Das zu
NULL = NULL
bewertenFALSE
ist falsch. Hacker und Mister haben richtig geantwortetNULL
. Hier ist warum. Dewayne Christensen schrieb mir in einem Kommentar an Scott Ivey :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 (dh
NULL
).Dieses Beispiel sollte zeigen, dass ".. (
false
odernull
, abhängig von Ihrem System) .." eine richtige Antwort ist - es ist nicht nurNULL
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:
Also wiederhole ich: SQL zwingt nicht dazu, die reflexive Eigenschaft der Gleichheit zu interpretieren, die besagt, dass:
.. 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), dhx = x
bewerten immerTRUE
, 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 :
NULL
Als 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:
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.
Wieder dieser "Wert aber nicht ganz ein Wert" Unsinn. Der Rest scheint mir ziemlich vernünftig.
Apropos von SQL, NULLs und unendlich:
SQL-Implementierungen haben nicht entschieden, was NULL in bestimmten Kontexten wirklich bedeutet:
Joe Celko zitiert David McGoveran und CJ Datum:
NULL als Drogenabhängigkeit :
Mein einzigartiger Einwand hier ist, "sie richtig zu verwenden", was schlecht mit bestimmten Implementierungsverhalten interagiert.
(Separator)
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 :
Lesen Sie "ASIDE" auf UNKNOWN, ebenfalls unten verlinkt.
(Separator)
Einwand: NULL verwirrt auch Leute, die SQL gut kennen, siehe unten.
(Separator)
(Separator)
(Separator)
(Separator)
(Separator)
(Separator)
Diskussion der GRUPPE VON:
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:
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):
quelle
NULL
es kein Wert ist.(NULL = NULL) -> FALSE
. Um die Dokumentation zu zitieren fürANSI_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."Vielleicht hängt es davon ab, aber ich dachte
NULL=NULL
,NULL
dass die meisten Operationen mit NULL als Operand bewertet werden .quelle
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 dasIS DISTINCT FROM
UND von PostgresqlIS NOT DISTINCT FROM
Aus den PostgreSQL-Dokumenten zu "Vergleichsfunktionen und Operatoren"
quelle
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
NULL
in SQL fehlerhaft ( die Implementierung von SQL Server macht die Dinge aufgrund seinerANSI_NULLS
Option 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
NULL
in SQL geltend machen :NULL
=NULL
bewertet zuUNKNOWN
.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
UNKNOWN
wird in SQL DML bzw. SQL DDL unterschiedlich behandelt.In SQL DML werden
UNKNOWN
Zeilen aus der Ergebnismenge entfernt.Beispielsweise:
Das ist
INSERT
für diese Zeile erfolgreich, obwohl dieCHECK
Bedingung in aufgelöst wirdNULL = NULL
. Dies ist im SQL-92-Standard ("ANSI") definiert: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
UNKNOWN
und das Bestehen.In SQL DML ist die Regel für die
WHERE
Klausel viel einfacher zu befolgen:Im Klartext werden Zeilen, die als ausgewertet
UNKNOWN
werden, aus der Ergebnismenge entfernt.quelle
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
und
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.
quelle
Weil
NULL
bedeutet "unbekannter Wert" und zwei unbekannte Werte können nicht gleich sein.Wenn also nach unserer Logik
NULL
N ° 1 gleichNULL
N ° 2 ist, müssen wir das irgendwie sagen:wobei der bekannte Wert
-1
N ° 1 gleich-1
N ° 2 istquelle
nullParam1 = -1
undnullParam2 =NULL
und Flugzeugabsturz .... sollte seinISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
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.LastPurchase
fü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 Wurzel
Parent = NULL
Und viele mehr...
Ich bin sicher, dass die meisten Entwickler irgendwann geschrieben
WHERE value = NULL
haben, keine Ergebnisse erzielt haben und so etwas über dieIS NULL
Syntax 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.
quelle
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 :).
quelle
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
quelle
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.
quelle
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:
quelle
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
quelle
null
, lernt sie zu verstehen oder ändert einfach die Tabelle, um int-Typen zu haben und die Spalten zu aktualisieren.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
NULL
Option 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, dieNULL = NULL
nicht wahr ist.Notwendigkeit ist die Mutter der Erfindung.
quelle
Nur eine Ergänzung zu anderen wunderbaren Antworten:
quelle
Wenn Sie nach einem Ausdruck suchen, der für zwei NULL-Werte true zurückgibt, können Sie Folgendes verwenden:
Es ist hilfreich, wenn Sie Daten von einer Tabelle in eine andere replizieren möchten.
quelle
Der Gleichheitstest kann beispielsweise in einer case-Anweisung when-Klausel von geändert werden
zu
Wenn ich Leerzeichen und leere Zeichenfolgen als NULL behandeln möchte, verwende ich häufig auch einen Gleichheitstest wie:
quelle