トリガー - 典型例

以下は、トリガー・ファンクションの使用方法を示す典型例です。

この例では、複雑な業務上の規則をトリガーに「カプセル化」します。

次に、トリガーを関連データベース・テーブルに関連付け、指定のイベントが発生した場合に必ず業務上の規則で規定された処理が実行されるようにします。

これは、トリガーによって複雑な規則を「カプセル化」し、「オブジェクト」(テーブル)に直接関連付ける方法を明確に示している典型例です。

業務上の問題

ACMEエンジニアリングでは、給与支払いシステムを運用しています。

従業員マスター・テーブル(EMPL)には、"SALARY"および"WEEKPAY"という2つの列が含まれています。

SALARYは、会社が従業員に支払うよう契約している年棒です。

WEEKPAYは、従業員に対して毎週支払われる金額です。

WEEKPAYは、一連の複雑な規則を用いて算出されます。

新しい従業員に対するWEEKPAYの計算は比較的単純ですが、従業員のSALARYが変更された場合は、新しいSALARY額と以前のSALARY額が関与する複雑な計算になります。

トリガー・ファンクション

トリガーを定義するための最初の手順では、すべてのWEEKPAY規則を1つにカプセル化するトリガー・ファンクションを定義します。

これが、優れたトリガー設計の基礎となります。

そのために、以下のファンクションがコーディングされているとします。

FUNCTION OPTIONS(*DIRECT *NOMESSAGES *MLOPTIMIZE)
         RCV_LIST(#TRIG_LIST) TRIGGER(*FILE EMPL)
  
/ Define the standard trigger list which will contain the /
/ before and after images of the EMPL table record. These  /
/ fields are automatically added to the list definition   /
/ by the RDML compiler.                                   /
  
DEF_LIST NAME(#TRIG_LIST) TYPE(*WORKING) ENTRYS(2)
  
/ Now examine exactly what event has occurred              /
  
DEFINE FIELD(#OLDSALARY) REFFLD(#SALARY)
  
CASE  OF_FIELD(#TRIG_OPER)
  
/ A new employee is being created /
  
WHEN  VALUE_IS('= BEFINS')
      GET_ENTRY NUMBER(1) FROM_LIST(#TRIG_LIST)
      << calculate correct value into field WEEKPAY >>
      UPD_ENTRY IN_LIST(#TRIG_LIST)
  
/ An existing salary has been changed /
  
WHEN  VALUE_IS('= BEFUPD')
      GET_ENTRY NUMBER(2) FROM_LIST(#TRIG_LIST)
      #OLDSALARY := #SALARY
  
      GET_ENTRY NUMBER(1) FROM_LIST(#TRIG_LIST)
      << calculate correct value into WEEKPAY >>
      << using OLDSALARY in the calculations  >>
      UPD_ENTRY IN_LIST(#TRIG_LIST)
  
OTHERWISE
      ABORT MSGTXT('WEEKPAY trigger function invalidly invoked')
  
ENDCASE
  
#TRIG_RETC := OK
RETURN

トリガー・ファンクションのアクティブ化

これで、トリガー・ファンクションが定義されました。次に、このトリガー・ファンクションをアクティブ化する必要があります。これを行うには、テーブルEMPLの定義にアクセスし、2つのトリガー呼び出しイベントをこの定義に関連付けます。

1つ目は、「INSERT前」として指定し、条件を関連付けません。すなわち、このトリガー・ファンクションは、新しい従業員を作成しようとするたびに呼び出されます。

2つ目は、「UPDATE前」として指定し、以下のような条件を関連付けます。

SALARY    NEP   SALARY

すなわち、
SALARYが以前のSALARYと等しくない

これにより、トリガーは、従業員のSALARYが変更された場合のみ、「UPDATE前」にアクティブ化されます。

「UPDATE前」イベントをこのように定義すると、従業員のSALARYが変更されない(ほとんどがこの状況に該当)限りトリガーはアクティブ化されないため、非常に効率的です。

SALARYが変更されるか、従業員が勤務するCOMPANYが変更されたときに、WEEKPAYを再計算する必要がある場合は、代わりに以下のような呼び出しイベントを定義します。

    SALARY    NEP   SALARY
OR  COMPANY   NEP   COMPANY

すなわち、
       SALARYが以前のSALARYと等しくない
または   COMPANYが以前のCOMPANYと等しくない

 WEEKPAYを必ず再計算する場合は、2つの呼び出しイベントを別々に定義する必要はありません。単純に1つのイベント(条件なし)を定義し、「INSERT前」および「UPDATE前」にトリガーを呼び出すよう指定します。

この場合、当然ながら、従業員の挿入または更新を行うたびに、トリガー・ファンクションが呼び出されることになります。

この例についての注意点

この例には、優れたトリガーの設計と使用のために重要になる要素がいくつか示されています。