2010-05-11 65 views
4

我正在編寫SQL Server 2005觸發器。我想在觸發器執行期間做一些日誌記錄,在我的日誌表中使用INSERT語句。當執行過程中出現錯誤時,我想提出錯誤並取消導致觸發器執行的操作,但不會丟失日誌記錄。達到此目的的最佳方法是什麼?在SQL Server中登錄表觸發器

現在我的觸發器會記錄除了情況發生錯誤時的所有事情 - 因爲ROLLBACK。需要RAISERROR語句來通知調用程序有關錯誤。

現在,我的錯誤處理代碼如下所示:

if (@err = 1) 
begin 
    INSERT INTO dbo.log(date, entry) SELECT getdate(), 'ERROR: ' + out from #output 
    RAISERROR (@msg, 16, 1) 
    rollback transaction 
    return 
end 

回答

7

另一種可能的選擇是使用表變量捕獲您想要存儲在永久日誌表中的信息。如果給出ROLLBACK TRANSACTION命令,表格變量不會回滾。示例代碼如下...



--- Declare table variable 
DECLARE @ErrorTable TABLE 
    ([DATE] smalldatetime, 
    [ENTRY] varchar(64)) 

DECLARE @nErrorVar int 

--- Open Transaction 
BEGIN TRANSACTION 

--- Pretend to cause an error and catch the error code 
SET @nErrorVar = 1 --- @@ERROR 

IF (@nErrorVar = 1) 
    BEGIN 

    --- Insert error info table variable 
    INSERT INTO @ErrorTable 
     ([Date], [Entry]) 
    SELECT 
     getdate(), 'Error Message Goes Here' 

    RAISERROR('Error Message Goes Here', 16, 1) 

    ROLLBACK TRANSACTION 

    --- Change this to actually insert into your permanent log table 
    SELECT * 
    FROM @ErrorTable 

    END 

IF @@TRANCOUNT 0 
    PRINT 'Open Transactions Exist' 
ELSE 
    PRINT 'No Open Transactions' 
+0

這就是我們做的 – HLGEM 2010-05-11 19:58:45

+0

的確。我錯過了這個選項,但是投了票。 – AlexS 2010-05-11 20:04:02

2

這裏的問題是,日誌記錄是修改數據的交易的一部分。嵌套事務在這裏沒有幫助。您需要的是將日誌記錄操作放入單獨的上下文(連接)中,即使其獨立於當前事務。

兩個選項來我的腦海:

  • 使用Service Broker的記錄 - 把數據記錄到隊列中,接收並保存「在管道的另一端」的數據(即在另一個進程/連接/交易)
  • 使用OPENQUERY - 你需要註冊你自己的服務器作爲一個「鏈接服務器」,並執行查詢「遠程」(我知道,這看起來有點怪怪的,但一個選項無論如何...)

HTH

2

不知道如果我想得簡單,但爲什麼不只是改變錯誤處理程序的順序插入回滾後?

if (@err = 1) 
begin 
    RAISERROR (@msg, 16, 1) 
    rollback transaction 
    INSERT INTO dbo.log(date, entry) SELECT getdate(), 'ERROR: ' + out from #output 
    return 
end 
+0

投票+1爲簡單XD – 2011-12-15 18:01:13