Implementowanie obsługi błędów języka T-SQL

Ukończone

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.