プログラマ38の日記

主にプログラムメモです。

【Salesforce】データ移行時のトリガスキップについて考えたこと

データ移行では、既存のデータを確実に移行したいのでトリガを動かしたくない時があると思います。その制御の方法について考えてみました。

No.3のユーザのカスタム項目の制御がいいかなと思っていますが、要件として、トリガをスキップしたい時スキップしたくない時がある場合は、No.4のカスタムオブジェクトの項目の制御になると思います。

 

No 制御で使う設定 スキップの制御 メリット デメリット
1 カスタム表示ラベル 制御用にカスタム表示ラベルを用意し、その値がtrueの時はトリガの先頭でreturnする。 実装がシンプル。

beforeトリガ/afterトリガも確実にスキップできる。
カスタム表示ラベルをtrueにすると他のユーザもトリガスキップされてしまうため、運用開始後に、再度移行が難しい。
2 ユーザのプロファイル 移行用のプロファイルを用意し、そのプロファイルの時は、トリガの先頭でreturnする。 実装がカスタム表示ラベルの次にシンプル。

beforeトリガ/afterトリガも確実にスキップできる。

移行のためだけにプロファイルを用意するのは意外と手間。

3 ユーザのカスタム項目 ユーザオブジェクトに、制御用のカスタム項目を用意し、その値がtrueの時はトリガの先頭でreturnする。

実装がカスタム表示ラベルの次にシンプル。

 

beforeトリガ/afterトリガも確実にスキップできる。

あまりないかなと思います。
4 カスタムオブジェクトの項目 データを登録したいカスタムオブジェクトに制御用のカスタム項目を用意し、その値がtrueの時はトリガの先頭でreturnする。 移行時だけでなく、どのユーザでもトリガをスキップしたいタイミングでスキップが可能。

beforeトリガは確実にスキップできる。
実装が込み入っている。
また、複数行の更新時に、トリガをスキップしたい行とスキップしたくない行が混在すると制御がほぼ不可能なので、まとめて更新する際は、トリガのスキップの指定を混在できない。

仕様によってはafterトリガのスキップが困難な場合がある。

 

実装例は次のようになります。

No.1  カスタム表示ラベルの制御

trigger SampleiTrigger on Sample__c (after delete, after insert, after undelete, after update,
        before delete, before insert, before update) {


  if(System.Label.IKOFLAG == 'TRUE'){
    return;
  }
//処理

 No.2 ユーザのプロファイルの制御

trigger SampleiTrigger on Sample__c (after delete, after insert, after undelete, after update,
        before delete, before insert, before update) {
  
  User u = [select Profile.Name from User where Id =:Userinfo.getUserId()];
  
  if(u.Profile.Name == '移行'){
    return;
  }

 No.3 ユーザのカスタム項目の制御

trigger SampleiTrigger on Sample__c (after delete, after insert, after undelete, after update,
        before delete, before insert, before update) {
  
  User u = [select TriggerSkipFlag__c from User where Id =:Userinfo.getUserId()];
  
  if(u.TriggerSkipFlag__c){
    return;
  }

 

 No.4 カスタムオブジェクトの項目の制御

trigger SampleiTrigger on Sample__c (after delete, after insert, after undelete, after update,
        before delete, before insert, before update) {
  
  Boolean triggerskip = false;

   for(   Sample__c s : Trigger.New ){
    if( s.TriggerSkipFlag__c ){
      triggerskip = true;
//trueのままにしておくと、次に更新した際に無条件にトリガがスキップされる
//のを防ぐためフラグは常にfalseに戻す
      s.TriggerSkipFlag__c = false;
    }
  }

  if ( triggerskip ){
    //afterトリガ用にstatic変数にトリガスキップのフラグをたてる。
    Cls_StaticValue.triggerskip = true; 
  }

  if( triggerskip || Cls_StaticValue.triggerskip ){
    return;
  }

 

No.4の実装にすると、1つのトランザクション内で、何度も同じオブジェクトを登録・更新する場合、どこかでトリガをスキップすると、トリガはスキップされ続けてしまいます。Trigger.InsertやTrigger.Afterなどを使えばある程度まで細かく制御はできると思います。