Sql-server – Transaction Error in TRY CATCH block

rollbacksql serversql-server-2008-r2transaction

The following code returns this message in case something goes wrong:

Transaction count after EXECUTE indicates a mismatching number of
BEGIN and COMMIT statements. Previous count = 0, current count = 1.

OPEN extensionViews
     FETCH NEXT FROM extensionViews
     INTO @Viewname
     WHILE @@FETCH_STATUS = 0
     BEGIN      
        BEGIN TRY
                exec sp_refreshview @Viewname
        END TRY
        BEGIN CATCH
            print 'ERROR sp_refreshview'
        END CATCH 

        FETCH NEXT FROM extensionViews
        INTO @Viewname
     END
     CLOSE extensionViews
     DEALLOCATE extensionViews

I already found out that there is something going wrong with the implicit transactions, but I do not really understand it entirely.

In case of a CATCH, do I have to explicitly ROLLBACK the transaction? Does this mean that I have to start the transaction explicitly as well insode of the Cursor to rollback THIS one command instead of all?

Best Answer

Given the following info:

Previous count = 0, current count = 1.

the implication is that sp_refreshview is opening an explicit transaction but encountering an unhandled exception such that it doesn't do its own ROLLBACK. The "Previous count = 0" means that your code is not creating the Transaction.

This is not something that you can fix in your code because a subprocess must exit with the same @@TRANCOUNT that it started with. I doubt you will be able to add a ROLLBACK, or even a BEGIN TRAN and then ROLLBACK to help this.

At the very least, you need to figure out which View is causing the problem. You can do that by printing the view name being given to that system stored procedure before executing sp_refreshview, especially if the error is one of the few that cannot be trapped by the TRY...CATCH construct. Just add the following statement just after the BEGIN TRY:

RAISERROR(N'View: %s', 10, 1, @ViewName) WITH NOWAIT;

Also, it would be helpful to see the exact error message, so replace the PRINT in the CATCH block with the following query:

SELECT @Viewname AS [ViewName],
       ERROR_NUMBER() AS [ErrorNumber],
       ERROR_MESSAGE() AS [ErrorMessage];

You can also add the following to the CATCH block, but I doubt it will solve this issue:

IF (@@TRANCOUNT > 0)
BEGIN
  ROLLBACK;
END;

P.S. You should be using sysname (all lower-case) for variable and columns that hold SQL Server object names since that is the datatype used in the system tables for object names. sysname is an alias for NVARCHAR(128).