Wie füge ich bei Vergleichen in SQL Server Nullen hinzu?

9

Grundsätzlich bedeutet ein NULL in SQL Server, dass es keinen Wert gibt und daher nicht verglichen werden kann, was zu unerwarteten Ergebnissen führt.

Beispielsweise gibt die folgende Abfrage keine Zeilen zurück, in denen der Wert NULL ist, aber ich möchte, dass dies der Fall ist:

SELECT *
FROM table
WHERE
  (value != 26)
  AND date IS NULL
  AND last_modified >= '5/21/2014'

Ich verstehe, dass ich Folgendes als Problemumgehung tun kann, aber im Ernst? Müssen Sie jedes Mal, wenn ich es einfügen möchte, Klammern hinzufügen und prüfen, ob für jedes einzelne Feld null ist? Scheint hässlich, nicht intuitiv und verrückt.

SELECT *
FROM table
WHERE
  (value != 26 OR value is null)
  AND date IS NULL
  AND last_modified >= '5/21/2014'

Ich meine, ich weiß, dass NULL kein Wert ist und daher nicht verglichen werden kann, aber können Sie nicht daraus schließen, dass es tatsächlich definitiv nicht 26 ist? Wenn 26 etwas ist und NULL nichts ist und nichts nichts ist, dann ist NULL nicht 26. Scheint mir logisch.

Weiß jemand, wie ich bei der Verwendung von Vergleichen auf sauberere Weise Nullen in meine Ergebnisse aufnehmen kann, ohne jedes Mal eine explizite Prüfung durchführen zu müssen? Auch das Deaktivieren von Nullen auf meinen Tabellen ist definitiv keine Option.

Bearbeiten:

Mein eigentliches Problem, warum ich es nicht so machen will, wie ich es gezeigt habe, wurde nicht aufgedeckt. Also los geht's. Ich schreibe ein Programm, mit dem Sie Abfragen für Datenbanktabellen erstellen und den Benutzer dynamisch Filter erstellen lassen können, die im Wesentlichen am Ende des Tages eine SQL-Anweisung erstellen und die Ergebnisse für den Benutzer anzeigen. Die vom Benutzer ausgewählten Felder können beliebige und / oder alle Felder in einer bestimmten Datenbank sein. Wenn ich diese ISNULL-Prüfung buchstäblich auf jedes einzelne Feld setzen muss, wäre dies wirklich ineffizient und würde das Betrachten von SQL sehr hässlich machen. Mein Programm ist tabellendefinitionsunabhängig, was bedeutet, dass es mir egal ist, was in Ihrer Tabelle enthalten ist, und ich möchte nicht wissen, wie Ihre Tabelle definiert ist. Ich möchte nur, dass Sie eine Tabelle auswählen, einige Felder auswählen, nach denen mit gleich, nicht gleich, in, nicht in usw. gefiltert werden soll.

Brian T Hannan
quelle
Ich habe keine Kontrolle über die Tabelle, es ist eine Legacy-Tabelle und ich schreibe Code, der sie verwendet.
Brian T Hannan
Re. "Klammern hinzufügen müssen und ...? Scheint hässlich, nicht intuitiv und verrückt.": Sie sollten - IMMER "Klammern hinzufügen". "Code wird viel mehr gelesen als geschrieben." Lassen Sie nicht jeden (fehleranfälligen) menschlichen Leser a) den Vorrang kennen, b) sich daran erinnern und c) ihn jedes Mal richtig anwenden, wenn er jeden Ausdruck liest , und daher viel häufiger (als Sie) gegen das DRY-Prinzip verstoßen durch Hinzufügen von "nicht benötigten" Klammern). "Nur weil du es nicht kannst (lass sie weg), heißt das nicht, dass du es nicht lassen sollst ..."
Tom
Diese Frage ist im Wesentlichen ein Duplikat der StackOverflow-Frage von 8 Monaten zuvor, die hier eine viel bessere Antwort hatte (die selbst auf einem Artikel 2 Jahre zuvor basierte): stackoverflow.com/questions/19682956/…
Tom

Antworten:

9

Zu Beginn bedeutet NULL nicht "kein Wert", sondern "Unbekannter Wert" in SQL Server. Es gibt eine Sitzungseinstellung mit dem Namen ANSI_NULLS, die dazu führen kann, dass sich Ihre Abfragen so verhalten, wie Sie es möchten. Sie ist jedoch veraltet und wird in einer zukünftigen Version auf ON gesetzt (was Ihnen anscheinend nicht gefällt): http: // msdn .microsoft.com / de-de / library / ms188048.aspx

