【问题标题】: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

问题:

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

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

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

【问题讨论】:

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

标签: sql sql-server raiseerror


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 2013-07-26
    • 2016-03-28
    • 2013-12-30
    • 1970-01-01
    • 2014-01-26
    • 1970-01-01
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多