In stored procedures, error handling can and should be implemented using special constructs.
In SQL Server, the main mechanisms are TRY...CATCH blocks, where all errors within TRY are caught, and in CATCH, you can log the details. Functions like ERROR_NUMBER(), ERROR_MESSAGE() are available to get the details.
BEGIN TRY -- Risky operation UPDATE Accounts SET balance = balance - 100 WHERE id = 1; END TRY BEGIN CATCH INSERT INTO ErrorLog( ErrorTime, ErrorNumber, ErrorMessage, UserName ) VALUES ( GETDATE(), ERROR_NUMBER(), ERROR_MESSAGE(), SUSER_SNAME() ); -- Additional recovery or ROLLBACK END CATCH
In Oracle, EXCEPTION blocks are more commonly used:
BEGIN UPDATE ...; EXCEPTION WHEN OTHERS THEN INSERT INTO error_log VALUES (..., SQLERRM); END;
Points to remember:
Can an exception in the CATCH block lead to loss of the original error context? How to implement nested error handling?
Answer and example: If an error occurs in the CATCH block (for example, due to the unavailability of the ErrorLog table), the original error context is lost, and information about the cause of failure may be lost.
To safeguard against this, encapsulate logging in a separate procedure with its own TRY...CATCH to always catch "errors in the error handler."
BEGIN TRY -- main code END TRY BEGIN CATCH EXEC LogError @Error = ERROR_MESSAGE(); END CATCH -- The LogError procedure itself contains its own TRY...CATCH
History
Project: Financial Reporting. In stored procedures, TRY...CATCH blocks were added, but we did not log the parameters with which the error occurred. As a result, during critical failure catches, it was necessary to manually search for the situation from the backup — the root cause was not obvious.
History
Project: Document Workflow Automation (Oracle). In the EXCEPTION block, we forgot to log the username. After a week of investigation, it was discovered that someone was intentionally "breaking" documents — we only found out through indirect signs in the audit log.
History
Project: E-commerce. The procedure wrote an error to ErrorLog on failure. Once the Log table was locked by a bloated transaction, and the logging attempt led to a nested error that overwrote the original cause and cleared the error stack. We fixed this by implementing an additional table for critical failures and multi-level logging.