USE AdventureWorks;
GO
BEGIN TRANSACTION;
GO
DELETE FROM HumanResources.JobCandidate WHERE JobCandidateID = 10;
DELETE FROM HumanResources.JobCandidate WHERE JobCandidateID = 11;
DELETE FROM HumanResources.JobCandidate WHERE JobCandidateID = 12;
GO
COMMIT TRANSACTION;
GO
如果第一个删除语句失败会怎样?第2和第3个删除语句是否会被执行?该示例没有任何错误处理,是否会在异常情况下保留打开的事务,或者SQL Server会自动回滚事务吗?打开事务=锁定资源,对吧?
我决定是否必须将TRY ... CATCH应用于使用事务的存储过程。
我知道set xact_abort on
,但想知道没有它会发生什么。
以下是我在docs中发现的内容 - 控制事务(数据库引擎):
如果错误阻止成功完成事务,SQL Server会自动回滚事务并释放事务持有的所有资源
但是我在其他帖子中读到没有触发自动回滚。
答案 0 :(得分:12)
在您的示例中,如果不使用SET XACT_ABORT ON
,即使第一个语句失败,事务也将继续并提交。在您引用的文本中,关键字是if an error **prevents** the successful completion of a transaction
,而DELETE
语句失败并不会阻止事务完成。
导致自动回滚的错误示例是在事务中间切断与数据库的连接。在你引用的MSDN article下面说:
如果发生运行时语句错误(例如违反约束) 在批处理中,数据库引擎中的默认行为是滚动 仅返回生成错误的语句。你可以改变这个 使用SET XACT_ABORT语句的行为。 SET XACT_ABORT ON后 执行时,任何运行时语句错误都会导致自动回滚 当前的交易。编译错误,例如语法错误 不受SET XACT_ABORT的影响。
如果需要,使用错误处理来捕获错误和回滚总是一个好主意。
答案 1 :(得分:6)
我更喜欢手动控制流程:
BEGIN TRY
BEGIN TRAN
-- do work
COMMIT
END TRY
BEGIN CATCH
ROLLBACK
RAISERROR (...)
END CATCH
GO