2

经过两天的批量测试,回滚并尝试..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'.

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

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 TRYAND之间的整个块END TRY* 另外,结果并不如我所愿。AND第CREATE TABLE一个插入仍然执行并且没有回滚。我又找了一遍。看来我需要SET XACT_ABORT ON在触摸提交之前将这些执行的语句记录为未提交。我在这里的理解是对的吗?如果是这样,在这种情况下我没有添加任何提交语句。

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

4

2 回答 2

1

它不允许 GO 语句的原因是 try 和 catch 必须与此MSDN 文章中提到的同一批次的一部分。它指出;

“每个 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

有关如何处理此问题的另一种想法,请查看 gbns 对包含 TRY CATCH ROLLBACK 模式的嵌套存储过程问题的回答?他讨论了他处理交易的模式/模板,包括 XACT_ABORT 和其他漂亮特性的使用(和原因)。我还建议阅读 gbns 答案中的相关链接

Aaron Betrand 对同一问题的回答参考了 Erland Somarsskog 的一篇关于错误处理的文章,该文章也与 gbn 的回答非常相似。

即使原始问题的标题与嵌套事务有关,我相信它仍然适用于您的情况。

于 2013-07-04T06:01:39.163 回答
0

尝试XACT_ABORT ON在脚本开头使用 SET。

在此处查看XACT_ABORTMDSN 参考页面

于 2013-07-04T01:09:25.307 回答