Ich habe diese Fehlermeldung:
Meldung 8134, Ebene 16, Status 1, Zeile 1 Fehler beim Teilen durch Null aufgetreten.
Was ist der beste Weg, um SQL-Code zu schreiben, damit ich diese Fehlermeldung nie wieder sehe?
Ich könnte eine der folgenden Aktionen ausführen:
- Fügen Sie eine where-Klausel hinzu, damit mein Divisor niemals Null ist
Oder
- Ich könnte eine Fallbeschreibung hinzufügen, damit es eine Sonderbehandlung für Null gibt.
Ist der beste Weg, eine NULLIF
Klausel zu verwenden?
Gibt es einen besseren Weg oder wie kann dies durchgesetzt werden?
sql
sql-server
sql-server-2005
sql-server-2008
Henrik Staun Poulsen
quelle
quelle
Antworten:
Um einen Fehler "Division durch Null" zu vermeiden, haben wir ihn folgendermaßen programmiert:
Aber hier ist eine viel schönere Art, es zu tun:
Jetzt besteht das einzige Problem darin, sich das NullIf-Bit zu merken, wenn ich die Taste "/" verwende.
quelle
IsNull
statt verwendet habenNullIf
? Versuch es selber!SELECT Value,1/NullIf(Value,0)FROM(VALUES(0),(5.0),(NULL))x(Value);
Wenn nicht mit "Pausen" gemeint ist, wird NULL zurückgegeben? Sie können das mitIsNull
oder in alles konvertieren, was Sie wollenCoalesce
.SELECT 1 / NULLIF(NULL, 0)
schlägt fehl, aber es liegt daranNULLIF()
, dass der Datentyp des ersten Arguments bekannt sein muss. Dieses geänderte Beispiel funktioniert einwandfrei :SELECT 1 / NULLIF(CAST(NULL AS INT), 0)
. Im wirklichen Leben werden SieNULLIF()
eher eine Tabellenspalte als eineNULL
Konstante angeben. Da Tabellenspalten bekannte Datentypen haben, funktioniert dies auch einwandfrei :SELECT 1 / NULLIF(SomeNullableColumn, 0) FROM SomeTable
.Wenn Sie Null zurückgeben möchten, falls eine Null-Abweichung auftreten würde, können Sie Folgendes verwenden:
Für jeden Divisor, der Null ist, erhalten Sie eine Null in der Ergebnismenge.
quelle
Dies schien die beste Lösung für meine Situation zu sein, wenn ich versuchte, die Division durch Null zu beheben, was in meinen Daten vorkommt.
Angenommen, Sie möchten das Verhältnis von Männern zu Frauen für verschiedene Schulklubs berechnen, stellen jedoch fest, dass die folgende Abfrage fehlschlägt und einen Fehler beim Teilen durch Null ausgibt, wenn versucht wird, das Verhältnis für den Lord of the Rings-Club zu berechnen, der keine Frauen hat ::
Mit dieser Funktion können Sie
NULLIF
eine Division durch Null vermeiden.NULLIF
vergleicht zwei Ausdrücke und gibt null zurück, wenn sie gleich sind, oder den ersten Ausdruck andernfalls.Schreiben Sie die Abfrage wie folgt um:
Jede Zahl geteilt durch
NULL
gibtNULL
, und es wird kein Fehler erzeugt.quelle
select males/(males+females), females/(males+females)
. Dies gibt Ihnen die prozentuale Verteilung von Männern und Frauen in einem Club, wie 31% Männer, 69% Frauen.Sie können dies auch zu Beginn der Abfrage tun:
Wenn Sie also so etwas haben,
100/0
wird NULL zurückgegeben. Ich habe dies nur für einfache Abfragen getan, daher weiß ich nicht, wie sich dies auf längere / komplexe Abfragen auswirkt.quelle
Sie können zumindest verhindern, dass die Abfrage mit einem Fehler unterbrochen wird, und zurückkehren,
NULL
wenn eine Division durch Null vorliegt :Allerdings würde ich nie diese auf Null konvertieren ,
coalesce
wie es in der anderen Antwort gezeigt, die viele upvotes bekamen. Dies ist im mathematischen Sinne völlig falsch und sogar gefährlich, da Ihre Anwendung wahrscheinlich falsche und irreführende Ergebnisse liefert.quelle
BEARBEITEN: Ich bekomme in letzter Zeit viele Abstimmungen dazu ... also dachte ich, ich würde nur eine Notiz hinzufügen, dass diese Antwort geschrieben wurde, bevor die Frage zuletzt bearbeitet wurde, wobei die Rückgabe von null als Option hervorgehoben wurde. .das scheint sehr akzeptabel. Einige meiner Antworten richteten sich in den Kommentaren an Bedenken wie die von Edwardo, der anscheinend die Rückgabe einer 0 befürwortete. Dies ist der Fall, gegen den ich mich beschimpfte.
ANTWORT: Ich denke, hier liegt ein Problem zugrunde, nämlich dass die Division durch 0 nicht legal ist. Es ist ein Hinweis darauf, dass etwas grundlegend falsch ist. Wenn Sie durch Null teilen, versuchen Sie, etwas zu tun, das mathematisch nicht sinnvoll ist, sodass keine numerische Antwort gültig ist. (Die Verwendung von null ist in diesem Fall sinnvoll, da es sich nicht um einen Wert handelt, der in späteren mathematischen Berechnungen verwendet wird.)
Also fragt Edwardo in den Kommentaren "Was ist, wenn der Benutzer eine 0 eingibt?" Und er befürwortet, dass es in Ordnung sein sollte, eine 0 als Gegenleistung zu erhalten. Wenn der Benutzer den Betrag auf Null setzt und Sie möchten, dass 0 zurückgegeben wird, sollten Sie Code auf der Ebene der Geschäftsregeln eingeben, um diesen Wert abzufangen und 0 zurückzugeben. Es gibt keinen Sonderfall, in dem Division durch 0 = 0.
Das ist ein subtiler Unterschied, aber es ist wichtig ... weil das nächste Mal, wenn jemand Ihre Funktion aufruft und erwartet, dass sie das Richtige tut, etwas Funky funktioniert, das mathematisch nicht korrekt ist, sondern nur den speziellen Randfall behandelt, den es hat gute Chance, später jemanden zu beißen. Sie teilen nicht wirklich durch 0 ... Sie geben nur eine schlechte Antwort auf eine schlechte Frage zurück.
Stellen Sie sich vor, ich codiere etwas und vermassle es. Ich sollte einen Skalierungswert für die Strahlungsmessung einlesen, aber in einem seltsamen Randfall, den ich nicht erwartet hatte, las ich 0 ein. Dann lasse ich meinen Wert in Ihre Funktion fallen ... Sie geben mir eine 0 zurück! Hurra, keine Strahlung! Außer es ist wirklich da und es ist nur so, dass ich einen schlechten Wert abgegeben habe ... aber ich habe keine Ahnung. Ich möchte, dass die Division den Fehler auslöst, weil es die Flagge ist, dass etwas nicht stimmt.
quelle
Indem Sie die Null mit einem nullif () und dann die resultierende Null mit einem isnull () abfangen, können Sie Ihre Division durch einen Nullfehler umgehen.
quelle
Das Ersetzen von "durch Null teilen" durch Null ist umstritten - aber es ist auch nicht die einzige Option. In einigen Fällen ist das Ersetzen durch 1 (angemessen) angemessen. Ich finde mich oft mit
Wenn ich Verschiebungen in Punktzahlen / Zählungen betrachte und standardmäßig 1 verwenden möchte, wenn ich keine Daten habe. Zum Beispiel
Meistens habe ich dieses Verhältnis tatsächlich woanders berechnet (nicht zuletzt, weil es einige sehr große Anpassungsfaktoren für niedrige Nenner auslösen kann. In diesem Fall würde ich normalerweise steuern, dass OldSampleScore größer als ein Schwellenwert ist, der dann Null ausschließt Aber manchmal ist der "Hack" angemessen.
quelle
Ich habe vor einiger Zeit eine Funktion geschrieben, um sie für meine gespeicherten Prozeduren zu handhaben :
quelle
Divisor
, dass sie nicht Null istquelle
Für Update-SQLs:
quelle
Es gibt keine magische globale Einstellung "Division durch 0 Ausnahmen ausschalten". Die Operation muss werfen, da sich die mathematische Bedeutung von x / 0 von der NULL-Bedeutung unterscheidet und daher nicht NULL zurückgeben kann. Ich gehe davon aus, dass Sie sich um das Offensichtliche kümmern und Ihre Abfragen Bedingungen haben, die die Datensätze mit dem 0-Teiler beseitigen und die Teilung niemals bewerten sollten. Das übliche "Gotcha" ist, dass die meisten Entwickler erwarten, dass sich SQL wie prozedurale Sprachen verhält und einen logischen Operator-Kurzschluss bietet, dies jedoch NICHT . Ich empfehle Ihnen, diesen Artikel zu lesen: http://www.sqlmag.com/Articles/ArticleID/9148/pg/2/2.html
quelle
Hier ist eine Situation, in der Sie durch Null teilen können. Die Geschäftsregel lautet, dass Sie zur Berechnung der Lagerumschläge die Kosten der für einen bestimmten Zeitraum verkauften Waren auf Jahresbasis berechnen. Nachdem Sie die annualisierte Zahl haben, dividieren Sie durch den durchschnittlichen Bestand für den Zeitraum.
Ich möchte die Anzahl der Inventarumdrehungen berechnen, die in einem Zeitraum von drei Monaten stattfinden. Ich habe berechnet, dass ich die Kosten für Waren innerhalb des Dreimonatszeitraums von 1.000 USD verkauft habe. Die jährliche Umsatzrate beträgt 4.000 USD (1.000 USD / 3) * 12. Das Anfangsinventar ist 0. Das Endinventar ist 0. Mein durchschnittliches Inventar ist jetzt 0. Ich habe einen Umsatz von 4000 USD pro Jahr und kein Inventar. Dies ergibt eine unendliche Anzahl von Windungen. Dies bedeutet, dass mein gesamtes Inventar von Kunden konvertiert und gekauft wird.
Dies ist eine Geschäftsregel für die Berechnung von Lagerumschlägen.
quelle
quelle
Filtern Sie Daten mithilfe einer where-Klausel heraus, damit Sie keine 0-Werte erhalten.
quelle
Manchmal ist 0 möglicherweise nicht geeignet, aber manchmal ist 1 auch nicht geeignet. Manchmal kann auch ein Sprung von 0 auf 100.000.000, der als 1 oder 100-prozentige Änderung beschrieben wird, irreführend sein. In diesem Szenario könnten 100.000.000 Prozent angemessen sein. Es hängt davon ab, welche Art von Schlussfolgerungen Sie aufgrund der Prozentsätze oder Verhältnisse ziehen möchten.
Zum Beispiel kann ein sehr kleinverkaufter Artikel, der von 2-4 verkauft wird, und ein sehr großverkaufter Artikel, der von 1.000.000 auf 2.000.000 verkauft wird, für einen Analysten oder das Management sehr unterschiedliche Bedeutungen haben, aber beide werden zu 100% oder 1 durchkommen Veränderung.
Es ist möglicherweise einfacher, NULL-Werte zu isolieren, als eine Reihe von 0% - oder 100% -Zeilen zu durchsuchen, die mit legitimen Daten gemischt sind. Oft kann eine 0 im Nenner auf einen Fehler oder einen fehlenden Wert hinweisen, und Sie möchten möglicherweise nicht nur einen beliebigen Wert eingeben, damit Ihr Datensatz ordentlich aussieht.
quelle
So habe ich es behoben:
IIF (WertA! = 0, Gesamt / WertA, 0)
Es kann in ein Update eingeschlossen werden:
SET Pct = IIF (WertA! = 0, Gesamt / WertA, 0)
Oder in einer Auswahl:
SELECT IIF (WertA! = 0, Gesamt / WertA, 0) AS Pct FROM Tablename;
Gedanken?
quelle
Sie können den Fehler entsprechend behandeln, wenn er an das aufrufende Programm zurückgegeben wird (oder ihn ignorieren, wenn Sie dies wünschen). In C # lösen alle Fehler, die in SQL auftreten, eine Ausnahme aus, die ich abfangen und dann in meinem Code behandeln kann, genau wie jeder andere Fehler.
Ich stimme Beska darin zu, dass Sie den Fehler nicht verbergen möchten. Möglicherweise haben Sie es nicht mit einem Kernreaktor zu tun, aber das Ausblenden von Fehlern im Allgemeinen ist eine schlechte Programmierpraxis. Dies ist einer der Gründe, warum die meisten modernen Programmiersprachen eine strukturierte Ausnahmebehandlung implementieren, um den tatsächlichen Rückgabewert mit einem Fehler- / Statuscode zu entkoppeln. Dies gilt insbesondere, wenn Sie Mathe machen. Das größte Problem ist, dass Sie nicht zwischen einer korrekt berechneten 0, die zurückgegeben wird, oder einer 0 als Ergebnis eines Fehlers unterscheiden können. Stattdessen ist jeder zurückgegebene Wert der berechnete Wert. Wenn etwas schief geht, wird eine Ausnahme ausgelöst. Dies hängt natürlich davon ab, wie Sie auf die Datenbank zugreifen und welche Sprache Sie verwenden. Sie sollten jedoch immer in der Lage sein, eine Fehlermeldung zu erhalten, mit der Sie umgehen können.
quelle
Verwenden Sie
NULLIF(exp,0)
aber auf diese Weise -NULLIF(ISNULL(exp,0),0)
NULLIF(exp,0)
bricht, wenn exp ist,null
aberNULLIF(ISNULL(exp,0),0)
nicht brechen wirdquelle