我正在尝试编写一个具有事务和try/catch块的MS sql脚本。如果它捕获异常,则回滚事务。如果没有,则提交事务。我见过几个不同的网站说这样做:
begin transaction
begin try
--main content of script here
end try
begin catch
rollback transaction
end catch
commit transaction
但是,即使在捕获异常的情况下,我们也不会仍然命中“提交事务”行吗?这不会导致 SQL 错误,因为事务已经回滚吗?我认为应该这样做:
declare @success bit = 1
begin transaction
begin try
--main content of script here
end try
begin catch
rollback transaction
set @success = 0
end catch
if(@success = 1)
begin
commit transaction
end
为什么通常发布的解决方案不包括@成功变量?提交已经回滚的事务时没有发生sql错误吗?我说第一个代码示例的“提交事务”行在捕获异常的情况下仍然会被击中是不正确的吗?
我在ms sql脚本模式下成功使用了几次,其中使用了尝试-捕获、提交事务-回滚事务、错误跟踪。
您的TRY块将如下所示
BEGIN TRY
BEGIN TRANSACTION T
----
//your script block
----
COMMIT TRANSACTION T
END TRY
您的捕获块将如下所示
BEGIN CATCH
DECLARE @ErrMsg NVarChar(4000),
@ErrNum Int,
@ErrSeverity Int,
@ErrState Int,
@ErrLine Int,
@ErrProc NVarChar(200)
SELECT @ErrNum = Error_Number(),
@ErrSeverity = Error_Severity(),
@ErrState = Error_State(),
@ErrLine = Error_Line(),
@ErrProc = IsNull(Error_Procedure(), '-')
SET @ErrMsg = N'ErrLine: ' + rtrim(@ErrLine) + ', proc: ' + RTRIM(@ErrProc) + ',
Message: '+ Error_Message()
您的回滚脚本将成为 CATCH 块的一部分,如下所示
IF (@@TRANCOUNT) > 0
BEGIN
PRINT 'ROLLBACK: ' + SUBSTRING(@ErrMsg,1,4000)
ROLLBACK TRANSACTION T
END
ELSE
BEGIN
PRINT SUBSTRING(@ErrMsg,1,4000);
END
END CATCH
在不同的脚本块之上,您需要将其用作一个块。如果TRY块中发生任何错误,它将进入CATCH块。在那里它设置了有关错误编号、错误严重性、错误行…等的各种详细信息。最后所有这些细节都将附加到@ErrMsg参数中。然后它将检查事务计数(@@TRANCOUNT
我们将COMMIT TRANSACTION T脚本保留在TRY块的最后一行,以确保它应该在TRY块中的所有代码成功运行后才提交事务(数据库中的最终更改)。
在您的第一个示例中,您是正确的。无论try块是否触发,批处理都会命中提交事务。
在你的第二个例子中,我同意其他评论者的观点。使用成功标志是不必要的。
我认为以下方法本质上是一种轻量级的最佳实践方法。
如果您想了解它如何处理异常,请将第二次插入的值从255更改为256。
CREATE TABLE #TEMP ( ID TINYINT NOT NULL );
INSERT INTO #TEMP( ID ) VALUES ( 1 )
BEGIN TRY
BEGIN TRANSACTION
INSERT INTO #TEMP( ID ) VALUES ( 2 )
INSERT INTO #TEMP( ID ) VALUES ( 255 )
COMMIT TRANSACTION
END TRY
BEGIN CATCH
DECLARE
@ErrorMessage NVARCHAR(4000),
@ErrorSeverity INT,
@ErrorState INT;
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (
@ErrorMessage,
@ErrorSeverity,
@ErrorState
);
ROLLBACK TRANSACTION
END CATCH
SET NOCOUNT ON
SELECT ID
FROM #TEMP
DROP TABLE #TEMP
我一直认为这是关于这个主题的较好的文章之一。它包括下面的例子,我认为这个例子很清楚,并且包括经常被忽略的@@trancount,可靠的嵌套事务需要它
PRINT 'BEFORE TRY'
BEGIN TRY
BEGIN TRAN
PRINT 'First Statement in the TRY block'
INSERT INTO dbo.Account(AccountId, Name , Balance) VALUES(1, 'Account1', 10000)
UPDATE dbo.Account SET Balance = Balance + CAST('TEN THOUSAND' AS MONEY) WHERE AccountId = 1
INSERT INTO dbo.Account(AccountId, Name , Balance) VALUES(2, 'Account2', 20000)
PRINT 'Last Statement in the TRY block'
COMMIT TRAN
END TRY
BEGIN CATCH
PRINT 'In CATCH Block'
IF(@@TRANCOUNT > 0)
ROLLBACK TRAN;
THROW; -- raise error to the client
END CATCH
PRINT 'After END CATCH'
SELECT * FROM dbo.Account WITH(NOLOCK)
GO
以下是使用事务教程中描述的提交和回滚的代码示例。 此示例代码是基于前面章节中完成的环境和数据库设置编写的。 复制并将以下示例代码保存到:CommitAndRollback.java 中,编译并运行如下 - 编译并运行结果如下 -
我是WebServices的新手。Im通过标记为“Transacted”的camel路由向cxfendpoint发送webservice请求,并得到响应。在同一事务路由中,next语句抛出一个异常,以便我的异常处理程序回滚该事务。 我可以在我的事务回滚中找到其他东西,除了我的webservice请求响应,因为它已经提交了。
我正在处理一些旧的应用程序代码,其中似乎涉及到几个概念,因此我希望能够将它们改进为一个坚实而严格的实践。 基本上,整个代码都用这样的HibernateSessionRequest estFilter包装 然后,有一个拦截器,做这样的事情 然后还有更多的业务逻辑代码,包括更多的初始事务和会话清除等。 那么,问题是: 当在同一会话中多次调用beginTransaction时会发生什么 非常感谢。
问题内容: 我无法避免在RuntimeException之后阻止事务回滚。我的环境是在Websphere 8.0上运行的Spring 4.1 + Hibernate 3.6 + JTA(WebSphereUowTransactionManager)。 首先,一个简单的情况表现出预期的效果。由于我 捕获了RuntimeException ,因此事务提交并成功创建了新资源。 下一个也可以。我声明了 n
问题内容: 调用的方法: 1. Struts Action 2.服务类方法(由@Transactional注释) 3. Xfire Web服务调用 包括struts(DelegatingActionProxy)和事务在内的所有内容都使用Spring进行配置。 持久性是通过JPA / Hibernate完成的。 有时,Web服务将引发未经检查的异常。我捕获了此异常并抛出了一个已检查的异常。我不希望事