今天在做项目时,由于业务需求,需要在SQL语句的事务中添加条件判断,不符合条件则跳出事务进行回滚,但是在执行了SQL语句后,系统提示异常错误:COMMIT TRANSACTION 请求没有对应的 BEGIN TRANSACTION。
以下是出现错误的SQL部分语句:
BEGIN TRAN
--进行判断,不符合条件就回滚,不执行其他操作
IF NOT EXISTS(SELECT [ID] FROM [TestTable] WHERE NO='123')
BEGIN
ROLLBACK TRAN;
END
--这里执行其他SQL操作语句。
UPDATE TestTable SET NO='312' WHERE NO='122'
--如果有错误就回滚,没错误就提交
IF(@@ERROR<>0)
BEGIN
ROLLBACK TRAN;
END
ELSE
BEGIN
COMMIT TRAN;
END
此错误的原因是由于一个事务只能对应一个操作,要么回滚要么提交,所以执行了ROLLBACK TRAN语句后一定不能再执行COMMIT TRAN语句!!!而无论是回滚事务还是提交事务,都是不会中断SQL处理流程的,要想中断流程就需要使用RETURN语句。
上面范例中的语句先执行了ROLLBACK TRAN回滚操作(这里造成事务已经处理完成),但是并没有中断流程,所以后面的语句依然会继续执行。执行过程中由于没有任何异常错误,最终导致重复执行了底部的COMMIT TRAN事务提交操作,最后一次事务操作没有找到相匹配的事务声明,就会提示"COMMIT TRANSACTION(事务提交) 请求没有对应的 BEGIN TRANSACTION(事务声明)"这个错误。
所以要跳出事务,在进行回滚ROLLBACK操作后,还必须马上使用RETURN语句跳出执行流程。以下为修改后的语句:
BEGIN TRAN
--进行判断,不符合条件就回滚,不执行其他操作
IF NOT EXISTS(SELECT [ID] FROM [TestTable] WHERE NO='123')
BEGIN
ROLLBACK TRAN;
--------------------------------
--这里需要添加RETURN,中断处理流程,防止重复执行事务提交!
RETURN;
--------------------------------
END
--这里执行其他SQL操作语句。
UPDATE TestTable SET NO='312' WHERE NO='122'
--如果有错误就回滚,没错误就提交
IF(@@ERROR<>0)
BEGIN
ROLLBACK TRAN;
END
ELSE
BEGIN
COMMIT TRAN;
END
这里在做一个简单测试,有助于理解所谓的一个事务只能对应一个事务操作的意思,在SQL中输入下图的三行代码并执行:
事务的语法只能一一对应,我们只有一个事务声明但是却有两个事务操作,最后一个事务操作无法找到匹配的事务声明,自然就出错。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/98294.html