Tsql 如何使用SQL;对于事务中执行的存储过程,是否尝试将错误信息捕获到错误日志表?

Tsql 如何使用SQL;对于事务中执行的存储过程,是否尝试将错误信息捕获到错误日志表?,tsql,error-handling,translation,try-catch,Tsql,Error Handling,Translation,Try Catch,在我的存储过程中,我使用Try-Catch,并在Catch块中调用一个错误处理过程,该过程将在ErrorLog表中记录错误详细信息,然后重新显示错误 在我的C#代码中,我使用以下命令执行存储过程: 使用(TransactionScope范围=新TransactionScope()){ //执行存储过程 scope.Complete(); } 我遇到的问题是,如果事务中止(从未调用scope.Complete),我的错误处理存储过程会重新显示sql错误,但无法将错误记录到ErrorLog表中,因

在我的存储过程中,我使用Try-Catch,并在Catch块中调用一个错误处理过程,该过程将在ErrorLog表中记录错误详细信息,然后重新显示错误

在我的C#代码中,我使用以下命令执行存储过程:

使用(TransactionScope范围=新TransactionScope()){
//执行存储过程
scope.Complete();
}
我遇到的问题是,如果事务中止(从未调用scope.Complete),我的错误处理存储过程会重新显示sql错误,但无法将错误记录到ErrorLog表中,因为它位于事务上下文中;这有什么办法吗!?我已经知道,当事务处于不可提交状态时,无法插入数据,因此如何退出事务并仍然记录错误

TSQL代码:

BEGIN PROCEDURE [dbo].[usp_UpsertSomething]
    @SomethingID BIGINT
AS
BEGIN
    SET NOCOUNT ON;

    BEGIN TRY
        -- do something
    END TRY
    BEGIN CATCH
        EXEC dbo.cp_RethrowError
        RETURN -1
    END CATCH;
END

CREATE PROCEDURE [dbo].[usp_RethrowError]
    @ErrorLogID [INT] = 0 OUTPUT -- Contains the ErrorLogID of the row inserted
                                 -- by cp_RethrowError in the ErrorLog table.
AS
BEGIN
    -- Return if there is no error information to retrieve.
    IF ERROR_NUMBER() IS NULL
        RETURN;

    DECLARE 
        @ErrorMessage           VARCHAR(4000),
        @FormattedErrorMessage  VARCHAR(4000),
        @ErrorNumber            INT,
        @ErrorSeverity          INT,
        @ErrorState             INT,
        @ErrorLine              INT,
        @ErrorProcedure         VARCHAR(200);

    -- Assign variables to error-handling functions that 
    -- capture information for RAISERROR.
    SELECT 
        @ErrorNumber = ERROR_NUMBER(),
        @ErrorMessage = ERROR_MESSAGE(),
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE(),
        @ErrorLine = ERROR_LINE(),
        @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');

    -- Build the message string that will contain original
    -- error information.
    SELECT @FormattedErrorMessage = 
        'ErrorLogID %d, Error %d, Level %d, State %d, Procedure %s, ' + 
            'Line %d, Message: '+ @ErrorMessage;

    BEGIN TRY
        -- Data insertion/modification is not allowed when 
        -- a transaction is in an uncommittable state.
        IF XACT_STATE() = -1 BEGIN
            SET @ErrorLogID = 0;
        END
        ELSE BEGIN
            INSERT [dbo].[ErrorLog] 
            (
                ErrorNumber, 
                ErrorSeverity, 
                ErrorState, 
                ErrorProcedure, 
                ErrorLine, 
                ErrorMessage
            ) 
            VALUES 
            (
                @ErrorNumber,
                @ErrorSeverity,
                @ErrorState,
                @ErrorProcedure,
                @ErrorLine,
                @ErrorMessage
            );

            -- Pass back the ErrorLogID of the row inserted
            SELECT @ErrorLogID = @@IDENTITY;
        END
    END TRY
    BEGIN CATCH
        PRINT 'An error occurred in stored procedure cp_RethrowError.';
    END CATCH

    -- Raise an error: msg_str parameter of RAISERROR will contain
    -- the original error information.
    RAISERROR 
    (
        @FormattedErrorMessage, 
        @ErrorSeverity, 
        1,
        @ErrorLogID,     -- parameter: ErrorLogID in ErrorLog table.
        @ErrorNumber,    -- parameter: original error number.
        @ErrorSeverity,  -- parameter: original error severity.
        @ErrorState,     -- parameter: original error state.
        @ErrorProcedure, -- parameter: original error procedure name.
        @ErrorLine       -- parameter: original error line number.
    );
END

因为事务是一个全有或全无的事务,所以完成我想要完成的事情的唯一方法是在调用我的错误处理调用之前,在Catch块内部调用ROLLBACK事务

我的错误日志以我希望记录的错误结束,但在我的.Net catch块中,我以SQL的抱怨结束:“执行后的事务计数表示缺少提交或回滚事务语句。上一个计数=1,当前计数=0。”


我可以接受

您还可以首先将错误日志条目放入一个表变量中(该变量应具有与实际日志表相同的结构)。回滚不清除表变量。最后,只需将表变量的内容插入到实际的日志表中

我没有试过,但可能有用。
SQL Server中仍然缺少自治事务之类的功能(Oracle已经有了它)。在自治事务中执行的任何操作都独立于主事务。这正是错误日志记录所需的:特别是当事务回滚时,您仍然希望知道发生了什么。

这是一个排序问题。检查错误处理程序中的事务计数。 步骤: 1.首先将原始错误信息放入@variables或@table中。 2.检查事务计数,如果大于0,则回滚。 3.插入刚刚在步骤1中收集的错误信息。 完成了