13
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 - Controlling Transactions (Database Engine) 中找到的内容:

如果错误阻止事务的成功完成,SQL Server 会自动回滚事务并释放事务占用的所有资源

但是我在其他帖子中读到不会触发自动回滚。

4

2 回答 2

17

在您的示例中,如果不使用SET XACT_ABORT ON,即使第一条语句失败,事务也将继续并提交。在您引用的文本中,关键字是if an error **prevents** the successful completion of a transaction,并且DELETE语句失败不会阻止事务完成。

一个会导致自动回滚的错误示例是,如果与数据库的连接在事务中间被切断。在您引用的MSDN 文章中进一步说:

如果批处理中发生运行时语句错误(例如违反约束),则数据库引擎中的默认行为是仅回滚生成错误的语句。您可以使用 SET XACT_ABORT 语句更改此行为。执行 SET XACT_ABORT ON 后,任何运行时语句错误都会导致当前事务的自动回滚。编译错误(例如语法错误)不受 SET XACT_ABORT 影响。

使用错误处理来捕获错误并在需要时回滚总是一个好主意。

于 2012-07-10T13:58:49.387 回答
7

我更喜欢手动控制过程:

BEGIN TRY
BEGIN TRAN

   -- do work

COMMIT
END TRY
BEGIN CATCH
    ROLLBACK
    RAISERROR (...)
END CATCH
GO
于 2012-07-10T13:57:24.440 回答