| Termin | Definicja |
|---|---|
| Funkcja ERROR_LINE() | Funkcja ERROR_LINE() zwraca numer linii kodu, w której wystąpił błąd w bloku obsługi wyjątków. Funkcja ERROR_LINE() – czym jest i do czego służyFunkcja ERROR_LINE() w języku Transact-SQL służy do ustalenia numeru wiersza instrukcji, przy której wystąpił błąd obsługiwany w bloku CATCH. Jest używana razem z konstrukcją TRY...CATCH, czyli mechanizmem pozwalającym przechwycić wyjątek, odczytać jego szczegóły i zdecydować, co powinno wydarzyć się dalej. Zwracany numer nie jest komunikatem opisującym problem, lecz dodatkową informacją lokalizującą miejsce wystąpienia błędu w kodzie. Najczęściej funkcja ERROR_LINE() pojawia się w procedurze obsługi wyjątków, obok funkcji ERROR_MESSAGE(), ERROR_NUMBER(), ERROR_SEVERITY(), ERROR_STATE() oraz ERROR_PROCEDURE(). Dzięki takiemu zestawieniu można zbudować czytelny zapis diagnostyczny. Numer linii pomaga szybko przejść do właściwego fragmentu procedury, wyzwalacza lub innego kodu wykonywanego przez silnik bazy danych. Ma to szczególne znaczenie wtedy, gdy większa procedura zawiera wiele operacji, zagnieżdżone instrukcje warunkowe i kilka miejsc, w których może dojść do niepowodzenia. W podstawowym ujęciu działanie wygląda następująco: kod wykonywany w sekcji TRY powoduje błąd, sterowanie przechodzi do sekcji CATCH, a wywołanie ERROR_LINE() zwraca numer linii związany z obsługiwanym błędem. Funkcja nie wymaga argumentów, dlatego zapis ma postać ERROR_LINE(). Wynik jest liczbą całkowitą albo wartością NULL, gdy funkcja zostanie wywołana poza właściwym kontekstem obsługi wyjątku. ERROR_LINE() w kontekście technicznym i porównanie z innymi funkcjamiWarto odróżnić numer linii zwracany przez ERROR_LINE() od numeru błędu zwracanego przez ERROR_NUMBER(). Pierwsza funkcja odpowiada na pytanie, gdzie w kodzie pojawił się problem, natomiast druga wskazuje, jaki typ błędu został zgłoszony. ERROR_MESSAGE() dostarcza opis słowny, ERROR_PROCEDURE() może wskazać nazwę procedury, a ERROR_SEVERITY() i ERROR_STATE() przekazują dodatkowe właściwości zdarzenia. Żadna z tych funkcji nie zastępuje ERROR_LINE(), ponieważ każda opisuje inną cechę tego samego wyjątku. Przykładowy schemat obsługi może wyglądać następująco: W tym przykładzie dzielenie przez zero powoduje przejście do sekcji CATCH. Funkcja ERROR_LINE() zwraca położenie instrukcji SELECT 1 / 0 w obrębie kodu objętego obsługą wyjątku. Jeżeli kod zostanie przeniesiony, rozbudowany albo uzupełniony o dodatkowe instrukcje, numer może się zmienić. Dlatego sam numer linii nie powinien być traktowany jako trwały identyfikator problemu. Najlepszą wartość diagnostyczną uzyskuje się przez zapisanie go razem z nazwą procedury, komunikatem, numerem błędu oraz czasem wystąpienia zdarzenia. Istotne jest także rozróżnienie ERROR_LINE() od funkcji używanych do informacji o bieżącym wykonaniu. Numer bieżącej linii w kodzie nie jest tym samym co pozycja błędu. ERROR_LINE() odnosi się do linii, która doprowadziła do wyjątku przechwyconego przez CATCH. W przypadku procedur wywołujących inne procedury trzeba analizować cały łańcuch wykonania, ponieważ błąd może powstać w kodzie podrzędnym, a zostać przechwycony wyżej. Wtedy pomocne jest równoczesne wykorzystanie ERROR_PROCEDURE() i ERROR_LINE(). Ważna jest również perspektywa zagnieżdżonych bloków TRY...CATCH. Jeżeli wyjątek zostanie przechwycony wewnątrz niższego bloku, ERROR_LINE() wywołane w tym bloku odnosi się do miejsca pierwotnego problemu. Jeżeli błąd zostanie przekazany dalej i przechwycony przez zewnętrzny blok, wynik należy interpretować razem z nazwą procedury i pełnym komunikatem. Pozwala to uniknąć błędnego założenia, że numer zawsze wskazuje linię w najbardziej zewnętrznym fragmencie kodu. Typowe problemy przy stosowaniu ERROR_LINE()Jednym z częstych problemów jest wywołanie ERROR_LINE() poza sekcją CATCH. Funkcja została zaprojektowana do odczytu informacji o aktualnie obsługiwanym wyjątku. Po opuszczeniu tego kontekstu wynik może być pusty, dlatego dane powinny zostać odczytane i zapisane bezpośrednio w bloku obsługi. Dotyczy to także sytuacji, w której tworzony jest pomocniczy fragment kodu odpowiedzialny za rejestrowanie błędów. Jeżeli rejestracja nastąpi zbyt późno, część informacji może nie być już dostępna w oczekiwanej postaci. Inną trudnością jest mylenie numeru linii z numerem instrukcji w całym projekcie. ERROR_LINE() nie wskazuje pozycji w edytorze wszystkich plików ani miejsca w aplikacji wywołującej procedurę. Informacja dotyczy kodu, w którym silnik wykrył błąd i który pozostaje objęty obsługą TRY...CATCH. Jeżeli procedura jest wywoływana przez aplikację, log aplikacji może wskazywać inną lokalizację niż log po stronie bazy. Oba zapisy należy zestawić, zamiast traktować jeden z nich jako zamiennik drugiego. Trzeba również uwzględnić błędy związane z dynamicznym wykonywaniem kodu. Gdy instrukcja jest tworzona jako tekst i uruchamiana podczas działania, numer linii może odnosić się do tego dynamicznego fragmentu, a nie do miejsca, w którym tekst został przygotowany. W takich przypadkach sam wynik ERROR_LINE() może nie wystarczyć. Przydatne bywa rejestrowanie treści wykonywanego polecenia, parametrów przekazanych do procedury oraz nazwy procedury, która uruchomiła dany fragment. Problemy interpretacyjne pojawiają się także wtedy, gdy kod jest regularnie zmieniany, a logi przechowują wyłącznie numer linii. Po wdrożeniu nowej wersji numer może wskazywać inną instrukcję niż w momencie zapisu zdarzenia. Z tego powodu do diagnostyki warto dołączyć oznaczenie wersji kodu, nazwę obiektu oraz pełny komunikat błędu. Taki zestaw informacji ułatwia odtworzenie warunków wystąpienia problemu po późniejszej aktualizacji. Nie należy też zakładać, że każdy błąd zostanie przechwycony w identyczny sposób. Niektóre sytuacje mogą zatrzymać wykonanie na poziomie, na którym zwykła obsługa TRY...CATCH nie dostarczy oczekiwanych danych. W praktyce analizuje się więc nie tylko ERROR_LINE(), lecz także rodzaj wyjątku, moment jego powstania i sposób wywołania kodu. Funkcja jest bardzo użyteczna, ale stanowi jeden element całego mechanizmu diagnostycznego. Praktyczne wskazówki dla ERROR_LINE() w logowaniu błędówNajbezpieczniejszym rozwiązaniem jest utworzenie jednolitego formatu logu. W sekcji CATCH można zapisać numer linii, numer błędu, treść komunikatu, nazwę procedury, poziom ważności oraz stan. Dzięki temu kolejne zdarzenia mają podobną strukturę i można je łatwiej filtrować. Warto również zapisać moment wystąpienia błędu oraz informacje o operacji, która była wykonywana, o ile nie zawierają danych poufnych. Dobrym zwyczajem jest używanie ERROR_LINE() razem z instrukcją ponownego zgłaszania błędu. Jeżeli kod ma jedynie zarejestrować problem i przekazać go wyżej, należy zadbać o zachowanie pierwotnego kontekstu. Samodzielne tworzenie nowego komunikatu bez dołączenia informacji o źródle może utrudnić późniejsze ustalenie przyczyny. Z kolei zbyt ogólny opis, taki jak „wystąpił błąd”, nie daje osobie analizującej log wystarczających danych. Numer linii powinien być traktowany jako wskazówka do rozpoczęcia analizy. Po jego odczytaniu należy sprawdzić instrukcję znajdującą się w tym miejscu, wartości parametrów, zależności między tabelami oraz warunki, które doprowadziły do wykonania konkretnej gałęzi kodu. Czasem błąd jest skutkiem wcześniejszego działania, a wskazana linia jedynie ujawnia problem. Przykładem może być próba zapisania wartości przygotowanej w nieprawidłowy sposób albo użycie danych, które nie spełniają ograniczeń tabeli. W większych procedurach przydatne bywa dodanie własnych punktów kontrolnych. Można zapisać nazwę etapu przed wykonaniem grupy operacji, a po wystąpieniu błędu połączyć tę nazwę z wynikiem ERROR_LINE(). W ten sposób wiadomo nie tylko, w której linii pojawił się wyjątek, ale również jaka część procesu była wtedy realizowana. Takie podejście pomaga zwłaszcza wtedy, gdy kilka instrukcji znajduje się blisko siebie albo gdy kod generuje polecenia zależne od danych wejściowych. Przy testowaniu warto sprawdzić kilka wariantów: błąd składniowy, naruszenie ograniczenia, nieprawidłowe dane, brak oczekiwanego obiektu oraz wyjątek powstały wewnątrz wywołanej procedury. Dla każdego wariantu można zweryfikować, czy ERROR_LINE() wskazuje oczekiwaną linię i czy zapis w logu zawiera komplet informacji. Test powinien obejmować również ścieżkę bez błędu, aby upewnić się, że kod nie zapisuje pustych lub mylących wpisów. Kiedy zgłosić problem związany z ERROR_LINE() do serwisuDo serwisu warto zgłosić się wtedy, gdy komunikaty o błędach pojawiają się cyklicznie, aplikacja niespodziewanie przerywa pracę, dane nie zapisują się prawidłowo albo analiza kodu wymaga sprawdzenia środowiska komputera. Szczególnie pomocne będzie przekazanie dokładnej treści komunikatu, numeru linii zwróconego przez ERROR_LINE(), nazwy używanej procedury oraz informacji o czynności wykonywanej tuż przed wystąpieniem problemu. Nie należy przesyłać haseł, kluczy dostępowych ani pełnych danych użytkowników. Warszawskie Pogotowie Komputerowe 24/7 może pomóc w uporządkowaniu informacji diagnostycznych i w sprawdzeniu, czy źródło problemu leży w oprogramowaniu, konfiguracji systemu lub stanie komputera. Przy zgłoszeniu dobrze opisać, czy błąd występuje zawsze, czy tylko przy określonych danych, oraz czy pojawił się po aktualizacji. Tak przygotowane zgłoszenie ułatwia odtworzenie sytuacji i ogranicza ryzyko pominięcia istotnego szczegółu. W przypadku ERROR_LINE() nie zawsze konieczna jest natychmiastowa zmiana kodu. Najpierw warto ustalić, czy wskazana linia jest źródłem wyjątku, czy tylko miejscem, w którym problem stał się widoczny. Dopiero po porównaniu logów, kodu i warunków wykonania można zdecydować, czy potrzebna jest korekta procedury, zmiana danych, uzupełnienie obsługi błędu, czy też diagnostyka komputera używanego do pracy. Takie metodyczne podejście pozwala ograniczyć przypadkowe modyfikacje i zachować czytelny mechanizm rejestrowania błędów. |