【问题标题】:RAISERROR Severity Level 16 IS rolling back transactionRAISERROR 严重级别 16 是回滚事务
【发布时间】:2017-06-29 20:10:09
【问题描述】:

我遇到了 AFTER INSERT UPDATE TRIGGER 的问题。测试代码如下。问题是当这个表上的事务启动时,它会回滚。

在网上进行了大量研究后,似乎每个人都认为情况并非如此。无论如何,我缺少服务器端设置吗?

我还将 sp_settriggerorder() 添加到第一个触发器中,最后命名有问题的触发器。

我还注意到,禁用以下触发器可以完成交易。

低于 11 的严重性不是一个选项,因为它会在客户端应用程序中提示一个丑陋的警告,以强制用户“扩展”选择。

严重性 11 到 16 都给我这个问题。

USE [Test]
GO
/****** Object:  Trigger [dbo].[co_bln_AfterIup]    Script Date: 06/29/2017 14:43:12 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[co_bln_AfterIup]
ON [dbo].[co_bln]
AFTER INSERT,UPDATE

AS

IF 1 = 1

RAISERROR('test error',16,1)

【问题讨论】:

  • 我没有关注你。有什么问题?
  • 我也很困惑。您是否用此错误替换了实际的触发器查询以进行测试?您确定事务已创建然后回滚,还是可能是更新/插入本身的问题并且 RAISERROR 是一个红鲱鱼?

标签: sql-server sql-server-2008-r2


【解决方案1】:

简答

1# 在触发器执行开始时设置 SET XACT_ABORT OFF

2# 做一些 DML(插入/更新/删除)

3# 设置触发 RAISERROR 的条件,消息和严重性低于 18

4# 结果将被提交事务并引发错误

更长的答案

SQL Server 中有两种处理错误的方法,一种是使用 RAISERROR,另一种是使用 THROW。你更喜欢哪一个取决于进一步的解释

使用 throw 不能指定严重性,而使用 RAISERROR 可以 使用更高(18 以上)的严重性可以终止用户连接,这不是你可以用 throw 做的事情

RAISERROR 也可以在显式事务 (BEGIN/END) 中指定,而 THROW 不能(必须使用 TRY/CATCH 块)。

这里重要的是连接这两个错误处理程序的东西是 XACT_ABORT 通过指定 XACT_ABORT,您正在定义事务行为

在单个事务中可能有某些事务会失败,其中一些不会失败,具体取决于 XACT_ABORT 是 ON 还是 OFF ,其中一些成功的事务可能会被执行,而另一些则不会,这通常是你的如果你想保持一致的数据库不想做 更多关于 XACT_ABORT 你可以阅读here

现在这与您的错误处理程序有什么关系?

如果您在事务开始时指定 SET XACT_ABORT OFF,您的 RAISERROR 错误处理程序将不会回滚事务,并且您之前所做的任何事情都会反映到数据库中。 您必须使用显式 ROLLBACK 事务或启用 XACT_ABORT 来防止这种情况发生

如果您想使用 TRY/CATCH 块,并进行一些错误处理,您可以使用其中任何一种。每当您调用 RAISERROR 或 THROW 时,您将被直接转移到 CATCH 块。但是请记住,如果 XACT_ABORT 为 OFF,并且您使用的是没有 ROLLBACK 命令的 RAISERROR,那么即使您在 catch 块中,该事务也将无论如何完成。 如果你使用 THROW 会立即回滚

然而 XACT_ABORT on 或 off 对 THROW 处理程序没有影响,并将按预期执行(回滚所有更改)

还要注意,即使 XACT_ABORT OFF,您仍然可以使用超过 18 的严重性回滚事务

因此,根据您要达到的目标,您可以选择最适合您的目标。遵循标准,THROW 是一种选择,它是较新的,但如果您只想显示警告 - 返回 简答

【讨论】:

    【解决方案2】:

    如果您不希望 RAISERROR 结束事务,您可以在 TRY/CATCH 块中将 RAISERROR 周围的语句括起来。或者,您可以用 TRY/CATCH 块包围触发触发器的 INSERT/UPDATE 语句。

    来自RAISERROR 文档(备注):

    当 RAISERROR 在 TRY 块中以 11 或更高的严重性运行时,它会将控制权转移到关联的 CATCH 块。

    严重性在 11 到 20 之间的 RAISERROR 应将控制权转移到 catch 块,如果您不这样写,则不一定要中止事务。

    没有看到你所有的代码,我猜你的程序的某些部分正在回滚事务,作为对触发器中引发的错误的响应。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-17
      • 2015-08-19
      相关资源
      最近更新 更多