Ich verstehe, was Sie tun möchten, und um einen Gegenpunkt zu machen, würde ich fragen, ob Sie Fragen gesehen haben, die von Berichtsdiensten oder so etwas wie Cognos generiert wurden. Wenn ja, sehen Sie genau, was Sie beschreiben, was Sie nicht tun möchten. Warum? Nun, mit einem Schema, das Nullen zulässt, ist dies der richtige Weg. Ich sage nicht, dass es eine super tolle und großartige Idee ist, aber sie funktioniert die ganze Zeit.

Was Ihr Designer tun könnte, ist zu überprüfen, ob diese Spalte überhaupt null sein könnte, und wenn ja, könnte die entsprechende Logik sie schrittweise ausführen und die richtige Abfrage erstellen. Sie könnten auch Optionen wie "Diese Spalte ist möglicherweise null, möchten Sie diese Werte?" Haben. Ich kenne das Endspiel per se nicht und das Schreiben eines eigenen dynamischen Abfragetools ist ziemlich schwierig, wenn alle logischen Konsistenzen berücksichtigt werden (wie dieses).

Ich würde weiterhin explizite Nullprüfungen für Spalten durchführen, die möglicherweise null sein könnten. Sicher sieht es nicht gut aus, aber es funktioniert die ganze Zeit.

Die ANSI_NULL-Set-Option funktioniert vorerst, ist jedoch keine gute Idee, insbesondere wenn Sie die Umgebung nicht steuern. Außerdem wird sie später auf ON gesetzt und verursacht Fehler, bei denen Sie Ihre Anwendungslogik ohnehin neu schreiben müssen. Auf diese Weise arbeitet SQL Server mit NULL-Werten.

Sean Gallardy - Benutzer im Ruhestand
quelle
9

Das NULLProblem ist ein heikles Problem mit SQL. Es ist im Grunde ein Fehler, der jetzt in alle SQL-Software auf dem Planeten eingebrannt ist. Wir müssen uns darum kümmern.

value <> 26 or value is nullist ein guter Weg, um diese Logik zu implementieren. Es gibt andere Formulierungen derselben Semantik.

Wenn Sie wissen, dass dieser Wert niemals -1(zum Beispiel) ist, können Sie sagen ISNULL(value, -1) <> 26. Ich denke nicht, dass dies vom Standpunkt der Lesbarkeit aus besser ist. Dies kann auch zu Optimierungsproblemen führen, da dieses Prädikat möglicherweise nicht SARG-fähig ist. value is null ist ein SARGable und indexable Prädikat, das der landläufigen Meinung widerspricht.

SQL hat den IS DINSTINCT FROMOperator, T-SQL unterstützt ihn jedoch nicht. Bitte nehmen Sie sich eine Sekunde Zeit, um für den Antrag auf Umsetzung zu stimmen! Es ist ein rein syntaktisches Problem. Der Optimierer muss sich überhaupt nicht ändern. Dieser Operator wird bereits intern unterstützt.

TL; DR: Die Art und Weise, wie Sie es gerade tun, ist die richtige. Lebe damit.

usr
quelle
1
"Grundsätzlich ein Fehler". Ich sehe das anders. Das relationale Modell basiert auf Mengenlehre und Prädikatenlogik. SQL implementiert eine dreiwertige Prädikatenlogik, indem NULL unterstützt wird, um das generische Konzept eines fehlenden Werts zu kennzeichnen. Die Unterstützung von NULL-Werten und dreiwertiger Prädikatenlogik ist seit langem Teil der ANSI- und ISO-Standards. Leider herrscht Debatte und Verwirrung ...
Dave Mason
3
@DMason Ich verstehe die Gründe für dieses Modell (obwohl es nichts mit Mengen zu tun hat. Dies ist ein skalares Problem.). Es ist nur so, dass niemand dieses Modell will. In der Praxis ist es nicht sinnvoll. Schien damals eine gute Idee zu sein, aber 30 Jahre später wissen wir, dass es keine war. Es gibt einen Grund, warum fast alle Programmiersprachen null wie jeden anderen Wert behandeln. C # mit nullbaren Werttypen macht das auch.
usr
Umstritten? Tatsächlich! Du bist nicht allein, @usr. Viele andere sind der Meinung, dass ein gültiges relationales Modell einer zweiwertigen Logik folgen und dem Konzept der NULL-Werte in SQL stark widersprechen sollte. EF Codd, der Schöpfer des relationalen Modells, glaubte an die Idee, fehlende Werte und Prädikate zu unterstützen, die über die zweiwertige Logik hinausgehen. Ich stimme ihm zu. Sie haben eine andere Meinung. So ist das Leben. Wer bin ich, um dir deine Meinung zu verweigern?
Dave Mason
@DMason Ich respektiere deine.
usr