Dec12th

トリガ

Top / トリガ

beforeトリガとafterトリガの違いは?
beforeトリガとafterトリガの特徴をまとめてみました。

○beforeトリガ
レコードがDBに保存される前に起動されます。
レコードがDBに保存される前のため、Trigger.newを直接変更することができます
(before insert、before updateトリガ)。

○afterトリガ
レコードがDBに保存された後に起動されます。
但し、まだコミットはされていません(重要)。

DBに保存された後のため、
・Id
・自動採番
・作成者
・作成日時
・更新者
・更新日時
などのDBで設定された項目の値にアクセスできます。

DBに保存された後のため、Trigger.newを直接変更することはできませんが、
DML操作で元レコードの更新・削除を行うことができます
(after insert、after updateトリガ)。

○実行順序
beforeトリガ、afterトリガ、必須、入力規則のチェックは、
↓の順番で実行されます。

1. beforeトリガ
2. 必須、入力規則のチェック
3. afterトリガ

○使い分け

開発時には、
・入力規則のチェックより前に実施したい場合には、beforeトリガを使う
・DBで設定された値にアクセスしたい場合には、afterトリガを使う
など、両者の特徴を生かして、使い分けると良いと思います。

最後に、特徴をまとめた表を載せておきます。

beforeトリガ afterトリガ 

起動タイミング レコードがDBに保存される前 レコードがDBに保存された後
DBで設定する項目へのアクセス 不可 可
Trigger.newの項目の値の変更 可 ※1 不可 ※2
元レコードのDML操作(更新・削除) 不可 ※1 可 ※2
実行順序 必須、入力規則のチェックの前 必須、入力規則のチェックの後

※1 before insert、before updateの場合
※2 after insert、after updateの場合

「Trigger.new」からは、変更が反映された最新のレコードの情報が取得できます。
「Trigger.old」からは、変更前のレコードの情報が取得できます。

 // Apexトリガ内で使えそうなTriggerクラスの主要な静的フィールド
 // Trigger.new: トリガ発生元となったレコード群
 // Trigger.newMap: 同じく発生元となったレコード群だが
 //                 IDとレコードのMapとして使える
 // Trigger.old: トリガ発生元となったレコード群だがレコード操作前の
 //              状態で格納されている
 // Trigger.oldMap: Mapのold版
 // Trigger.isInsert: 発生原因が新規追加の場合、真
 // Trigger.isUpdate: 発生原因が更新だった場合、真
 // Trigger.isDelete: 発生原因が削除だった場合、真
 // Trigger.isUndelete: 発生原因がゴミ箱から復帰の場合、真
 // Trigger.isBefore: 発生原因が格納直前の場合、真
 // Trigger.isAfter: 発生原因が格納直後の場合、真

┌───────┬───────────────────────┬───────────────────┬────────────────────┐
│トリガイベント│trigger.newを使用した │更新 DML 操作を使用した │削除 DML 操作を使用した │
│ │項目の変更 │元のオブジェクトの更新 │元のオブジェクトの削除 │
├───────┼───────────────────────┼───────────────────┼────────────────────┤
│ │ │該当なし元のオブジェクトが │該当なし元のオブジェクトが │
│before insert │可 │作成されていません。 │作成されていません。 │
│ │ │参照できるものがないため、 │参照できるものがないため、 │
│ │ │更新できません。 │更新できません。 │
├───────┼───────────────────────┼───────────────────┼────────────────────┤
│ │不可 │ │可能ですが、必須ではありません。 │
│after insert │trigger.new がすでに保存されているため、 │可 │挿入後すぐにオブジェクトが削除されます。│
│ │ランタイムエラーが発生します。 │ │ │
├───────┼───────────────────────┼───────────────────┼────────────────────┤
│before update │可 │不可 │不可 │
│ │ │ランタイムエラーが発生します。 │ランタイムエラーが発生します。 │
├───────┼───────────────────────┼───────────────────┼────────────────────┤
│ │ │可 │可 │
│ │不可 │不適切なコードにより │オブジェクトが削除される前に │
│after update │trigger.new がすでに保存されているため、 │無限に不適切な操作が │更新が保存されるため、 │
│ │ランタイムエラーが発生します。 │反復される可能性があります。 │オブジェクトが復元された時に │
│ │ │ │更新結果が表示されます。 │
│ │ │ガバナ制限によりエラーが検出されます。│ │
├───────┼───────────────────────┼───────────────────┼────────────────────┤
│ │ │可 │ │
│ │不可ランタイムエラーが発生します。 │オブジェクトが削除される前に │不可 │
│before delete │trigger.newは before 削除トリガで使用できませ │更新が保存されるため、 │ランタイムエラーが発生します。 │
│ │ん。 │オブジェクトが復元された時に │削除はすでに処理中です。 │
│ │ │更新結果が表示されます。 │ │
├───────┼───────────────────────┼───────────────────┼────────────────────┤
│ │不可ランタイムエラーが発生します。 │ │ │
│after delete │trigger.newは after 削除トリガで使用できません│該当なしオブジェクトはすでに │該当なしオブジェクトはすでに │
│ │。 │削除されています。 │削除されています。 │
│ │ │ │ │
├───────┼───────────────────────┼───────────────────┼────────────────────┤
│ │ │ │ │
│ │不可ランタイムエラーが発生します。 │ │可能ですが、必須ではあり │
│after undelete│trigger.oldは after 復元トリガで使用できません│可 │ません。挿入後すぐにオブ │
│ │。 │ │ジェクトが削除されます。 │
│ │ │ │ │
└───────┴───────────────────────┴───────────────────┴────────────────────┘