SQL Server Try/Catch、Begin/Tran、RaiseError、Loop 和 Return。正确的顺序是啥?

Posted

技术标签:

【中文标题】SQL Server Try/Catch、Begin/Tran、RaiseError、Loop 和 Return。正确的顺序是啥?【英文标题】:SQL Server Try/Catch, Begin/Tran, RaiseError, Loop, & Return. What's the right order?SQL Server Try/Catch、Begin/Tran、RaiseError、Loop 和 Return。正确的顺序是什么? 【发布时间】:2018-01-03 16:51:26 【问题描述】:

我有以下程序。 (语法并不完美,只是想给大家一个想法)。

begin tran

begin try

while loop
  some condition, if true
   raiseerror('error', 16, 1)

end try
begin catch
  if transaction > 0
    rollback tran
  select error message
end catch

if transaction > 0
  commit tran

问题:

    raise 错误会强制 catch 块吗?如果是这样,事务是否会完全回滚(对于循环的所有迭代)?

    我希望#1这样,是否需要在回滚后添加“RETURN”?

我问这个问题是因为即使在迭代中出现一些错误之后,循环似乎仍在继续。

【问题讨论】:

首先要做的事......你不应该在几乎所有情况下都使用循环来修改数据。但是,当然,如果您发出回滚,它会回滚整个事务。如果您在每次通过循环时都在执行事务,那么您的事务范围将是循环的主体。您应该将您的提交放在循环之后作为“结束尝试”之前的最后一条语句。不需要用 if 语句包装它。 这很复杂。在不同的情况和上下文中,哪些语句可能失败以及正确的恢复步骤是不同的。例如,大多数 SQL 开发人员可能不知道COMMIT 可能会失败,但它可以。 @SeanLange 我曾经有过只有一些被回滚的时候——他们有docs.microsoft.com/en-us/sql/t-sql/statements/…是有原因的 @Rj。如果您正在寻找一种方法来完成拥有多个 try/catch 块的方法,所有这些块都包含在单个事务中,并且具有全有或全无规则(如果有任何失败,则将其全部回滚),请告诉我,就像我所做的那样那,并用基本的代码结构回答了一个关于SO的问题。 @Eli,是的,这就是我想要完成的。 【参考方案1】:

看看这个问题(你真的问过):SQL Server XACT_ABORT with exclusion

虽然问题略有不同,但它显示了如何完成您正在尝试做的事情的基本结构。

30 秒的运行过程如下:像您所做的那样使用 try/catch 块,并在您的过程结束时有一个名为“失败”的部分,所有捕获都将指向该部分。您可以在每个 catch 中为您的日志记录设置一条消息,或将错误传递给最终用户。

【讨论】:

以上是关于SQL Server Try/Catch、Begin/Tran、RaiseError、Loop 和 Return。正确的顺序是啥?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 数据库try catch 存储过程

SQL Server Try/Catch、Begin/Tran、RaiseError、Loop 和 Return。正确的顺序是啥?

SQL Server中事务transaction如果没写在try catch中,就算中间语句报错还是会提交

SQL Server 2008 中的错误日志记录

TRY/CATCH 块与 SQL 检查

Sql语法高级应用之六:如何在Sql语句中如何使用TRY...CATCH