Raymond Lewallen

Sponsors

The Lounge

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Exception Handling in Sql Server 2005
SQL Server 2005 provides a new exception-handling mechanism in the form of TRY...CATCH. In current version of Sql Server you have to include GOTO statements, and check @@ERROR after every statement is executed to determine if an error had occurred at that particular point and terminate your process or rollback your transaction. This is very ugly indeed. Now Sql Server 2005 provides us with a way to handle those exceptions with the familiar TRY...CATCH blocks. Note: TRY...CATCH blocks in Sql Server cannot handle errors that cause a connection to be lost, i.e. any severity 21 error.

Let's look at this simple block of code:

BEGIN TRY
  BEGIN TRAN
  INSERT Northwind.dbo.Region(RegionId, RegionDescription) VALUES (5,'CENTRAL')
  PRINT 'Added Central Region'
  INSERT Northwind.dbo.Region(RegionId, RegionDescription) VALUES (5,'ANOTHER REGION')
  PRINT 'Added Another Region'
  COMMIT TRAN
END TRY
BEGIN CATCH
  PRINT 'The following error has occurred:  ' + ERROR_MESSAGE()
  ROLLBACK TRAN
END CATCH

The following output will be produced:
Added Central Region
The following error has occurred: Violation of PRIMARY KEY constraint 'PK_Region'. Cannot insert duplicate key in object 'Region'.


Well that is simple enough. Note that unlike .Net, you cannot leave out the CATCH statement in T-SQL. Not much change to existing code in order to get this implemented, other than taking out a bunch of labels, GOTOs and @@ERROR > 0 checks.
Here's another example:

BEGIN TRY
  BEGIN TRAN
  INSERT Northwind.dbo.Region(RegionId, RegionDescription) VALUES (5,'CENTRAL')
  PRINT 'Added Central Region'
  INSERT Northwind.dbo.Region(RegionId, RegionDescription) VALUES (6,NULL)
  PRINT 'Added NULL Region'
  COMMIT TRAN
END TRY
BEGIN CATCH
  PRINT 'The following error has occurred:  ' + ERROR_MESSAGE()
  ROLLBACK TRAN
END CATCH

The following output will be produced:
Added Central Region
The following error has occurred: Cannot insert the value NULL into column 'RegionDescription', table 'Northwind.dbo.Region'; column does not allow nulls. INSERT fails.


Now lets combine the two examples together and look at how we capture a specific error that occurred using ERROR_NUMBER(). Also, I'm introducing the new XACT_STATE() into this example. XACT_STATE() does exactly what you think it does, it returns the state of the transaction. Return values 0 for no transaction is open and you cannot commit or rollback, 1 means that a transaction is open and can committed or rolled back based on how you need to handle your situation, and new to Sql Server 2005 is a transaction state of -1, which means that a transaction is open but cannot be committed. A transaction within a TRY block reaches this state when an error occurs that would normally cause the transaction to be aborted. You cannot continue to change data once the transaction reaches a point of not being able to be committed because an uncommittable transaction keeps all locks open and allows you to only read data. At this point, the only way to terminate the transaction is to roll it back. Let's look at this example:

BEGIN TRY
  BEGIN TRAN
  INSERT Northwind.dbo.Region(RegionId, RegionDescription) VALUES (5,'CENTRAL')
  PRINT 'Added Central Region'
  INSERT Northwind.dbo.Region(RegionId, RegionDescription) VALUES (5,'ANOTHER REGION')
  PRINT 'Added Another Region'
  INSERT Northwind.dbo.Region(RegionId, RegionDescription) VALUES (6,NULL)
  PRINT 'Added NULL Region'
  COMMIT TRAN
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 2627
BEGIN
    PRINT 'Statement violates primary key constraints.'
    IF (XACT_STATE()) <> 0 -- We are in a transaction and want to roll it back
        ROLLBACK TRAN
END
ELSE IF ERROR_NUMBER() = 515
BEGIN
    PRINT 'Statement attempted to insert a NULL where a NULL is not allowed.'
    IF (XACT_STATE()) = -1 -- Can only rollback
        ROLLBACK TRAN
    ELSE IF (XACT_STATE()) = 1 -- We can do whatever we want, commit or roll back
        COMMIT TRAN
END

