Każde przemysłowe rozwiązanie SQL wymaga przemyślanej architektury przetwarzania błędów. Bez logowania i starannego obsługiwania wyjątków, trudno jest debugować złożone procesy, szczególnie w procedurach składowanych i skryptach wsadowych.
Historia pytania: Standardowy SQL umożliwia minimalne przetwarzanie błędów (np. RETURN i zakończenie przetwarzania). Nowoczesne rozszerzenia (T-SQL, PL/pgSQL, PL/SQL itp.) oferują pełne konstrukcje przetwarzania błędów (TRY/CATCH, EXCEPTION).
Problem: Bez jawnej obsługi błędów „toną”, a administratorowi trudno ustalić przyczynę awarii - szczególnie przy masowych zmianach lub pracy z systemami zewnętrznymi. Często pojawia się konieczność logowania błędów w osobnej tabeli do późniejszej analizy.
Rozwiązanie: Użyj arsenału TRY/CATCH (T-SQL) lub EXCEPTION (PL/pgSQL), a także własnych tabel logujących. Nie zapomnij wysyłać informacji diagnostycznych (kod błędu, treść błędu, parametry zapytania i czas) do logu.
Przykład kodu (T-SQL, MS SQL Server):
CREATE TABLE ErrorLog ( ErrorId INT IDENTITY PRIMARY KEY, ErrorTime DATETIME, ProcedureName NVARCHAR(128), ErrorMessage NVARCHAR(MAX), ErrorNumber INT, ErrorState INT, ErrorSeverity INT ); CREATE PROCEDURE usp_ProcessOrders AS BEGIN BEGIN TRY -- Logika biznesowa UPDATE Orders SET Status = 'PROCESSED' WHERE Status = 'NEW'; END TRY BEGIN CATCH INSERT INTO ErrorLog ( ErrorTime, ProcedureName, ErrorMessage, ErrorNumber, ErrorState, ErrorSeverity ) VALUES ( GETDATE(), ERROR_PROCEDURE(), ERROR_MESSAGE(), ERROR_NUMBER(), ERROR_STATE(), ERROR_SEVERITY() ); THROW; END CATCH END
Przykład kodu (PL/pgSQL, PostgreSQL):
BEGIN -- Twój kod EXCEPTION WHEN OTHERS THEN INSERT INTO error_log(ts, proc_name, err_text) VALUES(now(), 'my_proc', SQLERRM); RAISE; END;
Kluczowe cechy:
Czy wystarczy przechwycić błąd i zakończyć wykonywanie procedury bez przekazywania informacji na zewnątrz?
Nie. Bez jawnego logowania lub propagowania błędu nie można uchwycić i przeanalizować przyczyn awarii. Ważne jest, aby albo szczegółowo opisać błąd w logu, albo przynajmniej przekazać go dalej (THROW/RAISE).
Czy można używać wyłącznie wbudowanych dzienników SQL Server/DBMS do wykrywania wszystkich błędów w procedurach użytkownika?
Częściowo. Wiele błędów nie trafia do dzienników serwera, jeśli są „chwytane” i obsługiwane w aplikacji lub w procedurach. Dla logiki biznesowej przydatne jest prowadzenie własnego dziennika zdarzeń z detalami.
Czy konieczne jest użycie TRY/CATCH (lub EXCEPTION), jeśli w procedurze używane są tylko proste operacje DML?
Konieczne, jeśli procedura wpływa na ważne dane, bierze udział w krytycznych łańcuchach i musi rejestrować sytuacje awaryjne. Nawet „bezpieczne” operacje mogą prowadzić do błędów z powodu ograniczeń zewnętrznych (unikalność, FOREIGN KEY, deadlocki itp).
W projekcie błędy nie są logowane, tylko wyświetlane użytkownikowi. Przy masowej awarii administrator przez wiele godzin szuka „niewidocznego” problemu.
Zalety:
Wady:
Każdy krytyczny błąd jest rejestrowany w tabeli logującej z szczegółami (czas, procedura, parametry, kod błędu) i odnosi się do niego zgłoszenie systemowe.
Zalety:
Wady: