2011-09-07 59 views
3

我有一个SQL Server 2008 R2存储过程,它在TRANSACTION中运行一些INSERT和UPDATE。在每个陈述之后,我需要记录刚才发生的事情,然后再进行下一步。如何记录事务中的事件

这里是我的代码:

BEGIN TRY 

    BEGIN TRANSACTION 

     INSERT INTO... -- 1st statement 
     INSERT INTO MyEventLog (EventDescription) VALUES ('Did Step 1') -- log 

     UPDATE... -- 2nd statement 
     INSERT INTO MyEventLog (EventDescription) VALUES ('Did Step 2') -- log 

    COMMIT TRANSACTION 

END TRY 

BEGIN CATCH 
    IF (@@TRANCOUNT<>0) ROLLBACK TRANSACTION 
    EXEC LogError 'I got an error' 
END CATCH 

问题是:如果有错误,事务回滚所有语句 - 包括我所需要的记录。如果发生错误,如何回滚事务但保留日志记录

回答

1

我要问你为什么会想记录,在技术上并没有发生的事件,因为事务会被回滚数据库将处于交易前的状态。但是后来我想到,你可能只是想记录它,以便知道它在哪里失败,所以你可以解决潜在的问题,这是一个聪明的事情。

如果确实如此,最好的办法是按照您当前的方式回滚整个事务,并使用LogError SP将错误消息记录到另一个表中。这是我用:

CREATE PROCEDURE [dbo].[Error_Handler] 
@returnMessage bit = 'False' 
WITH EXEC AS CALLER 
AS 
BEGIN 

    DECLARE @number int, 
    @severity int, 
    @state int, 
    @procedure varchar(100), 
    @line int, 
    @message varchar(4000) 

    INSERT INTO Errors (Number,Severity,State,[Procedure],Line,[Message]) 
    VALUES (
    ERROR_NUMBER(), 
    ERROR_SEVERITY(), 
    ERROR_STATE(), 
    isnull(ERROR_PROCEDURE(),'Ad-Hoc Query'), 
    isnull(ERROR_LINE(),0), 
    ERROR_MESSAGE()) 

    IF(@returnMessage = 'True') 
    BEGIN 
    select * 
    from Errors 
    where ErrorID = scope_identity() 
    END 
END 

错误消息应该让你知道在什么表出了错,那应该有足够的信息来解决问题。

0

如何将日志报表放入单独的事务?

我把它倒在CATCH块:

BEGIN CATCH    
    IF (@@TRANCOUNT<>0) 
    ROLLBACK TRANSACTION   
    EXEC LogError 'I got an error' 
    BEGIN TRANSACTION 
    INSERT INTO MyEventLog (EventDescription) VALUES ('Error Updating') -- log 
    END TRANSACTION 
END CATCH 
+0

如何?请更新我的代码示例以显示您的意思。订单需要保持不变,非登录语句需要在TRANS中。 –

1

参见Logging messages during a transaction。有点令人费解:

但它确实允许您在事务处理期间记录消息,即使事务回滚,消息也将保留。记录顺序被保留。

当一个过程失败但事务可以继续时(例如,当处理一个批次和一个项目失败时,您希望继续完成批处理的其余部分),您还需要使事务和存储过程发挥良好效果。见Exception handling and nested transactions

0

事实证明,表变量不遵守事务语义。所以,你可以插入一个表变量,然后在catch块之后从你的表变量插入你的日志表中。