2011-09-07 58 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塊之後從你的表變量插入你的日誌表中。