2

我在将语句插入表时有一个触发器(可能会修改插入的值)。如果触发器中发生错误,我想记录它。并且 INSERT 仍然必须插入。所以我使用了一个 TRY / CATCH 块,其中 catch 部分将进行日志记录。问题是我只能回滚整个事务然后记录。但随后插入也被回滚。

在 Sql Server 2008 上运行...

到目前为止,一切都很好。

为了测试捕获部分的日志记录,我使用了 RAISERROR。(也许这是个问题?我会回到那部分)。然后我运行插入到表中。

在触发器中,我放置了一个 BEGIN TRANSACTION triggerTransaction2。我命名了它,所以我可以回滚那个特定的事务。另请注意,插入语句已启动事务。但问题是我无法回滚嵌套的 (triggerTransaction2) 事务。只有整个事务(使用没有名称的 ROLLBACK)。

如果我查看XACT_STATE () 那么它是-1。这应该意味着“它只能请求事务的完全回滚。”。

我试图简化代码,并希望它仍然有意义。我也遵循了这个例子- 这对我有用,但也不是嵌套事务。

所以我在想,将 RAISERROR 与所选值一起使用不是很好。

触发器的伪代码:

CREATE TRIGGER [dbo].[Trigger_SomeTableStatus]
ON [dbo].[SomeTable]
FOR INSERT
AS

BEGIN
    SET NoCount ON
    -- declaring som variables;         DECLARE @isActive BIT;

    BEGIN TRY

        BEGIN TRANSACTION triggerTransaction2       
        -- SAVE TRANSACTION triggerTransaction2

        -- some logic ... 
        RAISERROR(' Test error message; *failed* ', 16, 1);

        COMMIT TRANSACTION triggerTransaction2

    END TRY
    BEGIN CATCH

        -- HERE  XACT_STATE() = -1)
        ROLLBACK TRANSACTION   triggerTransaction2      -- Cannot rollback with the name 

        BEGIN TRY
            BEGIN TRANSACTION triggerTransactionLog
            -- Do the logging..
            COMMIT TRANSACTION triggerTransactionLog
        END TRY
        BEGIN CATCH
        --      -- Logging of error failed...
        END CATCH
    END CATCH
END
4

1 回答 1

0

是的,这是因为当您进行 ROLLBACK 时,完整的交易会被取消。您必须在内存中创建一个表,例如:

DECLARE @Log AS TABLE 
(
    Description NVARCHAR(100)
);

然后,在@Log 表中插入您要登录的内容。最后,在 END TRY 和 END CATCH 之前(或在 SP 结束之前)将 @Log 表中的内容插入数据库中的 Log 表中

于 2019-01-03T15:32:17.413 回答