Implementowanie obsługi błędów języka T-SQL
Błąd wskazuje problem lub godny uwagi problem, który występuje podczas operacji bazy danych. Błędy mogą być generowane przez aparat bazy danych programu SQL Server w odpowiedzi na zdarzenie lub awarię na poziomie systemu; lub możesz wygenerować błędy aplikacji w kodzie Transact-SQL.
Elementy błędów silnika bazy danych
Niezależnie od przyczyny każdy błąd składa się z następujących elementów:
- Numer błędu — unikatowy numer identyfikujący określony błąd.
- Komunikat o błędzie — tekst opisujący błąd.
- Ważność — numeryczne wskazanie powagi z zakresu od 1 do 25.
- State - wewnętrzny kod stanu dla silnika bazy danych.
- Procedura — nazwa procedury składowanej lub wyzwalacza, w którym wystąpił błąd.
- Numer wiersza — która instrukcja w partii lub procedurze wygenerowała błąd.
Błędy systemowe
Błędy systemowe są wstępnie zdefiniowane i można je wyświetlić w widoku systemu sys.messages . W przypadku wystąpienia błędu systemu program SQL Server może podjąć automatyczne działanie naprawcze w zależności od ważności błędu. Na przykład w przypadku wystąpienia błędu o wysokiej ważności, program SQL Server może przełączyć bazę danych w tryb offline, a nawet zatrzymać usługę aparatu baz danych.
Błędy niestandardowe
Błędy w kodzie Transact-SQL można wygenerować w odpowiedzi na warunki specyficzne dla aplikacji lub dostosować informacje wysyłane do aplikacji klienckich w odpowiedzi na błędy systemowe. Te błędy aplikacji można zdefiniować w tekście, w którym są generowane, lub można je wstępnie zdefiniować w tabeli sys.messages wraz z błędami dostarczonymi przez system. Numery błędów używane w przypadku błędów niestandardowych muszą mieć wartość 50001 lub nowszą.
Aby dodać niestandardowy komunikat o błędzie do pliku sys.messages, użyj sp_addmessage. Użytkownik, który ma wysłać komunikat, musi być członkiem jednej ze stałych ról serwera: sysadmin lub serveradmin.
Jest to składnia sp_addmessage:
sp_addmessage [ @msgnum= ] msg_id , [ @severity= ] severity , [ @msgtext= ] 'msg'
[ , [ @lang= ] 'language' ]
[ , [ @with_log= ] { 'TRUE' | 'FALSE' } ]
[ , [ @replace= ] 'replace' ]
Oto przykład niestandardowego komunikatu o błędzie przy użyciu tej składni:
sp_addmessage 50001, 10, N’Unexpected value entered’;
Ponadto można zdefiniować niestandardowe komunikaty o błędach, członkowie roli serwera sysadmin mogą również użyć dodatkowego parametru , @with_log. Po ustawieniu wartości TRUE błąd zostanie również zarejestrowany w dzienniku aplikacji systemu Windows. Każdy komunikat zapisany w dzienniku aplikacji systemu Windows jest również zapisywany w dzienniku błędów programu SQL Server. Bądź rozsądny, stosując opcję @with_log, ponieważ administratorzy sieci i systemu nie lubią aplikacji, które są nadmiarowe w dziennikach systemowych. Jednak, jeśli błąd musi zostać wychwycony przez alert, najpierw musi być zapisany w dzienniku aplikacji systemu Windows.
Uwaga / Notatka
Zgłaszanie błędów systemowych nie jest obsługiwane.
Komunikaty można zastąpić, używając opcji @replace 'replace', bez konieczności ich uprzedniego usunięcia.
Komunikaty można dostosowywać, a także dodawać różne komunikaty dla tego samego numeru błędu w wielu językach, na podstawie wartości identyfikatora języka.
Uwaga / Notatka
Wiadomości w języku angielskim mają identyfikator językowy language_id 1033.
Zgłaszanie błędów przy użyciu RAISERROR
Zarówno PRINT, jak i RAISERROR mogą służyć do zwracania informacji lub komunikatów ostrzegawczych do aplikacji. Funkcja RAISERROR umożliwia aplikacjom zgłaszanie błędu, który może zostać przechwycony przez proces wywołujący.
RAISERROR
Możliwość zgłaszania błędów w języku T-SQL sprawia, że obsługa błędów w aplikacji jest łatwiejsza, ponieważ jest wysyłana jak każdy inny błąd systemu. Funkcja RAISERROR służy do:
- Pomoc dotycząca rozwiązywania problemów z kodem T-SQL.
- Sprawdź wartości danych.
- Zwraca komunikaty zawierające zmienny tekst.
Uwaga / Notatka
Użycie instrukcji PRINT jest podobne do zgłaszania błędu poziomu istotności 10.
Oto przykład niestandardowego komunikatu o błędzie za pomocą RAISERROR.
RAISERROR (N'%s %d', -- Message text,
10, -- Severity,
1, -- State,
N'Custom error message number',
2)
Po uruchomieniu funkcji, zwraca ona:
Custom error message number 2
W poprzednim przykładzie %d jest symbolem zastępczym dla liczby, a %s jest symbolem zastępczym ciągu. Ponadto należy zauważyć, że numer wiadomości nie został wymieniony. Gdy błędy z ciągami komunikatów są wywoływane przy użyciu tej składni, zawsze mają numer błędu 50000.
Zgłaszanie błędów przy użyciu THROW
Instrukcja THROW oferuje prostszą metodę zgłaszania błędów w kodzie. Błędy muszą mieć numer błędu co najmniej 50000.
RZUCAĆ
THROW różni się od RAISERROR na kilka sposobów:
- Błędy zgłaszane przez funkcję THROW mają zawsze poziom istotności 16.
- Komunikaty zwracane przez polecenie THROW nie są powiązane z żadnymi wpisami w pliku sys.sysmessages.
- Błędy zgłaszane przez funkcję THROW powodują przerwanie transakcji tylko wtedy, gdy są używane w połączeniu z SET XACT_ABORT ON i sesja zostanie zakończona.
THROW 50001, 'An Error Occured',0
Przechwytywanie kodów błędów przy użyciu @@Error
Większość tradycyjnego kodu obsługi błędów w aplikacjach programu SQL Server została utworzona przy użyciu @@ERROR. Obsługa wyjątków strukturalnych została wprowadzona w programie SQL Server 2005 i stanowi silną alternatywę dla używania @@ERROR. Zostanie omówiona w następnej lekcji. Duża ilość istniejącego kodu obsługi błędów programu SQL Server jest oparta na @@ERROR, dlatego ważne jest, aby zrozumieć, jak z nim pracować.
BŁĄD
@@ERROR jest zmienną systemową, która zawiera numer ostatniego wystąpionego błędu. Jednym z ważnych wyzwań z @@ERROR jest to, że wartość, którą przechowuje, jest automatycznie resetowana podczas wykonywania każdej dodatkowej instrukcji.
Rozważmy na przykład następujący kod:
RAISERROR(N'Message', 16, 1);
IF @@ERROR <> 0
PRINT 'Error=' + CAST(@@ERROR AS VARCHAR(8));
GO
Może się spodziewać, że po wykonaniu kodu zostanie zwrócony numer błędu w drukowanym ciągu. Jednak po wykonaniu kodu zwraca on następujące elementy:
Msg 50000, Level 16, State 1, Line 1
Message
Error=0
Błąd został zgłoszony, ale wyświetlony komunikat to "Error=0". W pierwszym wierszu danych wyjściowych widać, że błąd, zgodnie z oczekiwaniami, był rzeczywiście 50000, z komunikatem przekazanym do RAISERROR. Dzieje się tak, ponieważ instrukcja IF zgodna z instrukcją RAISERROR została wykonana pomyślnie i spowodowała zresetowanie wartości @@ERROR. Z tego powodu podczas pracy z @@ERROR ważne jest, aby numer błędu przechwycić do zmiennej natychmiast po jego wystąpieniu, a następnie kontynuować przetwarzanie za pomocą tej zmiennej.
Przyjrzyj się następującemu kodowi, który to demonstruje:
DECLARE @ErrorValue int;
RAISERROR(N'Message', 16, 1);
SET @ErrorValue = @@ERROR;
IF @ErrorValue <> 0
PRINT 'Error=' + CAST(@ErrorValue AS VARCHAR(8));
Po wykonaniu tego kodu zwraca on następujące dane wyjściowe:
Msg 50000, Level 16, State 1, Line 2
Message
Error=50000
Numer błędu jest teraz poprawnie zgłaszany.
Scentralizowana obsługa błędów
Innym istotnym problemem z używaniem @@ERROR do obsługi błędów jest to, że trudno jest scentralizować kod T-SQL. Obsługa błędów zazwyczaj jest rozproszona w całym kodzie. W pewnym stopniu można scentralizować obsługę błędów przy użyciu @@ERROR przy użyciu etykiet i instrukcji GOTO. Jednak większość deweloperów dzisiaj uznałaby to za słabą praktykę programistyczną.
Tworzenie alertów o błędach
W przypadku niektórych kategorii błędów administratorzy mogą tworzyć alerty programu SQL Server, ponieważ chcą otrzymywać powiadomienia natychmiast po ich wystąpieniu. Może to nawet dotyczyć komunikatów o błędach zdefiniowanych przez użytkownika. Możesz na przykład zgłosić alert za każdym razem, gdy zostanie wypełniony dziennik transakcji. Alerty są często używane do zwracania uwagi administratorów na błędy o wysokiej ważności (takie jak ważność 19 lub nowsza).
Zgłaszanie alertów
Alerty można tworzyć dla określonych komunikatów o błędach. Usługa alarmująca działa, rejestrując się jako usługa wywołania zwrotnego w usłudze rejestrowania zdarzeń. Oznacza to, że alerty działają tylko na zarejestrowanych błędach.
Istnieją dwa sposoby, aby błąd wygenerował alert — możesz użyć opcji WITH LOG podczas zgłaszania błędu lub zmienić komunikat, aby był logowany, wykonując sp_altermessage. Opcja WITH LOG ma wpływ tylko na bieżącą instrukcję. Użycie sp_altermessage zmienia zachowanie błędu dla wszystkich przyszłych użyć. Modyfikowanie błędów systemowych za pośrednictwem sp_altermessage jest możliwe tylko z programu SQL Server 2005 z dodatkiem SP3 lub SQL Server 2008 z dodatkiem SP1.