3

AFTER INSERT TRIGGERを作成しました

トリガーの実行中にエラーが発生した場合。トリガーされたテーブルの挿入操作には影響しません。

一言で言えば、トリガーでエラーが発生した場合は無視する必要があります。

私が使用したように

BEGIN TRY

END TRY
BEGIN CATCH

END CATCH

ただし、次のエラーメッセージが表示され、トリガーされたテーブルでの挿入操作がロールバックされます

トリガーの実行中にエラーが発生しました。バッチが中止され、ユーザー トランザクションがあればロールバックされました。

4

3 に答える 3

5

興味深い問題です。デフォルトでは、トリガーは、失敗した場合、それを起動したコマンドをロールバックするように設計されています。したがって、トリガーが実行されているときはいつでも、明示的な BEGIN TRANSACTION があったかどうかに関係なく、アクティブなトランザクションがあります。また、トリガー内の BEGIN/TRY も機能しません。失敗する可能性のあるコードをトリガーに記述しないことをお勧めします - 実行ステートメントも失敗させたい場合を除きます。

この状況では、この動作を抑制するために、いくつかの回避策があります。

オプション A (醜い方法):

トランザクションはトリガーの開始時にアクティブであるため、COMMITそのままトリガー コマンドを続行できます。

CREATE TRIGGER tgTest1 ON Test1 AFTER INSERT
AS
BEGIN
COMMIT;
... do whatever trigger does
END;

トリガー コードにエラーがある場合でもエラー メッセージが生成されますが、Test1テーブル内のデータは安全に挿入されることに注意してください。

オプションB(これも醜い):

コードをトリガーからストアド プロシージャに移動できます。次に、実装する Wrapper SP からそのストアド プロシージャをBEGIN/TRY呼び出し、最後にトリガーから Wrapper SP を呼び出します。これは、ロジック(現在SPにある)で必要な場合にテーブルからデータを移動するのが少し難しいかもしれませんINSERTED-おそらくいくつかの一時テーブルを使用しています。

SQLFiddle デモ

于 2013-07-18T13:23:07.653 に答える
2

あなたはできません、そしてそれを解決しようとする試みはすべて蛇油です. TRY/CATCH や @@ERROR のチェックを行っても、根本的な問題を回避することはできません。

トリガーの密結合を使用する場合は、結合によって引き起こされる可用性の低下を受け入れる必要があります。

可用性を維持したい (つまり、INSERT を成功させたい) 場合は、結合を断念する (トリガーを削除する) 必要があります。トリガーで実行する予定だったすべての処理は、INSERT がコミットされた後に開始される別のトランザクションで実行する必要があります。新しく挿入された行をテーブルにポーリングする SQL エージェント ジョブ、Service Broker 起動プロシージャ、さらにはアプリケーション層のステップはすべて、請求書に適合します。

于 2013-07-18T13:29:35.273 に答える