Oto pięć opcji postępowania z komunikatem o błędzie 8134 „Wystąpił błąd dzielenia przez zero” w SQL Server.
Błąd
Po pierwsze, oto przykład kodu, który generuje błąd, o którym mówimy:
SELECT 1 / 0;
Wynik:
Msg 8134, Level 16, State 1, Line 1 Divide by zero error encountered.
Otrzymujemy błąd, ponieważ próbujemy podzielić liczbę przez zero. Matematycznie to nie ma sensu. Nie możesz podzielić liczby przez zero i oczekiwać znaczącego wyniku.
Aby poradzić sobie z tym błędem, musimy zdecydować, co powinno zostać zwrócone, gdy próbujemy dzielić przez zero. Na przykład możemy chcieć, aby została zwrócona wartość null. Lub możemy chcieć, aby zwrócono zero. Albo jakaś inna wartość.
Poniżej znajduje się kilka opcji radzenia sobie z tym błędem.
Opcja 1:NULLIF()
Wyrażenie
Szybkim i łatwym sposobem radzenia sobie z tym błędem jest użycie NULLIF()
wyrażenie:
SELECT 1 / NULLIF( 0, 0 );
Wynik:
NULL
NULLIF()
zwraca NULL
jeśli dwa określone wyrażenia mają tę samą wartość. Zwraca pierwsze wyrażenie, jeśli oba wyrażenia są różne. Dlatego jeśli użyjemy zera jako drugiego wyrażenia, otrzymamy wartość null zawsze, gdy pierwsze wyrażenie będzie równe zero. Dzielenie liczby przez NULL
wyniki w NULL
.
W rzeczywistości SQL Server już zwraca NULL
na błędzie dzielenia przez zero, ale w większości przypadków tego nie widzimy, ze względu na nasz ARITHABORT
i ANSI_WARNINGS
ustawienia (więcej na ten temat później).
Opcja 2:Dodaj ISNULL()
Funkcja
W niektórych przypadkach możesz chcieć zwrócić wartość inną niż NULL
.
W takich przypadkach możesz przekazać poprzedni przykład do ISNULL()
funkcja:
SELECT ISNULL(1 / NULLIF( 0, 0 ), 0);
Wynik:
0
Tutaj określiłem, że zero powinno być zwracane za każdym razem, gdy wynik jest NULL
.
Bądź jednak ostrożny. W niektórych przypadkach zwrócenie zera może być niewłaściwe. Na przykład, jeśli masz do czynienia z dostawami zapasów, określenie zera może sugerować, że nie ma produktów, co może nie mieć miejsca.
Opcja 3:Użyj CASE
Oświadczenie
Innym sposobem na to jest użycie CASE
oświadczenie:
DECLARE @n1 INT = 20;
DECLARE @n2 INT = 0;
SELECT CASE
WHEN @n2 = 0
THEN NULL
ELSE @n1 / @n2
END
Wynik:
NULL
Opcja 4:SET ARITHABORT
Oświadczenie
SET ARITHABORT
Instrukcja kończy zapytanie, gdy podczas wykonywania zapytania wystąpi błąd przepełnienia lub dzielenia przez zero. Możemy go używać w połączeniu z SET ANSI WARNINGS
aby zwrócić NULL
kiedy może wystąpić błąd dzielenia przez zero:
SET ARITHABORT OFF;
SET ANSI_WARNINGS OFF;
SELECT 20 / 0;
Wynik:
NULL
Microsoft zaleca, aby zawsze ustawiać ARITHABORT
na ON
w twoich sesjach logowania i ustawienie go na OFF
może negatywnie wpłynąć na optymalizację zapytań, prowadząc do problemów z wydajnością.
Niektórzy klienci (np. SQL Server Management Studio) ustaw ARITHABORT
na ON
domyślnie. Dlatego prawdopodobnie nie widzisz NULL
wartość zwracana podczas dzielenia przez zero. Możesz użyć SET ARITHIGNORE
aby zmienić to zachowanie, jeśli wolisz.
Opcja 5:SET ARITHIGNORE
Oświadczenie
SET ARITHIGNORE
instrukcja kontroluje, czy komunikaty o błędach są zwracane z błędów przepełnienia lub dzielenia przez zero podczas zapytania:
SET ARITHABORT OFF;
SET ANSI_WARNINGS OFF;
SET ARITHIGNORE ON;
SELECT 1 / 0 AS Result_1;
SET ARITHIGNORE OFF;
SELECT 1 / 0 AS Result_2;
Wynik:
Commands completed successfully. Commands completed successfully. Commands completed successfully. +------------+ | Result_1 | |------------| | NULL | +------------+ (1 row affected) Commands completed successfully. +------------+ | Result_2 | |------------| | NULL | +------------+ Division by zero occurred.
Tutaj ustawiłem ARITHABORT
i ANSI_WARNINGS
na OFF
aby instrukcja nie została przerwana z powodu błędu, a NULL
jest zwracany, gdy wystąpi błąd dzielenia przez zero.
Zauważ, że SET ARITHIGNORE
ustawienie kontroluje tylko, czy zwracany jest komunikat o błędzie. SQL Server zwraca NULL
w obliczeniach obejmujących błąd przepełnienia lub dzielenia przez zero, niezależnie od tego ustawienia.
W powyższym przykładzie widzimy to, gdy ARITHIGNORE
jest ON
, dzielenie przez zero błędu nie jest zwracane. Kiedy jest OFF
, zwracany jest komunikat o błędzie dzielenia przez zero.