Solved

IF @@TRANCOUNT > 0     COMMIT TRANSACTION;

Posted on 2015-02-03
6
206 Views
Last Modified: 2015-02-03
Hello Experts;

Need some Expert help with SQL Transactions using TRY, CATCH, COMMIT and ROLLBACK.

Creating a SP that will receive parameters and based on the @DuplicateType will perform 1 of 4 tasks.  If the task is successful COMMIT, else ROLLBACK.

I have attached just the basic SP, but do I have my COMMIT TRANSACTION in the proper place?
COMMIT-TRANS.sql
0
Comment
Question by:wdbates
  • 3
  • 2
6 Comments
 
LVL 69

Accepted Solution

by:
ScottPletcher earned 500 total points
ID: 40586959
Yes.

But you really should use XACT_STATE() rather than @@TRANCOUNT.

Also, you need a BEGIN / END block on the IF in the error section:
BEGIN CATCH
       
      IF @@TRANCOUNT > 0
      BEGIN

            SELECT
                  @ErrorMessage   = ERROR_MESSAGE(),
                  @ErrorSeverity  = ERROR_SEVERITY(),
                  @ErrorState     = ERROR_STATE(),
                  @ErrorProcedure = ERROR_PROCEDURE(),
                  @ErrorLine      = ERROR_LINE(),
                  @ErrorNumber    = ERROR_NUMBER();

             ROLLBACK TRANSACTION;
            
             RAISERROR (@ErrorMessage,   -- Message text
                              @ErrorSeverity,  -- Severity
                              @ErrorState,     -- State
                              @ErrorProcedure, -- Procedure
                              @ErrorLine,             -- Line
                              @ErrorNumber     -- Number
                              );
    END
END CATCH;
0
 
LVL 69

Expert Comment

by:Éric Moreau
ID: 40586963
If you have a "begin tran" and no "commit", the operation will be automatically rolled back so yes you need the commit
0
 

Author Closing Comment

by:wdbates
ID: 40587166
Thank you Scott for the answer and the tip on XACT_STATE.  See the test code below where if the @DuplicateType = 1 you will receive a Divide by Zero error.

Thank you again.

BEGIN

SET XACT_ABORT ON;

BEGIN TRY

BEGIN TRANSACTION

      SET NOCOUNT ON;
      DECLARE @ErrorMessage   NVARCHAR(4000);
    DECLARE @ErrorSeverity  INT;
    DECLARE @ErrorState     INT;
    DECLARE @ErrorProcedure NVARCHAR(128);
    DECLARE @ErrorLine      INT;
    DECLARE @ErrorNumber    INT;
    DECLARE @DuplicateType  INT = 1;
      
      if @DuplicateType = 1 --Duplicate master page to new test page
      begin
            PRINT 'One'
            SELECT 1/0
      end
      
      if @DuplicateType = 2 --Duplicate test page to a new test page.
      begin
            PRINT 'two'
      end
      
      if @DuplicateType = 3 --Duplicate test page to new master page
      begin
            PRINT 'tree'
      end
      
      if @DuplicateType = 4 --Duplicate master page to a new master page.
      begin
            PRINT 'four'
      end
      
      IF (XACT_STATE()) = 1
    BEGIN
        PRINT 'The transaction is committable.' +
              ' Committing transaction.'
        COMMIT TRANSACTION;  
    END;

END TRY

BEGIN CATCH
       
    IF (XACT_STATE()) = -1
    BEGIN
        PRINT 'The transaction is in an uncommittable state.' +
              ' Rolling back transaction.'
            SELECT
                  @ErrorMessage   = ERROR_MESSAGE(),
                  @ErrorSeverity  = ERROR_SEVERITY(),
                  @ErrorState     = ERROR_STATE(),
                  @ErrorProcedure = ERROR_PROCEDURE(),
                  @ErrorLine      = ERROR_LINE(),
                  @ErrorNumber    = ERROR_NUMBER();
                  
        ROLLBACK TRANSACTION;
       
            RAISERROR (@ErrorMessage,   -- Message text
                         @ErrorSeverity,  -- Severity
                         @ErrorState,     -- State
                       @ErrorProcedure, -- Procedure
                       @ErrorLine,             -- Line
                       @ErrorNumber     -- Number
                  );
    END;
   
END CATCH;

END
0
Control application downtime with dependency maps

Visualize the interdependencies between application components better with Applications Manager's automated application discovery and dependency mapping feature. Resolve performance issues faster by quickly isolating problematic components.

 
LVL 69

Expert Comment

by:ScottPletcher
ID: 40587187
Looks very good overall.

However, to be thorough, I'd fully check XACT_STATE() in both the TRY area and CATCH areas:

--TRY area
     IF (XACT_STATE()) = 1
     BEGIN
         PRINT 'The transaction is committable.' +
               ' Committing transaction.'
         COMMIT TRANSACTION;  
     END
ELSE IF XACT_STATE() = -1
     BEGIN
         PRINT 'The transaction is committable.' +
               ' Committing transaction.'
         COMMIT TRANSACTION;  
     END;
END TRY
...
BEGIN CATCH
         
     IF (XACT_STATE()) <> 0
     BEGIN
         PRINT 'The transaction had an error.' +
               ' Rolling back transaction.'
    ...
0
 

Author Comment

by:wdbates
ID: 40587214
Is this correct?

BEGIN

SET XACT_ABORT ON;

BEGIN TRY

BEGIN TRANSACTION

      SET NOCOUNT ON;
      DECLARE @ErrorMessage   NVARCHAR(4000);
    DECLARE @ErrorSeverity  INT;
    DECLARE @ErrorState     INT;
    DECLARE @ErrorProcedure NVARCHAR(128);
    DECLARE @ErrorLine      INT;
    DECLARE @ErrorNumber    INT;
    DECLARE @DuplicateType  INT = 1;
      
      if @DuplicateType = 1 --Duplicate master page to new test page
      begin
            PRINT 'One'
            SELECT 1/0
      end
      
      if @DuplicateType = 2 --Duplicate test page to a new test page.
      begin
            PRINT 'two'
      end
      
      if @DuplicateType = 3 --Duplicate test page to new master page
      begin
            PRINT 'tree'
      end
      
      if @DuplicateType = 4 --Duplicate master page to a new master page.
      begin
            PRINT 'four'
      end
      
      IF (XACT_STATE()) = 1
    BEGIN
        PRINT 'The transaction is committable.' +
              ' Committing transaction.'
        COMMIT TRANSACTION;  
    END
    ELSE IF XACT_STATE() = -1
     BEGIN
         PRINT 'The transaction is committable.' +
               ' Committing transaction.'
         COMMIT TRANSACTION;  
     END

END TRY

BEGIN CATCH
       
    IF (XACT_STATE()) <> 0
    BEGIN
        PRINT 'The transaction is in an uncommittable state.' +
              ' Rolling back transaction.'
            SELECT
                  @ErrorMessage   = ERROR_MESSAGE(),
                  @ErrorSeverity  = ERROR_SEVERITY(),
                  @ErrorState     = ERROR_STATE(),
                  @ErrorProcedure = ERROR_PROCEDURE(),
                  @ErrorLine      = ERROR_LINE(),
                  @ErrorNumber    = ERROR_NUMBER();
                  
        ROLLBACK TRANSACTION;
       
            RAISERROR (@ErrorMessage,   -- Message text
                         @ErrorSeverity,  -- Severity
                         @ErrorState,     -- State
                       @ErrorProcedure, -- Procedure
                       @ErrorLine,             -- Line
                       @ErrorNumber     -- Number
                  );
    END;
   
END CATCH;

END
0
 
LVL 69

Expert Comment

by:ScottPletcher
ID: 40587243
Yep, the TRY part is great.

The CATCH is not quite fully accurate.  Only -1 means "can't be committed".  I also rolled back state 1 because we are in the CATCH block, which means some type of error must have occurred.

BEGIN CATCH
         
     IF (XACT_STATE()) <> 0
     BEGIN
          IF XACT_STATE() = -1
              PRINT 'The transaction is in an uncommittable state.' +
                   ' Rolling back transaction.'
         ELSE --IF XACT_STATE() = 1
              PRINT 'The transaction had an error.' +
                   ' Rolling back transaction.'
             SELECT
                   @ErrorMessage   = ERROR_MESSAGE(),
                   @ErrorSeverity  = ERROR_SEVERITY(),
                   @ErrorState     = ERROR_STATE(),
                   @ErrorProcedure = ERROR_PROCEDURE(),
                   @ErrorLine      = ERROR_LINE(),
                   @ErrorNumber    = ERROR_NUMBER();
                   
         ROLLBACK TRANSACTION;
         
             RAISERROR (@ErrorMessage,   -- Message text
                          @ErrorSeverity,  -- Severity
                          @ErrorState,     -- State
                        @ErrorProcedure, -- Procedure
                        @ErrorLine,             -- Line
                        @ErrorNumber     -- Number
                   );
     END;
     
 END CATCH;

 END
0

Featured Post

Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article explains how to reset the password of the sa account on a Microsoft SQL Server.  The steps in this article work in SQL 2005, 2008, 2008 R2, 2012, 2014 and 2016.
The Delta outage: 650 cancelled flights, more than 1200 delayed flights, thousands of frustrated customers, tens of millions of dollars in damages – plus untold reputational damage to one of the world’s most trusted airlines. All due to a catastroph…
Using examples as well as descriptions, and references to Books Online, show the documentation available for date manipulation functions and by using a select few of these functions, show how date based data can be manipulated with these functions.
Via a live example, show how to setup several different housekeeping processes for a SQL Server.

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now