為什麼 TRY CATCH 不會抑制觸發器中的異常
我在一個表(源)上有一個觸發器,數據應該被複製到另一個數據庫中的另一個(目標)。我正在嘗試為數據實現自定義同步過程:我希望目標數據庫(表)將是最新的源數據庫(表)。我有 300 張表要同步。其中一些具有不同的物理資料結構。由於不同的數據架構和其他限制(實施時間、環境問題…),我無法使用 Sql Server 的標準方法(複製、DTS …)。我的目標是:此觸發器不應影響源表中記錄的 INSERT、DELETE、UPDATE。我試過這樣的解決方案:
CREATE TRIGGER dbo.MyTrigger ... AFTER INSERT .... BEGIN TRY --RAISERROR('Test error', 16, 2) END TRY BEGIN CATCH -- nothing END CATCH
我已插入
RAISEERROR
以模擬錯誤。我希望try/catch
抑制該錯誤並成功插入(刪除或更新)記錄。別。這是行不通的。我收到錯誤:觸發器執行期間引發錯誤。批處理已中止,並且使用者事務(如果有)已回滾。
是否有可能以這種方式實現我的解決方案。如何擷取並保持(抑制)觸發器中的任何錯誤?
try/catch
如果它不起作用,在觸發器中使用什麼意義?
幾乎所有異常都注定了該事務,必須回滾。
來自MSDN 上的“在 Transact-SQL 中使用 TRY…CATCH”
在 TRY…CATCH 構造中,事務可以進入事務保持打開但不能送出的狀態。事務不能執行任何會生成事務日誌寫入的操作,例如修改數據或嘗試回滾到保存點。但是,在這種狀態下,事務獲取的鎖保持不變,連接也保持打開狀態。在發出 ROLLBACK 語句或批處理結束並且數據庫引擎自動回滾事務之前,事務的效果不會逆轉。如果在事務進入不可送出狀態時沒有發送錯誤消息,則當批處理完成時,將向客戶端應用程序發送一條錯誤消息,指示檢測到不可送出事務並回滾。
當發生錯誤時,交易進入 TRY 塊內的不可送出狀態,否則該錯誤將結束交易。例如,來自數據定義語言 (DDL) 語句(例如 CREATE TABLE)的大多數錯誤,或者當 SET XACT_ABORT 設置為 ON 時發生的大多數錯誤,會在 TRY 塊外終止事務,但在 TRY 塊內使事務不可送出.
這個例子說明了原因。XACT_STATE() 不註冊隱含事務(例如,沒有顯式 BEGIN TRAN)
CREATE TABLE TrgTest (gbn int NOT NULL); GO CREATE TRIGGER TRG_TrgTEst_I ON TrgTest AFTER INSERT AS BEGIN TRY SELECT '1', @@TRANCOUNT, XACT_STATE(); RAISERROR('Test error', 16, 2); END TRY BEGIN CATCH SELECT '2', @@TRANCOUNT, XACT_STATE(); END CATCH GO BEGIN TRANSACTION INSERT TrgTest VALUES (1) SELECT 'will not run' GO SELECT 'next batch' GO BEGIN TRY BEGIN TRANSACTION SELECT 'a', @@TRANCOUNT, XACT_STATE(); INSERT TrgTest VALUES (1) SELECT 'b', @@TRANCOUNT, XACT_STATE(); END TRY BEGIN CATCH SELECT ERROR_MESSAGE() SELECT 'c', @@TRANCOUNT, XACT_STATE(); END CATCH GO DROP TABLE TrgTest;