回滚后持久化日志到N-deep

Persisting log in N-deep after rollback

我的一个存储过程遇到问题。

我 运行 一个 main 过程,在事务中调用一个 recursiveChildren 调用自己的过程。

像这样:

EXEC main
{
    EXEC log 'START'

    BEGIN TRANSACTION
        BEGIN TRY
            EXEC recursiveChildren
            {
                IF ...
                    EXEC recursiveChildren
                    {
                        IF ...
                            EXEC recursiveChildren
                            {
                                ...
                            }
                        END IF
                        EXEC log 'step X'
                    }
                END IF
                EXEC log 'step X'
            }

            IF ...
                COMMIT;
            ELSE
                THROW error;
        END TRY
        BEGIN CATCH
            ROLLBACK;
            EXEC log 'ROLLBACK'
        END CATCH
    END TRANSACTION

    EXEC log 'STOP'
}

如您所见,我调用了一个记录程序来跟踪我正在做的事情,但是如果我需要使用我的 THROW error,我将丢失有关发生的事情的所有信息。

我读过 TSQL logging inside transaction 谈论日志和回滚,但是 table variable 不适合递归,因为它 READONLY 当用作过程的参数时。

回滚或不回滚时如何保留日志?

正如 Martin 所说,我的解决方案是在更新前将日志移至 var table。

如果有人遇到同样的问题,这里是代码:

CREATE PROCEDURE dbo.[main]
AS
BEGIN
    WHILE EXISTS(SELECT 1 FROM #tmp)
    BEGIN

        SET @last_id_log = (SELECT MAX([id]) FROM Logs);

        BEGIN TRANSACTION;
        BEGIN TRY

            SET @last_nb_error = @nb_error;

            EXEC dbo.[child] @nb_error output; -- recursive call of child

            IF( @nb_error - @last_nb_error = 0)
                COMMIT TRANSACTION;
            ELSE
                THROW 66666, 'Error while child, ROLLBACK', 1;

        END TRY
        BEGIN CATCH

            DECLARE @LogTable TABLE
                ([id] [int]
                ,[date] [datetime]
                ,[userName] [varchar](100)
                ,[error] [varchar](1000)
                );

            INSERT INTO @LogTable
            SELECT *
            FROM Logs
            WHERE [Id] > @last_id_log
            ;

            ROLLBACK TRANSACTION;

            INSERT INTO Logs
            SELECT *
            FROM @LogTable
            ;

            DELETE FROM @LogTable;
        END CATCH

    END
END