Friday, September 12, 2014

Error Handling in SQL Server


In this article, I am giving a quick overview about Error Handling in SQL Server. After completing this article you will understand:

How to do Error Handling in SQL Server?
How to Raise Error Manually in SQL Server?
How to ADD USER Defined Error Messages in sys.messages catalog view?

Please give your valuable suggestions and feedback to improve this article.

I have already discussed about TSQL programming basics, I will recommend you to visit the article if you are not aware of TSQL.

How to do Error Handling in SQL Server?

When you have a batch of SQL statements and in that batch of SQL Statements if any SQL statement causes error then it throws the error message but it never terminates the execution of program it continues the execution of SQL statements which comes after that SQL Statement which raised error.

Let’s understand the above problem with an example

I am creating a store procedure which divides two numbers and print the result. As you can see from the below query, I am passing two number in the procedure. I am dividing them and storing the result in variable named as @RESULT. Initially I am assigning 0 values for the @RESULT variable and later updating the variable value with the result.

CREATE DATABASE TEACHMESQLSERVER
USE TEACHMESQLSERVER
GO
CREATE PROCEDURE DIVISION_BY_ZERO(@FIRST INT, @SECOND INT)
AS
BEGIN
DECLARE @RESULT INT
SET @RESULT=0
SET @RESULT=@FIRST/@SECOND
PRINT 'THE OUTPUT IS:'+CAST(@RESULT AS VARCHAR)
END

Let’s execute the above procedure

EXEC DIVISION_BY_ZERO 20,10

 
As you can see from the result below; when we divide 20 by 10 we get 2 and our procedure prints the result as below.

Now let’s try to divide 20 by 0; its universal truth that we can’t divide any number by 0 and we will get error.

EXEC DIVISION_BY_ZERO 20,0

Here you go; we got below error message after executing the above query.


Error message clearly says that divided by zero error encountered. If you have noticed after the error message that Print Statement executed and it printed THE OUTPUT IS: 0. this is wrong right?
It should not have printed this.

To overcome this problem SQL server provides Error handling, when we do error handling the SQL statement which cause the error will be terminated and the execution of stored procedure or batch will also be stopped.

In T-SQL programming error handling is done by using TRY and CATCH construct. Errors in T-SQL code can be processed using a TRY-CATCH construct.  A TRY -CATCH construct consists of two parts TRY block and CATCH block. TRY Block contains the SQL statement which may cause error, when an error situation is detected in TYRY block, control is passed to a CATCH block where it can be processed or handled. After the CATCH block handles the exception (Error), control is then transferred to the first T-SQL statement that follows the END CATCH statement. A TRY block always starts with the BEGIN TRY statement and ends with END TRY statement. A CATCH block always starts with a BEGIN CATCH statement and ends with END CATCH statement. A CATCH block must follow a TRY block. In T-SQL each TRY block is associated with only one CATCH block.

Let’s do error handling in above procedure.

ALTER PROCEDURE DIVISION_BY_ZERO(@FIRST INT, @SECCOND INT)
AS
BEGIN
DECLARE @RESULT INT
SET @RESULT=0

BEGIN TRY
SET @RESULT=@FIRST/@SECCOND
END TRY

BEGIN CATCH
SELECT   ERROR_NUMBER() AS ErrorNumber
        ,ERROR_SEVERITY() AS ErrorSeverity
        ,ERROR_STATE() AS ErrorState
        ,ERROR_PROCEDURE() AS ErrorProcedure
        ,ERROR_LINE() AS ErrorLine
        ,ERROR_MESSAGE() AS ErrorMessage;
END CATCH

PRINT 'THE OUTPUT IS:'+CAST(@RESULT AS VARCHAR)
END

As you can see from the above code, we have kept SET @RESULT=@FIRST/@SECOND in TRY Block. It is because this line of SQL statement is creating dividing by zero error. We have CATCH block next to this TRY block. CATCH block is handling the error raised by its TRY block.

Let’s try to divide 20 by 0.
GO
EXEC DIVISION_BY_ZERO 20,0


As you can from the above output, this time we didn't get any error message but we get a message saying Divide by Zero encountered and it also terminates the execution and didn't print THE OUTPUT IS:0 like last time.

How to Raise Error Manually in SQL Server?

We can also raise errors manually at some required situations. It is used to return messages back to application using the same format as a system error or warning message is generated. For raising an error manually we use RAISERROR statement. RAISERROR can return either a user defined error message that has been created using the SP_ADDMESSAGE system stored procedure or a message string specified in the RAISERROR statement.

Syntax-  

RAISERROR (msg_id|msg_str|@local_variable, severity, State ,argument[,..n])
WITH option [,..n]

*msg_id is user defined error message number stored in the sys.messages catalog view. Using sp_addmessage system stored procedure user defined error message can be created in sys.messages table. It should be greater than 50000.When it is not specified RAISERROR raises an error message with an error number 50000.

*msg_str is a user defined message with formatting similar to the printf function in C.
*@local_variable is a variable of any valid charter data type that contains a string formatted in the same manner as msg_str. It must be char or varchar.
*Severity is the user defined severity level associated with this message. It can be 0-18.
* State is an arbitrary integer from 1-127.The value 0 and greater than 127 will raise an error.

Let’s understand this with an example

Problem - you don’t want to divide any number by 2. If anyone tries to divide with 2 it should throw error.

SQL Code-

CREATE PROCEDURE DIVISION_BY_TWO(@FIRST INT, @SECOND INT)
AS
BEGIN
Declare @RESULT int

BEGIN TRY
If @SECOND=2
RAISERROR('I AM RAISING THIS ERROR MANUALLY, SORRY YOU ARE NOT ALLOWED TO DIVIDE BY 2',15,1)
SET @RESULT=@FIRST/@SECOND
PRINT 'The Output is: '+ Cast(@RESULT as varchar(2))
END TRY

BEGIN CATCH
PRINT Error_Message()
END CATCH

END

As you can from the above query in try block, if anyone tries to divide by 2 it raise error, catch block just after the try block catch gets the control and it prints the error message written in RAISERROR under TRY block.

Let’s try to divide 20 by 2.

EXEC DIVISION_BY_TWO 20, 2


As you can see from the above result, it raised an error which was raised manually. It printed the error message written in RAISEERROR under TRY block.

If you want to customize the error message with formatting then use the RAISERROR statement as following

RAISERROR ('We don’t want to divide %d with %d',15,1,@FIRST,@SECOND)

We can also use the WITH LOG option at the end of the string to write the error message into the SQL server Log file as following.

RAISERROR (‘We don’t want to divide %d with %d’,15,1,@FIRST,@SECOND)  WITH LOG

How to ADD USER Defined Error Messages in sys.messages catalog view?

 All the predefined error list of SQL server can be found in the SYS.Messages catalog view. Query on the database with the following statement where we can view the list of predefined errors.

SELECT * FROM SYS.MESSAGES

We can add new user defined error message in SYS.Messages using the system store procedure SP_AddMessage.

Syntax:

SP_AddMessage @msgid, @severity, @msgtext, @lang, @with_log, @replace

Example:

Exec SP_AddMessage 50001,16,'I AM RAISING THIS ERROR MANUALLY, SORRY YOU ARE NOT ALLOWED TO DIVIDE BY 2'

You can confirm that above error message has been added into sys.messages table this by running below query

SELECT * FROM SYS.MESSAGES WHERE TEXT LIKE 'I AM RAISING%'

I hope you enjoyed the article don't forget to share on Facebook.

Keep Learning!


No comments: