2012-04-02 89 views
4

我有一個存儲過程,在插入/更新/刪除的觸發器中調用。忽略觸發器中的錯誤

問題是這個SP裏面有一個不重要的代碼塊。 因此我想忽略這個代碼塊產生的任何錯誤。

我在TRY CATCH塊中插入了這個代碼塊。但讓我吃驚,我得到了以下錯誤:

當前事務無法提交,無法支持寫入日誌文件的操作。回滾事務。

然後我試圖使用SAVE & ROLLBACK TRANSACTION與TRY CATCH一起,太失敗,出現以下錯誤:

當前事務不能被提交併且不能被回滾到保存點。回滾整個交易。

我的服務器版本是:微軟的SQL Server 2008(SP2) - 10.0.4279.0(X64)

樣品DDL:

IF OBJECT_ID('TestTrigger') IS NOT NULL 
    DROP TRIGGER TestTrigger 
GO 
IF OBJECT_ID('TestProcedure') IS NOT NULL 
    DROP PROCEDURE TestProcedure 
GO 
IF OBJECT_ID('TestTable') IS NOT NULL 
    DROP TABLE TestTable 
GO 

CREATE TABLE TestTable (Data VARCHAR(20)) 
GO 

CREATE PROC TestProcedure  
AS  
BEGIN 

    SAVE TRANSACTION Fallback 
    BEGIN TRY 
     DECLARE @a INT = 1/0 
    END TRY 
    BEGIN CATCH 
     ROLLBACK TRANSACTION Fallback 
    END CATCH 
END 
GO 

CREATE TRIGGER TestTrigger 
ON TestTable 
FOR INSERT, UPDATE, DELETE 
AS 
BEGIN 
    EXEC TestProcedure 
END 
GO 

代碼複製錯誤:

BEGIN TRANSACTION 
INSERT INTO TestTable VALUES('data') 
IF @@ERROR > 0 
    ROLLBACK TRANSACTION 
ELSE 
    COMMIT TRANSACTION 
GO 

回答

1

我建議重新設計這個,這樣你不會中毒原始交易 - 可能讓交易發送服務經紀人信息(或者只是將相關數據插入某種形式的隊列表中),以便「非關鍵」部分可以在完全獨立的事務中進行。

E.g.您的觸發變爲:

CREATE TRIGGER TestTrigger 
ON TestTable 
FOR INSERT, UPDATE, DELETE 
AS 
BEGIN 
    INSERT INTO QueueTable (Col1,Col2) 
    SELECT COALESCE(i.Col1,d.Col1),COALESCE(i.Col2,d.Col2) from inserted i,deleted d 
END 
GO 

應該做一個觸發器中任何可能失敗,除非你做要強制發起觸發操作也失敗交易。

+0

感謝您的建議。我實際上有一個服務代理機制,這就是我所說的非關鍵部分。我不希望主事務在服務代理機制失敗時回滾。我只會堅持當前的實現。謝謝你的幫助。 – Adi 2012-04-03 03:48:46

+0

關於你最近的聲明你不應該這樣做......這是否意味着我們不應該有任何業務邏輯代碼直接或間接在觸發器內?如果是這樣,這不會使生活變得非常困難? – Jami 2015-06-29 11:13:08

+1

@Sahand - 這取決於 - 這是「業務邏輯」,應該(可選)導致*原始*事務失敗?如果是這樣,那麼它應該在觸發器中(或者更好地,通過諸如外鍵或檢查約束等其他DRI直接表達)。或者,如果原始操作應該總是成功,而這個「業務邏輯」是分開的,那麼我會按照我在這個答案中所說的內容去使用某種形式的隊列來解耦處理。 *讀取*排隊更改的代碼可以像您想要的那樣複雜。 – 2015-06-29 12:08:07

0

我不認爲你可以使用一個觸發器內保存點。我的意思是,你可以但我搜索了一下,我看到一些人說他們不工作。如果您替換開始事務的「保存事務」,它將進行編譯。當然,這不是必須的,因爲你有外部事務控制,內部回滾會回滾所有內容。

9

我正在經歷同樣的折磨,我剛剛解決了它! 只需在觸發器的第一個步驟中添加這一條線上,你會好起來的:

SET XACT_ABORT OFF; 

在我的情況,我處理錯誤餵養引起此批特定的表錯誤和來自SQL的錯誤變量。

默認值XACT_ABORTON,所以即使你正在處理一個try catch塊(就像我做的)內部錯誤的整個交易將不被COMMITED。將其值設置爲OFF將導致事務即使在發生錯誤時也被提交。

但是,我沒有測試它的時候沒有處理的錯誤...

欲瞭解更多信息:

+1

你確定默認值是否打開?我可以找到的所有信息都表明默認值爲off – 2013-05-14 10:25:07

+0

從文檔中,對於SQL Server 2008+,「OFF是默認設置」。 – 2017-05-25 19:46:06