PRINT 'Error Number:   ' + CAST(ERROR_NUMBER() AS VARCHAR(10))
PRINT 'Error Message:  ' + ERROR_MESSAGE()
PRINT 'Error Severity: ' + CAST(ERROR_SEVERITY() AS VARCHAR(10))
PRINT 'Error State   : ' + CAST(ERROR_STATE() AS VARCHAR(10))
END CATCH

Now the following output will be produced for this block of code:
Added Central Region
Statement violates primary key constraints.
Error Number: 2627
Error Message: Violation of PRIMARY KEY constraint 'PK_Region'. Cannot insert duplicate key in object 'Region'.
Error Severity: 14
Error State : 1

Notice how I can still COMMIT the transaction if I want to depending on the specific error that occurred. I may not care so much that the NULL didn't get inserted, but I want to go ahead and commit the other inserts. By checking the ERROR_NUMBER() in my CATCH block, I can exactly determine which error occurred and how I want to handle the situation.

Posted 01-20-2005 11:56 AM by Raymond Lewallen

[Advertisement]

Comments

Scott Allen wrote re: Exception Handling in Sql Server 2005
on 01-20-2005 11:49 AM
That is awesome. I wish we had this 3 years ago.
Shrikant wrote re: Exception Handling in Sql Server 2005
on 11-04-2005 9:09 AM
Hi
This is really exceptional document.
Raymond Lewallen wrote re: Exception Handling in Sql Server 2005
on 11-04-2005 9:24 AM
Thank you Shrikant.
Ray wrote re: Exception Handling in Sql Server 2005
on 04-13-2006 5:55 PM
Could you explain when to use "SET XACT_ABORT ON" please.  Thanks!
Raymond Lewallen wrote re: Exception Handling in Sql Server 2005
on 04-14-2006 10:32 AM
Ray, see the following link for information on SET XACT_ABORT usage.

http://msdn2.microsoft.com/en-us/library/ms188792.aspx

stan wrote re: Exception Handling in Sql Server 2005
on 08-27-2006 7:58 PM

please can i send my code for you to have a lookat it

thanks

Anil Mohapatra wrote re: Exception Handling in Sql Server 2005
on 09-24-2006 8:21 AM

Superb display of the new "Try Catch" Feature.

Its really helpful for me as a developer.

MS Satish wrote re: Exception Handling in Sql Server 2005
on 12-13-2006 9:00 AM

Excellent..it was very useful for me...keep it up

Mo wrote re: Exception Handling in Sql Server 2005
on 10-25-2007 10:00 AM

Can we do the same TRY CATCH with sql statements (DDL) like Alter procedure instead of DML.

DAvid wrote re: Exception Handling in Sql Server 2005
on 11-21-2007 2:19 PM

Can you make this work inside a cursor while loop?  I would like to see the error return and continue after an error to finish the cursor processing.

Arvind wrote re: Exception Handling in Sql Server 2005
on 04-09-2008 5:06 PM
Excellent it was good to handle such errors
Gnanasundaram wrote re: Exception Handling in Sql Server 2005
on 05-13-2008 6:42 AM

It is very easy to understand.Example is very good

learner(learner520@googlemail.com) wrote re: Exception Handling in Sql Server 2005
on 06-18-2008 5:49 PM

hi raymond

after reading ur  artical i hope u wud be answer my question i just implement the following code cud u plz confirm i m applying in the right way try n catch block ."i used simply Paging option of sql server 2005  actually i want to code display a error message when end use doesn't enter the parameter like"

PaginRec  without any parameter

PaginRec 1,20    with parameter

if user doesnt pass the parameter how cud how cud we rais error msg "Enter required parameter please"

CREATE Procedure PaginRec

(

@PageNum int,

@NumOfRec int

)

as

begin try

 Begin

 with DIVRES as (

 select Row_Number() over(order by Responsible desc)

 as row, Responsible , Division

 from Bulist)

select Responsible,Division

from DIVRES

where row between

(@PageNum - 1) * @NumOfRec + 1 and @PageNum*@NumOfRec

end

end try

begin catch

select  'Error Caught'

end catch

AMOL KAGDE wrote re: Exception Handling in Sql Server 2005
on 09-18-2008 9:15 AM

HI

REALY THIS IS VERY NICE DOC THIS WILL HELP ME IN FUTURE...

THANK U!

Add a Comment

(required)  
(optional)
(required)  
Remember Me?