Wprowadzenie

W tym artykule skupię się na podstawach obsługi błędów za pomocą bloku TRY CATCH, który został wprowadzony w SQL Server 2005. Opiszę podstawowe funkcje do zwracania informacji dotyczących błędów oraz pokaże jak używać bloku TRY CATCH w procedurach składowanych i transakcjach.

SQL Server używa poniższej składni do przechwytywania wyjątków:

BEGIN TRY
	SELECT [FIRST] = 1
	SELECT [SECOND] = 1/0
	SELECT [THIRD] = 3
END TRY
BEGIN CATCH
	PRINT 'An error occurred'
END CATCH
Wywołanie spowoduje zwrócenie następującego wyniku:
-- (1 row(s) affected)
--
-- (0 row(s) affected)
-- An error occurred
Kluczową różnicą w porównaniu do SQL Server 2000 jest zatrzymanie wykonywania instrukcji. W nowszych wersjach realizacja zadania przenosi się do bloku CATCH. Ten błąd nie jest zwracany do aplikacji klienckiej lub programu wywołującego.

Funkcje błędów

Wewnątrz bloku TRY CATCH znajduje się szereg wyspecjalizowanych funkcji służących do zwracania informacji o błędzie:

BEGIN TRY
	SELECT [FIRST] = 1/0
END TRY
BEGIN CATCH
	SELECT
		[ErrorLine] = ERROR_LINE(),
		[ErrorNumber] = ERROR_NUMBER(),
		[ErrorSeverity] = ERROR_SEVERITY(),
		[ErrorState] = ERROR_STATE(),
		[ErrorMessage] = ERROR_MESSAGE()
END CATCH
Tak prezentują się zwracane informacje:
-- FIRST
-- -----------
--
-- (0 row(s) affected)
--
-- Error_Line  Error_Number Error_Severity Error_State ErrorMessage
-- --------- ------------ -------------- ----------- -------------
-- 2           8134         16             1         Divide by zero error encountered.
--
-- (1 row(s) affected)
Poniżej lista funkcji, które możesz wykorzystać w bloku CATCH. Funkcję te zwracają wartość NULL jeżeli będą wywołane poza tym blokiem.
  • ERROR_NUMBER - liczba wystąpień błędu. Podobne do parametru @@ERROR z tym, że zwraca ten sam numer przez cały czas trwania bloku CATCH;
  • ERROR_MESSAGE - pełny tekst komunikatu o błędzie zawierający wszystkie parametry, np. nazwa obiektu;
  • ERROR_LINE - numer linii w której pojawił się błąd;
  • ERROR_SEVERITY - rygor zgłoszonego błędu. Blok CATCH zostaje użyty jeżeli zgłoszony błąd ma numer 11 lub większy. Poziom błędów od 11 do 16 oznacza zwykle błędy użytkownika lub kodu. Poziom 17 do 25 to zwykle błędy oprogramowania lub sprzętu w przypadku których dalsze wykonywanie instrukcji nie jest możliwe;
  • ERROR_STATE - czasami używane przez system do zwrócenia większej liczby informacji o błędzie.
  • ERROR_PROCEDURE - jeżeli błąd został wygenerowany wewnątrz procedury składowej będzie to jej nazwa.

Wyłapywanie błędów w procedurach składowanych

Blok TRY CATCH może wyłapywać błędy w procedurach składowanych wywoływanych prze inne procedury skadowane. Przykład:

BEGIN TRY
	EXEC ParentError
END TRY
BEGIN CATCH
	SELECT ErroLine = ERROR_LINE(),
		   ErrorProc = ERROR_PROCEDURE()
END CATCH
Na potrzeby powyższego przykładu zakładamy, że procedura ParrentError wywołuje procedurę ChildError, która generuje błąd. Wówczas zobaczymy poniższy komunikat:
-- Error_Line  Error_Proc
-- ----------- -------------
-- 5           ChildError

Obsługa błędów a transakcje

Blok TRY CATCH działa również z transakcjami. Poniżej przedstawiam ogólny wzór użycia tego bloku wewnątrz procedur składowanych dla transakcji. Wszystkie błędy powodują operację cofnięcia instrukcji wykonanych w ramach transakcji.

BEGIN TRY
	BEGIN TRANSACTION
	INSERT INTO Person.Address (AddressLine1,AddressLine2)
	VALUES ('AddressLine1', 'AddressLine2')
	INSERT INTO Person.AddressType (Name)
	VALUES ('AddresTypeTest')
	COMMIT TRANSACTION
END TRY
BEGIN CATCH
	IF @@TRANCOUNT > 0 
		ROLLBACK TRANSACTION
	-- dodaj obsługę błędów:
    SELECT [Error_Line] = ERROR_LINE(),
           [Error_Number] = ERROR_NUMBER(),
           [Error_Severity] = ERROR_SEVERITY(),
           [Error_State] = ERROR_STATE(),
		   [Error_Message] = ERROR_MESSAGE()
END CATCH
Wywołanie zwróci błąd spowodowany próbą dodania wartości NULL do kolumny City.