BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

SQL Server
SQL 2005+

SQL Server Error Handling

Microsoft SQL Server 2005 introduced new error handling capabilities for scripts and stored procedures. This article describes the use of the try / catch block in Transact-SQL that permits errors to be captured and allows for graceful recovery.

Error Handling

Prior to the introduction of SQL Server 2005, error handling in Transact-SQL (T-SQL) scripts was very restrictive. If error handling was included in a batch or stored procedure, it would usually be limited to reading the value of @@ERROR immediately after attempting to execute a statement. If @@ERROR was zero, all was probably well. However, this approach was far from ideal, particularly as the value would be cleared after every executed statement.

Newer versions of SQL Server have improved error handling with the addition of the try / catch block, which is similar in operation to the try / catch block provided by C# and other languages. This code structure can be used in batches, stored procedures, triggers and other areas. It allows one or more statements to be executed within a try block. If an error occurs during processing, the block is exited immediately and control is passed to the catch block, where you can include statements that allow graceful recovery or report the error and leave the system in a stable state.

Try / Catch Blocks

The try / catch structure contains two blocks of statements. These are the statements that are to be attempted and those that will execute if an error is raised. The syntax for these blocks is as follows:

BEGIN TRY
    [statements to try]
END TRY
BEGIN CATCH
    [statements to run on error]
END CATCH

Capturing Errors

The use of the try / catch block can be made more obvious with an example. In the script below the statement within the try block is attempting to divide one by zero before outputting a success message. This will always cause an error because the result of such a division cannot be represented in T-SQL. The catch block outputs a message if an error occurs.

When you execute this script the division is attempted and fails. Without the try / catch structure this would cause the script to stop executing immediately. As the division occurs within a try block, control is passed to the catch block instead. The result is that the success message is not shown but the error detection message is. NB: If you run this script within SQL Server Management Studio with default settings, the message is shown in the Messages tab of the results.

BEGIN TRY
    SELECT 1 / 0
    PRINT 'Success'
END TRY
BEGIN CATCH
    PRINT 'Error Detected'
END CATCH

/* OUTPUT

Error Detected

*/

If no errors occur whilst processing a try block, control passes to the statement immediately after the catch block. Similarly, if no errors occur within a catch block, processing continues with the statement that follows it. This means that whether or not the try block is interrupted by an error, the execution of the entire script will continue. Remember though that an error within the catch block will not be captured.

We can see this by adding an extra message after the entire try / catch structure. In the script below, the error message and the continuation are displayed. If you remove the division statement the success and continuation text will be outputted.

BEGIN TRY
    SELECT 1 / 0
END TRY
BEGIN CATCH
    PRINT 'Error Detected'
END CATCH
PRINT 'Continued OK'

/* OUTPUT

Error Detected
Continued OK

*/

Nesting Try / Catch Blocks

If the error handling requirements of your scripts are more complex, you can nest try / catch blocks. It is possible to include a try / catch within either or both of the try and catch blocks of an outer structure. In either case, an error raised in an inner try will not be captured by the outer catch. This is demonstrated in the script below. In this case the division fails in the inner try. The message defined in the inner catch is outputted but the text from the outer catch is not.

BEGIN TRY
    BEGIN TRY
        SELECT 1 / 0
    END TRY
    BEGIN CATCH
        PRINT 'Error Detected in Inner TRY'
    END CATCH
END TRY
BEGIN CATCH
    PRINT 'Error Detected in Outer TRY'
END CATCH
PRINT 'Continued OK'

/* OUTPUT

Error Detected in Inner TRY
Continued OK

*/
3 October 2010