Serwisanci dostępni teraz · czynne całą dobę, także w weekendy i świętaWarszawa i okolice · dojazd bezpłatny
Darmowa diagnoza laptopa
Darmowa diagnoza laptopa
Dojazd do klienta bezpłatnie
Dojazd do klienta bezpłatnie
Laptopy zastępcze bezpłatnie
Laptopy zastępcze bezpłatnie
Odbiór i zwrot sprzętu bezpłatnie
Odbiór i zwrot sprzętu bezpłatnie

TRY...CATCH

Termin Definicja
TRY...CATCH

TRY...CATCH to konstrukcja T-SQL przechwytująca błędy wykonania i pozwalająca na nie zareagować.

TRY...CATCH jako mechanizm obsługi błędów w T-SQL

TRY...CATCH jest konstrukcją języka T-SQL służącą do kontrolowania sytuacji, w których wykonanie instrukcji SQL kończy się błędem. Jej działanie można porównać do dwóch powiązanych bloków: w części TRY umieszcza się operacje, które mogą się nie powieść, natomiast część CATCH zawiera reakcję na wykryty problem. Dzięki temu błąd nie musi kończyć całego procesu bez żadnego kontekstu. Można przechwycić informacje o zdarzeniu, wycofać niezatwierdzone zmiany, zapisać szczegóły do dziennika albo przekazać komunikat do warstwy aplikacji.

Nie jest to zwykły warunek sprawdzający wartość zwróconą przez zapytanie. Konstrukcja reaguje na błędy wykonania, takie jak naruszenie ograniczenia integralności, próba zapisania zbyt długiej wartości, problem z konwersją typu, odwołanie do nieistniejącego obiektu czy nieprawidłowa operacja w ramach transakcji. Ostateczny rezultat zależy od rodzaju błędu, poziomu jego ważności oraz miejsca, w którym wystąpił. Z tego powodu TRY...CATCH należy traktować jako element projektu procedury, a nie jedynie dopisek dodany po pojawieniu się komunikatu o błędzie.

Najprostszy schemat składa się z instrukcji BEGIN TRY, kodu operacji, END TRY, a następnie BEGIN CATCH, obsługi błędu i END CATCH. Bloki muszą występować w prawidłowej kolejności. W części CATCH można użyć funkcji ERROR_NUMBER(), ERROR_MESSAGE(), ERROR_SEVERITY(), ERROR_STATE(), ERROR_PROCEDURE() oraz ERROR_LINE(). Dostarczają one odpowiednio numer błędu, opis, poziom ważności, stan, nazwę procedury i numer wiersza, w którym nastąpiło zdarzenie. Zestaw tych informacji jest bardziej użyteczny diagnostycznie niż sam ogólny komunikat wyświetlony użytkownikowi.

TRY...CATCH a transakcje, atomowość i kontrola zmian

Największe znaczenie konstrukcja TRY...CATCH zyskuje w połączeniu z transakcjami. Jeżeli kilka instrukcji ma tworzyć jedną logiczną operację, częściowe wykonanie może doprowadzić do niespójności. Przykładem jest przeniesienie wartości między dwoma miejscami: zmniejszenie stanu w jednym rekordzie powinno być zatwierdzone razem ze zwiększeniem stanu w drugim. Gdy druga instrukcja zakończy się błędem, pozostawienie pierwszej zmiany może wprowadzić dane w stan trudny do odtworzenia.

Typowy wzorzec obejmuje rozpoczęcie transakcji w bloku TRY, wykonanie wszystkich powiązanych instrukcji, zatwierdzenie zmian po pomyślnym zakończeniu oraz wycofanie transakcji w bloku CATCH. Przy takim rozwiązaniu trzeba sprawdzić stan transakcji za pomocą XACT_STATE() albo wykorzystać @@TRANCOUNT, zależnie od przyjętej architektury. XACT_STATE() pozwala rozpoznać, czy transakcja jest aktywna i możliwa do zatwierdzenia, czy też stała się niezatwierdzalna i można ją jedynie wycofać.

W praktycznych procedurach często spotyka się schemat: jeśli istnieje aktywna transakcja, należy wykonać ROLLBACK, a następnie przekazać błąd dalej za pomocą THROW. Takie rozwiązanie zapobiega ukryciu problemu. Samo zapisanie błędu w tabeli i zakończenie procedury bez ponownego zgłoszenia może sprawić, że aplikacja uzna operację za udaną, mimo że zmiany zostały cofnięte. THROW zachowuje czytelny przepływ obsługi, a w odpowiednio przygotowanych przypadkach pozwala przekazać informację wyżej bez ręcznego składania całego komunikatu.

Warto odróżnić sytuację, w której transakcja została rozpoczęta przez bieżącą procedurę, od sytuacji, w której procedura działa wewnątrz transakcji przygotowanej przez kod wywołujący. Bezrefleksyjne COMMIT lub ROLLBACK może wtedy naruszyć założenia nadrzędnego procesu. Bezpieczniejszy projekt powinien jasno określać właściciela transakcji, zakres odpowiedzialności oraz sposób obsługi zagnieżdżonych wywołań.

TRY...CATCH i różnice między błędem składni a błędem wykonania

Nie każdy problem związany z instrukcją SQL zachowuje się tak samo. Błędy składni są wykrywane zanim dana partia zostanie wykonana, dlatego nie zawsze mogą zostać przechwycone przez TRY...CATCH znajdujący się w tej samej partii. Podobnie niektóre problemy powstające na poziomie kompilacji, wiązania nazw albo rozpoznawania obiektów mogą wystąpić poza zakresem lokalnego mechanizmu.

Inaczej wygląda błąd wykonania, który pojawia się już podczas realizacji konkretnej instrukcji. Wtedy przepływ przechodzi do bloku CATCH, o ile dane zdarzenie podlega przechwyceniu. Ma to znaczenie przy analizowaniu sytuacji, w których kod wydaje się prawidłowy, lecz zależność od schematu bazy, uprawnień, danych wejściowych albo bieżącego kontekstu powoduje nieoczekiwany rezultat.

W starszych rozwiązaniach można spotkać RAISERROR, jednak przy projektowaniu nowych procedur często wybiera się THROW. Oba mechanizmy służą do zgłaszania problemów, lecz różnią się składnią, zachowaniem przy ponownym zgłaszaniu oraz sposobem zachowania informacji o błędzie. RAISERROR nadal może być potrzebny ze względu na zgodność z istniejącym kodem, ale mieszanie obu podejść bez ustalonej reguły utrudnia analizę logów i obsługę po stronie aplikacji.

Warto również pamiętać, że TRY...CATCH nie zastępuje walidacji. Dane wejściowe powinny być sprawdzane przed wykonaniem operacji, jeżeli pozwala to uniknąć niepotrzebnego wyjątku. Walidacja pomaga przekazać użytkownikowi zrozumiałą informację, natomiast CATCH powinien zabezpieczać proces przed skutkami błędów, których nie dało się przewidzieć na wcześniejszym etapie.

TRY...CATCH w typowych problemach bazodanowych

Jednym z częstych zastosowań jest kontrola operacji INSERT, UPDATE i DELETE. Naruszenie klucza głównego, klucza obcego, ograniczenia UNIQUE lub warunku CHECK powinno zostać obsłużone w sposób spójny. W bloku CATCH można rozpoznać numer błędu, odnotować zdarzenie i zwrócić neutralny komunikat, bez ujawniania całej struktury bazy osobie korzystającej z aplikacji.

Inna grupa problemów dotyczy konwersji danych. Jeżeli tekst ma zostać przekształcony na datę, liczbę albo inny typ, niepoprawny format może przerwać instrukcję. W zależności od wymagań można wcześniej użyć funkcji TRY_CONVERT lub TRY_CAST, które zwracają wartość NULL zamiast generować błąd dla nieudanej konwersji. To ważne rozróżnienie: TRY...CATCH obsługuje błąd procesu, a funkcje z przedrostkiem TRY służą do bezpiecznego wykonania konkretnej konwersji.

