Sql-Server-2008

為什麼 TRY CATCH 不會抑制觸發器中的異常

  • April 9, 2018

我在一個表()上有一個觸發器,數據應該被複製到另一個數據庫中的另一個(目標)。我正在嘗試為數據實現自定義同步過程:我希望目標數據庫(表)將是最新的源數據庫(表)。我有 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;

引用自:https://dba.stackexchange.com/questions/8693