如何防止未来的批次在错误和回滚时完成?

时间:2011-07-12 15:22:59

标签: sql sql-server-2005 transactions

如果我有以下SQL查询

CREATE TABLE #t1
    (a INT NOT NULL PRIMARY KEY);
SET XACT_ABORT ON
go

BEGIN TRANSACTION
INSERT INTO #t1 VALUES (1);
INSERT INTO #t1 VALUES (2);
INSERT INTO #t1 VALUES (3);
INSERT INTO #t1 VALUES (2); -- PK violation error
go

INSERT INTO #t1 VALUES (4);
go

COMMIT TRANSACTION

SET XACT_ABORT OFF

当我运行查询时,我得到了这个输出

  

(1行受影响)

     

(1行受影响)

     

(1行(s)受影响)Msg 2627,Level 14,State 1,Line 7违反   PRIMARY KEY约束'PK_ #t1 _ __ _ _ _66D536B1'。无法插入   对象'dbo中的重复键。#t1'。

     

(1行(s)受影响)消息102,级别15,状态1,行8不正确   '#t1'附近的语法。

#t1的值是

a
-----------
4

我需要做什么才能使脚本中止而不运行第二批?

编辑:

尝试过JNK的解决方案

begin try
BEGIN TRANSACTION
INSERT INTO #t1 VALUES (1)
INSERT INTO #t1 VALUES (2)
INSERT INTO #t1 VALUES (3)
INSERT INTO #t1 VALUES (2) -- PK violation error
go

INSERT INTO #t1 VALUES (4)
go

COMMIT TRANSACTION

end try
begin catch 
IF @@trancount > 0 Rollback

END catch

select * from #t1

truncate table #t1

但是我得到了这个输出

Msg 102, Level 15, State 1, Line 6
Incorrect syntax near ')'.

(1 row(s) affected)
Msg 102, Level 15, State 1, Line 5
Incorrect syntax near 'begin'.
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near 'END'.

表格中仍然包含4个

EDIT2:

try catch的错误是因为GO语句,我需要为我的真实脚本而不是这个测试用例。所以看起来try / catch对于这种情况不起作用。

2 个答案:

答案 0 :(得分:1)

添加错误处理:

BEGIN TRY
<your query>
END TRY
BEGIN CATCH

IF @@TRANCOUNT > 0 ROLLBACK    

<other error reporting processes>

END CATCH

ROLLBACK是可选的,将撤消在发生错误之前完成的所有插入。您还可以添加多个事务,因此如果前三个插入与以后的某些其他内容无关,请将它们包装在事务中并提交它,然后再为其进行另一个转换。

答案 1 :(得分:0)

begin try
   begin transaction

    INSERT INTO #t1 VALUES (1);
    INSERT INTO #t1 VALUES (2);
    INSERT INTO #t1 VALUES (3);
    INSERT INTO #t1 VALUES (2); 
    INSERT INTO #t1 VALUES (4);

   commit
end try
begin catch
    if @@trancount > 0
        rollback

    declare @errmsg nvarchar(4000), @errseverity int
    select @errmsg = error_message(), @errseverity = error_severity()

    raiserror(@errmsg, @errseverity, 1)
end catch

来自MSDN: “ 将GO解释为他们应该将当前批处理的Transact-SQL语句发送到SQL Server实例的信号。当前一批语句由自上次GO以来输入的所有语句组成,或者自ad hoc会话或脚本开始以来(如果这是第一个GO )。

Transact-SQL语句不能与GO命令占用同一行。但是,该行可以包含注释。