Problemy mogą pojawiać się także przy odwołaniach do obiektów, blokadach i współbieżności. Dwie sesje próbujące zmodyfikować powiązane dane mogą wejść sobie w drogę, a długie oczekiwanie może zakończyć się przerwaniem operacji. CATCH nie rozwiązuje automatycznie konfliktu współbieżności. Może jednak zapisać szczegóły, zwolnić zasoby, wycofać transakcję i umożliwić kontrolowane ponowienie operacji, jeśli reguły aplikacji na to pozwalają.

Przy błędach związanych z blokadami należy zachować ostrożność z automatycznym ponawianiem. Powtórzenie operacji ma sens tylko wtedy, gdy można zagwarantować jej idempotencję albo odpowiednio zabezpieczyć ją przed podwójnym wykonaniem. W przeciwnym razie mechanizm naprawczy może spowodować więcej zmian niż pierwotny problem.

TRY...CATCH w praktycznej diagnostyce i utrzymaniu

Dobrze zaprojektowany blok CATCH powinien dostarczać informacji przydatnych podczas diagnozy, ale jednocześnie nie powinien ujawniać wrażliwych danych. Do dziennika można zapisać czas zdarzenia, numer błędu, komunikat, nazwę procedury, numer wiersza oraz identyfikator operacji. W przypadku procesów uruchamianych przez aplikację przydatne bywa także zapisanie identyfikatora żądania lub użytkownika, o ile takie dane są dostępne i mogą być przechowywane zgodnie z przyjętymi zasadami.

Komunikat dla użytkownika powinien być prosty i adekwatny do sytuacji. Nie należy zwracać całego tekstu błędu systemowego, jeżeli zawiera nazwy tabel, fragmenty zapytań albo informacje o strukturze bazy. Szczegóły techniczne powinny trafić do logu dostępnego dla osób utrzymujących rozwiązanie, natomiast interfejs może przekazać informację, że operacja nie została zakończona i wymaga ponowienia lub dodatkowej weryfikacji.

Podczas testów warto sprawdzać nie tylko scenariusz poprawny, lecz także każdą ścieżkę prowadzącą do CATCH. Należy zweryfikować, czy transakcja jest wycofywana, czy połączenie pozostaje w prawidłowym stanie, czy błąd dociera do warstwy wywołującej oraz czy logowanie nie powoduje kolejnego błędu. Osobnego sprawdzenia wymaga sytuacja, gdy zapis do tabeli logów odbywa się w tej samej transakcji co operacja biznesowa. Jeśli całość zostanie wycofana, wpis diagnostyczny również może zniknąć. Czasem potrzebny jest niezależny mechanizm zapisu, a czasem świadoma decyzja, że log ma być częścią tej samej transakcji.

TRY...CATCH: kiedy potrzebna jest pomoc serwisu

Problemy z wykonaniem procedur T-SQL mogą wynikać nie tylko z samego kodu. Przyczyną bywają uszkodzone pliki, niestabilna praca nośnika danych, problemy z pamięcią, nieprawidłowa konfiguracja systemu albo przerwy w działaniu środowiska, na którym pracuje baza. Jeżeli błędy pojawiają się losowo, towarzyszą im zawieszenia aplikacji, komunikaty o problemach z odczytem lub nagłe restarty, przydatna jest szersza diagnostyka komputera i jego podzespołów.

W takiej sytuacji można zgłosić problem do Warszawskiego Pogotowia Komputerowego 24/7, przekazując treść komunikatu, moment wystąpienia błędu, nazwę wykonywanej operacji oraz informację, czy problem powtarza się po ponownym uruchomieniu. Im dokładniejszy opis, tym łatwiej rozdzielić błąd w procedurze od problemu środowiskowego i ustalić dalszy zakres sprawdzenia.

Przed przekazaniem sprzętu lub rozpoczęciem zmian warto wykonać kopię danych, zachować logi i nie usuwać pochopnie plików diagnostycznych. Dobrą praktyką jest także odnotowanie ostatnich zmian w systemie: aktualizacji, modyfikacji konfiguracji, zmian uprawnień, przenoszenia bazy lub instalacji nowego oprogramowania. Takie informacje pomagają odtworzyć kolejność zdarzeń i ograniczyć ryzyko utraty danych podczas dalszej analizy.

+48 22 100 48 29Zadzwoń teraz · serwisant w 1 godzinę