Error handling and logging in SQL have gained particular popularity with the development of complex business processes when it became important not just to stop execution on error but to record the fact of failure and, if possible, continue working. Initially, SQL did not have advanced try-catch mechanisms, and each DBMS offered its own mechanisms.
History of the issue:
Early versions of SQL standards did not have built-in operators to catch errors in procedures. Later, vendors began to implement constructs such as TRY...CATCH in Microsoft SQL Server or HANDLER in MySQL, allowing for more flexible control over the workflow directly at the database level.
Problem:
Errors can occur due to incorrect data as well as system reasons. If a stored procedure does not implement capturing and logging errors, debugging and maintenance become extremely difficult. Furthermore, it is necessary to distinguish between critical errors and handled ones to avoid interrupting business operations where it is not required.
Solution:
In modern systems, it is advisable to implement constructs for collecting and logging errors. It is necessary to create separate log tables, use TRY...CATCH (SQL Server) or DECLARE ... HANDLER (MySQL), and store detailed information about exceptions in order to later analyze the causes of failures.
Code example (SQL Server):
CREATE PROCEDURE dbo.UpdateCustomer @CustomerID INT, @NewName NVARCHAR(100) AS BEGIN BEGIN TRY UPDATE Customers SET Name = @NewName WHERE CustomerID = @CustomerID; END TRY BEGIN CATCH INSERT INTO ErrorLog (ErrorMessage, ErrorSeverity, ErrorTime) VALUES (ERROR_MESSAGE(), ERROR_SEVERITY(), GETDATE()); THROW; END CATCH END;
Key features:
Can all types of errors be caught inside a TRY...CATCH block (or through a handler)?
No, not all errors, for example, severe server failures, can be caught. Attention errors or connection failures are beyond transaction processing.
What will happen to uncommitted changes in the procedure in case of an error if a transaction is not used?
Changes will be partially committed, some updates will enter the database, and some may be lost. To avoid inconsistency, it is recommended to always use transactions.
BEGIN TRY BEGIN TRANSACTION; --...code COMMIT; END TRY BEGIN CATCH ROLLBACK; END CATCH
Can INSERT EXEC be used directly from within the CATCH block to log an error from another context?
Not always: INSERT EXEC is prohibited in certain contexts (for example, if there is already an active transaction), which may cause second-level errors. It is better to collect error details locally and then log them with a single INSERT.
A client implemented logic only through RAISERROR without logging, so errors were not saved or analyzed.
Pros:
Cons:
Using TRY...CATCH plus an ErrorLog table, recording time, error code, user, text, and trace.
Pros:
Cons: