【问题标题】:Savepoints in triggers触发器中的保存点
【发布时间】:2019-11-14 01:39:33
【问题描述】:

我有 3 张桌子,比如说 A 桌、B 桌和 C 桌。

我在表 A 上有一个触发器,它将数据插入到表 B 中,我在表 b 上也有一个触发器,将数据输入到表 C 中。在表 C 上,有一个执行过程的触发器。

任务是即使在对表 C 的操作过程中发生了某些事情,即(发生任何错误),对表 A、B 和 C 的操作也应该继续并完成。问题是如果程序出现问题,对表 A、B 和 C 的操作也会中止。

我的表 C 触发器是:

CREATE TRIGGER [dbo].[Trg_Mst_TableC] 
ON [dbo].[TableC]
FOR UPDATE 
AS 
BEGIN
    DECLARE @flg_Error INT
    SET @flg_Error  = 0

    DECLARE @SLQString NVARCHAR(MAX) 

    SELECT @SLQString  = 'Text Message' 

    SAVE TRANSACTION MySavePoint                                    

    IF ISNULL(@SLQString, '') <> '' 
    BEGIN 
        EXEC spMsc_SendMsg 'Test', 'POST',  @SLQString

        IF @@error <> 0 BEGIN 
            ROLLBACK TRAN MySavePoint
        END 
    END
END

这是我的程序:

CREATE PROCEDURE [dbo].[spMsc_SendMsg]  
     @msg_type NVARCHAR(50),  
     @getpost NVARCHAR(20),  
     @msg_txt NVARCHAR(MAX)  
AS  
BEGIN  
    SET NOCOUNT ON 

    SAVE TRANSACTION MySavePoint

    CREATE TABLE Test (XXX NVARCHAR(MAX))

    SELECT @msg_type, @getpost, @msg_txt
END   

现在此过程返回“测试”表的错误消息。但我需要保存完成的剩余事务直到触发器 C。 请给我解决方案。

【问题讨论】:

  • 您不能在触发器中COMMIT 事务。事务的处理应该在它之外完成,而不是在里面。您在这里真正要解决的问题是什么?
  • 我推荐XACT_ABORT ON、TRY .. CATCH 并在您尝试任何非平凡的错误处理之前阅读所有this。如果可能的话,如果您不希望原始事务中止,请不要在触发器中做任何可能出错的事情——如有必要,通过插入表或服务代理队列来推迟处理。
  • 哦,触发其他触发器的触发器本质上是撒旦的工具。可能应该重新考虑这样的设计,以支持在表 A、B 和 C 上操作的存储过程调用,因为整个操作显然代表的不仅仅是单个插入。即使由于无法更改客户端代码而必须使用触发器,但最好不要嵌套触发器,而是将所有逻辑放在一个级别上。 TRIGGER_NESTLEVEL() 可用于检查是否从嵌套上下文中调用了触发器,如果​​是这种情况,则无需执行任何操作即可返回。

标签: sql-server tsql stored-procedures database-trigger savepoints


【解决方案1】:

您可以使用 TRY CATCH 块来控制在特定触发器中发生错误时您希望发生的事情,而不是使用事务和回滚。

【讨论】:

    猜你喜欢
    • 2016-07-28
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    • 2019-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多