如果任何语句失败,将回滚的 SQL 查询
Posted
技术标签:
【中文标题】如果任何语句失败,将回滚的 SQL 查询【英文标题】:SQL query that'll rollback if any statements fails 【发布时间】:2011-01-15 09:11:41 【问题描述】:我想编写一个执行多个单独 SQL 语句的 SQL 脚本;如果这些语句中的任何一个失败,我想回滚整个事务。所以,像:
BEGIN TRANSACTION
insert into TestTable values (1)
insert into TestTable values (2)
insert into TestTabe values (3)
--if any of the statements fail
ROLLBACK
--else
COMMIT
这是针对 MS SQL 2008 的。有什么我可以做的吗?也许是某种异常处理?
我意识到在我的示例中我可以检查这些值的 TestTable 并确定语句是否以这种方式失败。但实际上我的 SQL 会复杂得多,我宁愿抽象自己不知道 SQL 在做什么。
【问题讨论】:
【参考方案1】:我很懒,在我的所有陈述中都添加了这一行
SET XACT_ABORT ON
http://technet.microsoft.com/en-us/library/ms188792.aspx
当 SET XACT_ABORT 为 ON 时,如果 Transact-SQL 语句引发一个 运行时错误,整个事务 被终止并回滚。
当 SET XACT_ABORT 为 OFF 时,在某些 仅适用于 Transact-SQL 语句 引发错误的回滚 交易继续 加工。取决于 错误的严重性,整个 甚至可以回滚事务 当 SET XACT_ABORT 为 OFF 时。关是 默认设置。
编译错误,例如语法错误, 不受 SET XACT_ABORT 影响。
XACT_ABORT 必须为数据设置为 ON 隐式中的修改语句 或针对大多数人的明确交易 OLE DB 提供程序,包括 SQL 服务器。唯一的这种情况 选项不是必需的,如果 provider 支持嵌套事务。 有关详细信息,请参阅分布式 查询和分布式事务。
SET XACT_ABORT 的设置被设置 在执行或运行时而不是在 解析时间。
【讨论】:
【参考方案2】:这是我过去做过的一种方式:
Declare @HasError int;
set @HasError = 0;
BEGIN TRANSACTION
insert into TestTable values (1)
if (@@ERROR != 0)
set @HasError = 1
insert into TestTable values (2)
if (@@ERROR != 0)
set @HasError = 1
insert into TestTabe values (3)
if (@@ERROR != 0)
set @HasError = 1
if @HasError > 0
ROLLBACK TRANSACTION
ELSE
COMMIT TRANSACTION
【讨论】:
另一个有趣的建议。谢谢。虽然我会使用与@error 不同的名称,但更清楚的是它与@ERROR 不同。 是的,我现在头疼的少了:)【参考方案3】:自 2005 年以来,SQL Server 就提供了异常支持:
BEGIN TRY
BEGIN TRAN
INSERT INTO ...
COMMIT TRAN
END TRY
BEGIN CATCH
EXECUTE usp_LogAndRethrowError
END CATCH
然后您的 LogAndRethrowError 可以回滚任何注定失败的事务,例如:
-- Make sure we are not in a live or 'doomed' transaction
IF XACT_STATE() <> 0
ROLLBACK TRANSACTION
【讨论】:
@Nathan 如所述“您的 LogAndRethrowError 然后可以回滚任何注定失败的事务”。因此,您可以在 Catch 语句中添加 ROLLBACK TRAN(或让 SP 为您完成)。 不知何故没看到那部分答案。以上是关于如果任何语句失败,将回滚的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章