Při psaní složitějších rutin v T-SQL a zejména při zanořování uložených procedur a dalších pokročilých scénářích je určitě na místě předejít nekontrolovaným chybám využitím konstrukce TRY & CATCH. Pokud nějaká chyba přeci jen nastane a zachytíme ji v CATCH bloku, potřebujeme vědět, o jakou chybu se jedná. Pokud nepošleme chybu dále z CATCH bloku pomocí THROW, je na nás, abychom pomocí systémových funkcí získali popis chyby a dále s ním pracovali, buď vrácením uživateli nebo zapsáním do logu. A není nic rozumnějšího, než vypisování chyb sjednotit pro celé databázové řešení a mít jednotný výstupní formát, který bude jak jednoduše strojově zpracovatelný, tak i uživatelsky přívětivý a přidá nějakou tu informaci navíc.
Jednou z elegantních možností je, že pro sestavení chybové zprávy vytvoříme samostatnou proceduru, kterou budeme následně volat z CATCH bloku bez dalšího zbytečného kódu.
Procedura pro sestavení chybové zprávy může vypadat například takto:
CREATE OR ALTER PROCEDURE [dbo].[FireError] AS BEGIN DECLARE @ErrorMessage NVARCHAR(MAX) DECLARE @ErrorSeverity INT DECLARE @ErrorState INT SET @ErrorSeverity = ERROR_SEVERITY() SET @ErrorState = ERROR_STATE() SET @ErrorMessage = '|' + ISNULL(CAST(ERROR_NUMBER() AS NVARCHAR(10)), 'ERROR_NUMBER') + ' | ' + ISNULL(CAST(@ErrorSeverity AS NVARCHAR(10)), 'ERROR_SEVERITY') + ' | ' + ISNULL(CAST(@ErrorState AS NVARCHAR(10)), 'ERROR_STATE') + ' | ' + ISNULL(ERROR_PROCEDURE(), 'CALLED_OUTSIDE_STORED_PROCEDURE') + ' | ' + ISNULL(CAST(ERROR_LINE() AS NVARCHAR(10)), 'ERROR_LINE') + ' | ' + ISNULL(ERROR_MESSAGE(), 'ERROR_MESSAGE') + '|' RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState) RETURN 0 END GO
Tělo procedury pouze volá systémové funkce pro získání popisu chyby a formátuje jejich výstup do uživatelský přívětivé podoby.
Proceduru pak můžeme volat v CATCH bloku takto:
BEGIN TRY PRINT 1/0 END TRY BEGIN CATCH EXEC [dbo].[FireError] END CATCH GO
Na obrázku je vidět, jak vypadá zformátovaná chybová zpráva. A barevně je vyznačeno jedno drobné vylepšení, které jsme do sestavení chybové zprávy přidali: pokud již nastane v SQL Serveru uživatelská chyba, často první po čem budeme pátrat je, zda se jednalo o ad-hoc kód nebo došlo k chybě v uložené proceduře. Zde vidíme, že k chybě došlo v kódu mimo uloženou proceduru.
Pojďme nyní otestovat stejnou chybu, ale vyvolejme ji v těle testovací uložené procedury:
CREATE PROCEDURE [dbo].[TestProcedure] AS BEGIN BEGIN TRY PRINT 1/0 END TRY BEGIN CATCH EXEC [dbo].[FireError] END CATCH END GO EXEC [dbo].[TestProcedure] GO
Nyní nám chybová zpráva přímo ukazuje název uložené procedury, ve které k chybě došlo a vím tak rovnou, kam do databáze sáhnout a chybu opravit.