Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

IF @@TRANCOUNT > 0     COMMIT TRANSACTION;

Posted on 2015-02-03
6
Medium Priority
?
313 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
6 Comments
 
LVL 70

Accepted Solution

by:
Scott Pletcher earned 2000 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 70

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
What Is Blockchain Technology?

Blockchain is a technology that underpins the success of Bitcoin and other digital currencies, but it has uses far beyond finance. Learn how blockchain works and why it is proving disruptive to other areas of IT.

 
LVL 70

Expert Comment

by:Scott Pletcher
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 70

Expert Comment

by:Scott Pletcher
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

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

Why is this different from all of the other step by step guides?  Because I make a living as a DBA and not as a writer and I lived through this experience. Defining the name: When I talk to people they say different names on this subject stuff l…
In part one, we reviewed the prerequisites required for installing SQL Server vNext. In this part we will explore how to install Microsoft's SQL Server on Ubuntu 16.04.
This video shows, step by step, how to configure Oracle Heterogeneous Services via the Generic Gateway Agent in order to make a connection from an Oracle session and access a remote SQL Server database table.
Via a live example, show how to set up a backup for SQL Server using a Maintenance Plan and how to schedule the job into SQL Server Agent.

722 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