Quantcast
Channel: Niels Berglund
Viewing all articles
Browse latest Browse all 983

More T-SQL Error Functionality in Denali / SQL 11

$
0
0

In my previous post I wrote about the new THROW keyword in Denali / SQL 11. Having played around a bit more with Denali, I wanted to write some additional things about THROW and it’s relation to RAISERROR.

RAISERROR

First some background / overview of RAISERROR:

  • RAISERROR allows you to throw an error based on either an error number or a message, and you can define the severity level and state of that error:
  • If you call RAISERROR with an error number, that error number has to exist in sys.messages.
  • You can use error numbers between 13001 and 2147483647 (it cannot be 50000) with RAISERROR.

As I mentioned in my previous post, RAISERROR has been around since forever – and it works fairly well. One of the major drawbacks with RAISERROR– as I also wrote in my previous post; is that it cannot be used to re-throw an error we might have trapped in a structured error handling block. Or rather, this may not be that much a RAISERROR issue, as an issue that SQL Server has not previously supported the notion of re-throwing an error. Be as it may with that, there are other drawbacks with RAISERROR which I will mention later in this post.

THROW

In Denali / SQL 11 Microsoft introduces the THROW keyword, which allows us to re-throw an exception caught in an exception handling block. Some characteristics of THROW:

  • Using THROW you can throw a specific error number as well as message:
1
THROW50000,'Ooops',1;
  • When using THROW> you have to define both an error number as well as a message (and state), unless you re-throw an exception.
  • The error number does not have to exist in sys.messages but, it has to be between 50000 and 2147483647.

So, THROW looks fairly cool, but what are the drawbacks with RAISERROR I mentioned above? Well, for one – beginning with Denali / SQL 11 RAISERROR is being deprecated, i.e. it will eventually be removed from SQL Server. Another reason has to do with transactions and error handling.

UPDATE: According to Aaron Bertrand, in his post, it is only some very old RAISERROR syntax that is being deprecated.

XACT_ABORT

As every T-SQL programmer worth his (or her) salt should know, an exception does not roll back a transaction by default (ok, ok, it does depend on severity level to an extent – but a “normal” exception does not roll back a tran). I.e. the following code would cause two rows to be inserted in the table t1:

12345678910
--first create a test table which we will use throughout the code samplesCREATETABLEt1(idintprimarykey,col1nvarchar(15));--now onto the 'meat'BEGINTRANINSERTINTOt1VALUES(1,'row1');--emulate some error, this will indeed cause an exception to happen,--but the processing will continueSELECT1/0INSERTINTOt1VALUES(2,'row2')COMMIT

We can indicate to SQL Server that we want “automatic” rollback of transactions when an exception happens by setting XACT_ABORT. This will cause a rollback to happen if a system exception happens. So based on the example above, no rows will be inserted when the code below executes:

123456
SETXACT_ABORTONBEGINTRANINSERTINTOt1VALUES(3,'row3');SELECT1/0INSERTINTOT1VALUES(4,'row4')COMMIT

However, what happens if the user throws an exception using RAISERROR? In that case no rollback happens, i.e. RAISERROR does not honor the XACT_ABORT setting:

1234567
SETXACT_ABORTONBEGINTRANINSERTINTOt1VALUES(5,'row5');--the user raises an error, but the tx will not roll backRAISERROR('Oooops',16,1)INSERTINTOt1VALUES(6,'row6')COMMIT

This can catch developers out and is in my opinion a fairly severe drawback. So with the introduction of Denali / SQL 11 and the THROW keyword, Microsoft has tried to fix this by making THROW honor XACT_ABORT:

1234567
SETXACT_ABORTONBEGINTRANINSERTINTOt1VALUES(7,'row7');--the user raises an error, and the tx will roll backTHROW50000,'Ooops',1INSERTINTOt1VALUES(8,'row8')COMMIT

When you run the code above, you will see that the transaction is indeed rolled back and no rows are inserted.

So developers, “go forth” and THROW exceptions in SQL Server Denali / SQL 11.


Viewing all articles
Browse latest Browse all 983

Trending Articles