Error 8134 oznacza próbę dzielenia przez zero podczas wykonywania zapytania lub operacji obliczeniowej w bazie danych.
Co oznacza komunikat SQL Server Error 8134
Error 8134 w Microsoft SQL Server oznacza wykonanie operacji dzielenia, w której mianownik ma wartość zero. Dotyczy to zarówno prostego wyrażenia arytmetycznego, jak i obliczeń wykonywanych w zapytaniu SELECT, instrukcji UPDATE, INSERT lub DELETE, a także wyrażeń używanych w widokach, funkcjach i procedurach składowanych. Przykładem jest zapytanie SELECT 10 / 0; albo obliczenie marży, w którym cena zakupu wynosi zero.
Problem nie oznacza zwykle uszkodzenia samego silnika bazy danych. Jest sygnałem, że dane wejściowe albo logika zapytania dopuszczają przypadek, którego wyrażenie matematyczne nie obsługuje. Mianownik może pochodzić bezpośrednio z kolumny tabeli, parametru procedury, wyniku podzapytania lub agregacji. W praktyce błąd bywa widoczny dopiero po pojawieniu się konkretnego rekordu z zerową wartością, dlatego zapytanie może działać poprawnie dla większości danych, a zatrzymać się przy określonym zestawie wierszy.
Gdzie w zapytaniu powstaje dzielenie przez zero
Najpierw należy znaleźć wszystkie operatory dzielenia i ustalić, skąd pochodzi ich prawy operand, czyli mianownik. W wyrażeniu SUM(sprzedaz) / SUM(liczba_sztuk) problem może wynikać nie z pojedynczego rekordu, lecz z wyniku agregacji dla całej grupy. Jeżeli grupa nie zawiera sprzedanych sztuk, wartość SUM(liczba_sztuk) może być równa zero. Podobny przypadek występuje przy raportach grupowanych według daty, oddziału, produktu lub innego klucza.
Warto sprawdzić także wartości NULL. Samo NULL nie jest tym samym co zero: dzielenie przez wartość NULL zwykle prowadzi do wyniku NULL, natomiast mianownik równy zero powoduje Error 8134. Błąd może jednak pojawić się po wcześniejszym przekształceniu danych, na przykład po użyciu COALESCE(kolumna, 0). Taka konstrukcja zamienia brak wartości na zero i może nieoczekiwanie wprowadzić niedozwolony mianownik. Należy przeanalizować również typy danych oraz kolejność obliczeń, ponieważ konwersje i wyrażenia zagnieżdżone mogą ukrywać miejsce, w którym powstaje zero.
Bezpieczne zabezpieczenie mianownika w T-SQL
Typowym sposobem ochrony dzielenia w SQL Server jest użycie funkcji NULLIF. Konstrukcja licznik / NULLIF(mianownik, 0) zamienia mianownik równy zero na NULL, dzięki czemu wynik całego dzielenia również staje się NULL, zamiast powodować Error 8134. Jeżeli raport ma pokazywać inną wartość w takim przypadku, wynik można następnie obsłużyć funkcją COALESCE, na przykład COALESCE(licznik / NULLIF(mianownik, 0), 0). Zastąpienie wyniku zerem powinno jednak odpowiadać znaczeniu biznesowemu danych, ponieważ brak możliwości wyliczenia wskaźnika nie zawsze oznacza wartość zero.
Alternatywą jest wyrażenie CASE, które jawnie rozdziela przypadek prawidłowego i zerowego mianownika, na przykład CASE WHEN mianownik = 0 THEN NULL ELSE licznik / mianownik END. W złożonych zapytaniach nie należy zakładać, że sam warunek w innym miejscu zapytania zawsze ochroni przed obliczeniem dzielenia. Optymalizator SQL Server może przekształcać plan wykonania, dlatego bezpieczniej zabezpieczyć bezpośrednio każde wyrażenie dzielenia, zwłaszcza gdy mianownik jest wynikiem agregacji lub podzapytania.
Ustawienia sesji, takie jak ARITHABORT i ANSI_WARNINGS, mogą wpływać na zachowanie niektórych operacji arytmetycznych i sposób kończenia instrukcji, ale nie powinny służyć jako podstawowa metoda naprawy błędu. Wyłączanie ostrzeżeń może ukryć problem jakości danych albo spowodować różnice między wykonaniem zapytania w aplikacji, narzędziu administracyjnym i zadaniu uruchamianym automatycznie. Trwałe rozwiązanie polega na określeniu, czy zero jest prawidłową wartością, poprawieniu danych lub jawnej obsłudze tego przypadku w kodzie T-SQL.
Postępowanie przy błędzie w działającej bazie
Diagnostykę należy rozpocząć od odtworzenia błędu na kontrolowanym zapytaniu i zapisania pełnego tekstu instrukcji, parametrów oraz kontekstu jej uruchomienia. Następnie warto sprawdzić mianowniki osobno, używając warunku WHERE mianownik = 0, a przy agregacjach pogrupować dane i wyszukać grupy, dla których wartość mianownika wynosi zero. Trzeba ustalić, czy zero jest wynikiem błędnego importu, niepełnych danych, nieprawidłowego filtra, pustej grupy, czy dozwolonego stanu oznaczającego brak podstaw do obliczenia. Samo usunięcie rekordów z zerem może pozbawić raport istotnych danych.
Jeżeli błąd występuje w aplikacji, należy sprawdzić także sposób obsługi wyjątku po stronie programu. Przerwana instrukcja może pozostawić użytkownika bez wyniku, a nieprawidłowo zaprojektowana obsługa może zapisać częściowy stan albo pokazać wskaźnik jako zero bez wyjaśnienia. W procedurach modyfikujących dane istotne jest sprawdzenie transakcji i wycofania zmian po błędzie. Po korekcie należy przetestować normalny przypadek, mianownik równy zero, wartość NULL, liczby ujemne oraz bardzo duże wartości, aby wykluczyć dodatkowe problemy z typem danych lub przepełnieniem.
W przypadku błędu pojawiającego się na komputerze używanym do pracy z aplikacją konieczne może być zebranie informacji o nazwie programu, czasie wystąpienia, wykonywanej operacji i komunikacie zwróconym przez bazę. Takie dane pozwalają odróżnić problem w zapytaniu od problemu z połączeniem lub konfiguracją klienta. Diagnostyka powinna obejmować również wersję używanego programu, ponieważ aplikacja może wysyłać do SQL Server zapytania generowane automatycznie, których użytkownik nie widzi bezpośrednio.