如何处理触发器中的错误?

Posted

技术标签:

【中文标题】如何处理触发器中的错误?【英文标题】:How to handle errors in a trigger? 【发布时间】:2012-05-05 14:30:37 【问题描述】:

我正在编写一些在向数据库表中插入行时需要执行的 SQL 代码,因此我使用了 AFTER INSERT 触发器;代码相当复杂,因此可能仍然存在一些错误。

我发现,如果在执行触发器时发生错误,SQL Server 会中止批处理和/或整个事务。这对我来说是不可接受的,因为它会给使用数据库的主应用程序带来问题;我也没有该应用程序的源代码,因此无法对其进行适当的调试。我绝对需要所有数据库操作都成功,即使我的触发器失败。

如何编写触发器代码,以便在发生错误时,SQL Server不会中止 INSERT 操作?

此外,我怎样才能执行正确的错误处理,以便我可以真正知道触发器已失败?发送带有错误数据的电子邮件对我来说是可以的(触发器的主要目的实际上是发送电子邮件),但我如何检测触发器中的错误情况并做出反应?


编辑:

感谢有关使用触发器以外的其他东西优化性能的提示,但是从长时间运行或性能密集型的意义上说,这段代码并不“复杂”;它只是构建并发送邮件消息,但为了做到这一点,它必须从各种链接表中检索数据,并且由于我正在对该应用程序进行逆向工程,因此我没有可用的数据库模式并且仍在尝试查找我绕着它走;这就是为什么转换错误或意外/空值仍然会蔓延,导致触发器执行崩溃的原因。

另外,如上所述,我绝对不能对应用程序本身进行调试,也不能修改它以在应用程序层做我需要的事情;对应用程序事件做出反应的唯一方法是在应用程序向数据库写入刚刚发生的事情时触发数据库触发器。

【问题讨论】:

您可以在触发器内部使用TRY ... CATCH 来忽略,但会记录错误。 您没有可用的架构?这是什么意思?当然,您可以检查表/列(如果没有,您是如何开始这项任务的?) 我的意思是,根本没有文档;我必须自己找到数据库结构是什么。而且它非常混乱(我尝试过绘制图表,但它痛苦)。 【参考方案1】:

如果触发器中的操作很复杂和/或可能长时间运行,并且您不希望活动影响原始事务,那么您需要找到一种方法来解耦活动。

一种方法可能是使用Service Broker。在触发器中,只需创建消息(每行一个)并在途中发送它们,然后在服务中执行其余处理。

如果这看起来太复杂,那么较旧的方法是将需要处理的行插入工作/队列表中,然后让工作不断地从那里拉出行来完成工作。

无论哪种方式,您现在都不会阻止原始事务提交。

【讨论】:

【参考方案2】:

触发器是事务的一部分。您可以尝试在触发器代码周围捕获燕子,或者更专业地尝试捕获日志燕子,但实际上您应该让它爆炸,然后解决只能在您的触发器中的真正问题。 如果以上都不可接受,则不能使用触发器。

【讨论】:

我只能在使用真实数据从应用程序调用触发器时调试触发器......但是,我没有调试器。这就是为什么我需要一种方法让它自己处理错误(并通知我以便我可以修复它们)。 所以你唯一真正的选择是尝试捕获触发代码,记录,然后吞下。紧随其后的当然是闭上眼睛,经常大声祈祷。如果它失败了,就会有一个异常,它应该出现在某处的某个日志中,除非有人已经尝试过捕捉燕子。这取决于你,但我会设置一个测试环境,就像在带有触发器的数据库副本中一样,然后尝试破坏它,而不是交叉手指并希望没有其他任何东西。交叉手指对我来说从来没有用过,一次也没有。

以上是关于如何处理触发器中的错误?的主要内容,如果未能解决你的问题,请参考以下文章

您如何处理深度链接插件中的简历场景?

如何处理 ERD(表)设计中的“或”关系?

如何处理 Android 运行时权限中的“不再询问”复选框?

我应该如何处理 mysql 触发器中字段列表中未知的“Col_name”列?

多时域设计中,如何处理信号跨时域

自动布局和编程约束:如何处理多次触发的 updateConstraints?