Using Save Points with Transactions to Get Better

When we last conversed, we talked about the TRY/CATCH block and how it works with transactions. If you somehow missed that, you can read about it here – How about we TRY and CATCH some Transactions? We’ll wait for you…

All right, now that everyone’s back with us, we’ll talk more about everyone’s favorite – transactions. When they deal with transactions, most people only know how to begin one, then either commit it or roll it back. But there’s so much more you can do with a transaction!

This time I want to focus on savepoints for transactions. Yes, the same term you’ve been using in games for years can be used in the workplace!

Savepoint!

A savepoint – like in games – is used to save you from yourself. It allows you to begin a mini-transaction and either tear everything down to the frame or you can save everything that you’ve been doing.

For example, if I am in the middle of a transaction in one procedure and decide to bounce out to a new procedure – should I really be able to commit everything in the transaction that is about to be changed from the new one or should I just be able to deal with what I’ve been working on in this new procedure? If you said “Only deal with what you’ve done in that procedure,” then you’re probably right! As always, there are edge cases that you wouldn’t want to do this during, but the majority of the time, this should work for you – as always, mileage will vary.

So, my friends, with that we can go into today’s snippet of code:

CREATE PROC dbo.FirstProc AS 
BEGIN
     DECLARE @ErrorMessage NVARCHAR(4000);  
     DECLARE @ErrorSeverity INT;  
     DECLARE @ErrorState INT;  
     
     BEGIN TRY
           BEGIN TRAN
           INSERT INTO dbo.Person4
           (FirstName, LastName)
           SELECT 'Fred', 'Flintstone'

           EXEC dbo.SecondProc
           COMMIT

     END TRY
     BEGIN CATCH
        SELECT @ErrorMessage = ERROR_MESSAGE();  
        SELECT @ErrorSeverity = ERROR_SEVERITY();  
        SELECT @ErrorState = ERROR_STATE();  
 
        RAISEERROR (@Message, @Severity, @State)
        IF @@TRANCOUNT > 0 ROLLBACK
     END CATCH
END

CREATE PROC dbo.SecondProc AS
BEGIN
    DECLARE @ErrorMessage NVARCHAR(4000);  
    DECLARE @ErrorSeverity INT;  
    DECLARE @ErrorState INT;  
    DECLARE @TranCounter INT;  
    
    SET @TranCounter = @@TRANCOUNT;  
    IF @TranCounter > 0  
	SAVE TRAN ProcedureSave;  
    ELSE
	BEGIN TRAN;

    BEGIN TRY
        INSERT INTO dbo.Person4
        (FirstName, LastName)
        SELECT 'Barney', 'Rubble'

        IF @TranCounter = 0  
	    COMMIT 
				
    END TRY
    BEGIN CATCH
         SELECT @ErrorMessage = ERROR_MESSAGE();  
         SELECT @ErrorSeverity = ERROR_SEVERITY();  
         SELECT @ErrorState = ERROR_STATE();  
 
         RAISEERROR (@Message, @Severity, @State)

         IF @TranCounter = 0
	     ROLLBACK TRAN
	 ELSE
	     IF XACT_STATE() <> -1  
	     ROLLBACK TRAN ProcedureSave

    END CATCH
END

The first procedure, which I thoughtfully called dbo.FirstProc, calls the second procedure, shockingly called dbo.SecondProc, and the savepoint fun can begin!

In the first procedure, you’ll see that we inserted the Fred Flintstone record into our dbo.Person4 table. If that works, then we go into the second procedure and attempt to insert the Barney Rubble record. If that is inserted with no issues, we’ll commit everything in our transaction. If the Barney Rubble record has trouble being inserted, we’ll rollback Barney, but still keep Fred in the table.

Yes, you’ll notice from the stored procedures listed above that there is a semi-duplication of the catch block since you do have to catch all your errors – like good developers.

And it truly is simple as that. Just remember, if you flip to a new procedure in the middle of a transaction, then a savepoint could be your new best friend!

And with that, my friends, we come to the end of yet another post. Come join us next time when we talk even more about transactions. But until then, take a listen to a track from the Cyberpunk 2077 soundtrack – “No Save Point” from Yankee and The Brave (Run the Jewels).

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.