在数据库中没有事务的情况下,出现SQL错误“在批处理结束时检测到无法提交的事务”

8iwquhpp  于 2022-09-18  发布在  Java
关注(0)|答案(3)|浏览(287)

在我的代码的不同部分,我面临以下问题。调用存储过程后,从DB(SQL Server)返回SqlException,并显示消息“在批处理结束时检测到不可提交的事务。事务被回滚”。存储过程结构遵循以下示例:

USE [EXAMPLE_DB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_ExampleStoredProcedure]
@Parameter INT, @AnotherParameter INT

AS
BEGIN
    BEGIN TRY

    SET NOCOUNT ON;

    DECLARE @Variable INT;
    DECLARE @AnotherVariable CHAR;
    DECLARE @ErrMsg VARCHAR;

    SET @ErrMsg = '';

    /*Doing Some Stuff Here (Select, IF-THEN, etc...)

            /* I call another stored procedure */   
            EXECUTE [dbo].[sp_SecondStoredProcedure] 
                       @Param = 'Blabla'
                      ,@Param2 = 'BlaBlaBla'

            /*Here I handle some custom output parameters from second stored                           
                     procedure to handle errors */

                    /* Other stuff here */

END TRY

BEGIN CATCH    
        SET @CustomExitCode = 'XXXXX';
        SET @ErrMsg = (SELECT ERROR_MESSAGE()); 
END CATCH;

END

如您所见,在存储过程中没有事务处理。我使用TransactionScope类处理事务代码端(C#),在事务范围内调用各种存储过程,包括上面的那个(失败的那个)。

问题是:如果我没有事务SQL端,而只有一个try-Catch块,并且所有的事务处理都在代码上执行,那么为什么SQL谈论不可提交的事务?

我已经在网上搜索过了,找到了很多关于不可提交事务错误的材料,但实际上到处都有SQL端的事务处理。

我希望我已经以一种可以理解的方式解释了这个问题。很明显,我随时都可以得到进一步的信息。

非常感谢您的帮助!

干杯,加布里埃尔

km0tfn4u

km0tfn4u1#

将Try块中的所有操作 Package 在一个事务中,让SQL Server为您处理它,而不是让您在应用程序中处理它。在try块中显式开始事务并提交事务,如果在此事务期间出现任何错误,则回滚该事务。

我会做这样的事情......

ALTER PROCEDURE [dbo].[sp_ExampleStoredProcedure]
@Parameter INT, @AnotherParameter INT
AS
BEGIN
    SET NOCOUNT ON;
 BEGIN TRY
    DECLARE @Variable INT;
    DECLARE @AnotherVariable CHAR;
    DECLARE @ErrMsg VARCHAR;

    SET @ErrMsg = '';
BEGIN TRANSACTION;      --<-- Begin here 

    /*Doing Some Stuff Here (Select, IF-THEN, etc...)*/

            /* I call another stored procedure */   
            EXECUTE [dbo].[sp_SecondStoredProcedure] 
                       @Param = 'Blabla'
                      ,@Param2 = 'BlaBlaBla'
            /*Here I handle some custom output parameters from second stored                           
                     procedure to handle errors */

                    /* Other stuff here */
COMMIT TRANSACTION;     --<-- Commit here if nothing gone wrong

END TRY

BEGIN CATCH    
  IF (@@TRANCOUNT > 0)
   BEGIN
      ROLLBACK TRANSACTION;   --<-- Rollback if something went wrong
   END

           /*Other error logging here*/
        SELECT @CustomExitCode = 'XXXXX', @ErrMsg = ERROR_MESSAGE(); 
END CATCH;

END
bis0qfac

bis0qfac2#

有点晚了,但错误处理可能非常棘手,我看到许多人都在犯同样的错误。我知道Stackoverflow希望我把完整的答案放在这里,而不是链接到外部站点,但Erland Sommarskog编写了关于SQL错误处理的最终文档,他也已经在每个新的SQL服务器版本中维护了多年。我不能提供他写的关于这个问题的任何细节的答案,所以如果你想知道所有的细节,我建议你阅读他关于这个主题的三部分文章:

Part One – Jumpstart Error Handling

Part Two - Commands and Mechanisms

Part Three – Implementation

简单的答案是,您很可能在对第二个过程的调用中触发了一些错误,然后继续使用一个已经无效的事务,这导致了无法提交的事务。

r8uurelv

r8uurelv3#

如果您在“code”中启动事务,则该事务也将对该过程可见。否则,这怎么可能是真正的交易呢?

当您将事务与TRY CATCH组合在一起并发生错误时,许多错误(特别是在使用XACT_ABORT ON时)将导致“无法提交的事务错误”,请参阅XACT_STATE文档。

出错时,您必须对事务做一些操作,如果不这样做,它会在离开过程时自动回滚。

由于这些和其他原因,我们通常避免将尝试捕获与事务一起使用。因为您使用的是C#代码,所以您可能只需将try捕获移到应用程序部分,并将事务处理与XACT_ABORT一起保留,这意味着它将在出错时回滚

相关问题