回滚一批不容易?

时间:2013-07-04 00:52:19

标签: sql tsql sql-server-2005

经过两天的批量测试,回滚并尝试..catch,我的思绪仍然模糊不清。为了澄清我的问题,我将我正在做的事分成两步。

1。回滚批次 正如在线书籍所解释的那样,在批处理中,只有批处理在事务中并且批处理中的错误导致事务回滚,否则执行的语句不能回滚。

所以我把批处理放到像

这样的交易中
begin transaction
     create table  A ...
     insert into A values...
     insert into A values... (error here!)
     insert into A values...
     GO
rollback

这适用于错误输出,并且没有创建表

(1 row(s) affected)
Msg 213, Level 16, State 1, Line 5
Column name or number of supplied values does not match table definition.

Msg 208, Level 16, State 1, Line 1
Invalid object name 'A'.

但是,即使在事务中没有错误,也会执行回滚。为了处理这种情况,我使用TRY ... CATCH,如2。

2。使用TRY ... CATCH

BEGIN TRY
   begin transaction
     create table  A ...
     insert into A values...
     insert into A values... (error here!)
     insert into A values...
     --GO
END TRY 
BEGIN CATCH
     ROLLBACK
END CATCH

这次不再允许声明GO了。 S * o在这种情况下,批处理是BEGIN TRYEND TRY之间的整个块? *   另外,结果并不像我预期的那样。 CREATE TABLE和第一个插入仍然执行但没有回滚。   我再次搜查。 似乎我需要SET XACT_ABORT ON才能在触摸提交之前将这些执行的语句记录为未提交。我在这里理解的是对的吗?如果是这样,我在这种情况下没有添加任何提交语句。

顺便说一句,测试是在SQL SERVER 2012上完成的。感谢您的任何澄清!

2 个答案:

答案 0 :(得分:1)

它不允许GO语句的原因是try和catch必须是此MSDN article中提到的同一批次的一部分。它说明了;

  

“每个TRY ... CATCH构造必须在一个批次内,存储   程序或触发器。例如,您不能放置TRY块   一个批次和另一个批次中的关联CATCH块。该   以下脚本会生成错误:“

BEGIN TRY
    SELECT *
        FROM sys.messages
        WHERE message_id = 21;
END TRY
GO
-- The previous GO breaks the script into two batches,
-- generating syntax errors. The script runs if this GO
-- is removed.
BEGIN CATCH
    SELECT ERROR_NUMBER() AS ErrorNumber;
END CATCH;
GO

关于如何处理这个问题的另一个想法,看看问题Nested stored procedures containing TRY CATCH ROLLBACK pattern?上的gbns答案,因为他讨论了他处理交易的模式/模板,包括使用(和原因)XACT_ABORT和其他漂亮的特征。我还建议阅读gbns回答中的相关链接

Aaron Betrand对同一问题的回答是指Erland Somarsskog的article on error handling与gbn的回答非常相似。

即使原始问题的标题与嵌套交易有关,但它仍然适用于我认为的情况。

答案 1 :(得分:0)

尝试在脚本开头使用SET XACT_ABORT ON。查看XACT_ABORT MSDN参考页here