I was working with a customer and discussing how to do error handling. This is a short post that looks at how you can start adding TRY.. CATCH blocks to your code.
Another post for me that is simple and hopefully serves as an example for people trying to get blogging as #SQLNewBloggers.
TRY CATCH
This is a common error handling technique in other languages. C# uses it, as does Java, while Python has TRY EXCEPT. There are other examples, but these are good habits to get into when you don’t know how code will behave or if there is something in your data or environment that could cause an issue.
In SQL, I think many of us get used to writing one statement in a query and forget to do error handling, or transactions. However, this can be a good habit as your code might grow and people might add more statements that should execute.
A classic example of code is someone writing this:
DECLARE @id INT = 2 , @name VARCHAR(20) = 'Voice od the DBA' , @stat INT = 1;
BEGIN TRAN; INSERT dbo.Customer (CustomerID, CustomerName, status) VALUES (@id, @name, @stat); IF @@ERROR = 0 COMMIT; ELSE ROLLBACK;
Note that this does look for an error and then decide what to do. However, we could be better, especially if we wanted to possibly add a second insert or other work. We could do this:
DECLARE @id INT = 2 , @name VARCHAR(20) = 'Voice od the DBA' , @stat INT = 1;
BEGIN TRY BEGIN TRAN; INSERT dbo.Customer (CustomerID, CustomerName, status) VALUES (@id, @name, @stat); COMMIT END TRY BEGIN CATCH ROLLBACK END CATCH
It doesn’t look like much, but this code could easily be enhanced with a better pattern. We can capture the various error messages like this:
DECLARE @id INT = 2 , @name VARCHAR(20) = 'Voice od the DBA' , @stat INT = 1;
BEGIN TRY
BEGIN TRAN;
INSERT dbo.Customer
(CustomerID, CustomerName, status)
VALUES
(@id, @name, @stat);
COMMIT
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (@ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.
);
WHILE @@TRANCOUNT > 0
BEGIN
ROLLBACK TRANSACTION;
END
END CATCH
In this case, we have a few statements that work with the error, in this case using RAISERROR to raise this. We could also use THROW or add something else. If we had more inserts, like to a child table, we could encapsulate them all here. What’s more, if we had logging, we could log this before the rollback to another system if our logging were not transaction dependent.
Using TRY CATCH is really just structuring your code differently. Ideally, using something a snippet in SQL Prompt so your developers have an easy way to standardize error handling.
SQL New Blogger
This post took me about 15 minutes to structure and test. I looked at a few patterns, and I liked the one in this Stack Overflow answer as a good way to generically implement this structure.
You could write a similar post showing your next boss how you implement error handling, transactions, anything. Give it a try.


I NEVER execute an Update, Insert or DELETE without wrapping it within the Beg/Try structure especially if there is more than one DML being executed. If one part fails I want the entire thing rolled back and Beg/Try is a wonderful tool to do this.
LikeLike
good plan. I see sooooooooooooo much code without this
LikeLiked by 1 person
For some reason, and it might be just me, there is no comment section that I can get to on the voice of the DBA. Its appearance has also changed quite drastically in the last several weeks.
LikeLike
Pingback: Working with TRY-CATCH in SQL Server – Curated SQL
Weird, nothing changed from my side that I’m aware of.
LikeLike