Page History
トリガー - 典型例
以下は、トリガー・ファンクションの使用方法を示す典型例です。
...
これは、トリガーによって複雑な規則を「カプセル化」し、「オブジェクト」(テーブル)に直接関連付ける方法を明確に示している典型例です。
業務上の問題
ACMEエンジニアリングでは、給与支払いシステムを運用しています。
...
WEEKPAYは、一連の複雑な規則を用いて算出されます。以前の新しい従業員に対するWEEKPAYの計算は比較的単純ですが、従業員のSALARYが変更された場合は、新しいSALARY額とSALARY額が関与する複雑な計算になります。
新しい従業員に対するWEEKPAYの計算は比較的単純ですが、従業員のSALARYが変更された場合は、新しいSALARY額と以前のSALARY額が関与する複雑な計算になります。
トリガー・ファンクション
トリガーを定義するための最初の手順では、すべてのWEEKPAY規則を1つにカプセル化するトリガー・ファンクションを定義します。すべてのWEEKPAY規則を1つにカプセル化するトリガー・ファンクションを定義します。
これが、優れたトリガー設計の基礎となります。
そのために、以下のファンクションがコーディングされているとします。
| Code Block |
|---|
FUNCTION OPTIONSFUNCTION OPTIONS(*DIRECT DIRECT *NOMESSAGES NOMESSAGES *MLOPTIMIZE) RCV RCV_LIST(#TRIG_LIST) TRIGGER TRIGGER(*FILE EMPLFILE 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 / 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 TYPE(*WORKING) ENTRYS ENTRYS(2) / Now examine exactly what event has occurred / DEFINE FIELD(#OLDSALARY) REFFLD / Now examine exactly what event has occurred / DEFINE FIELD(#OLDSALARY) REFFLD(#SALARY) CASE OF CASE OF_FIELD(#TRIG_OPER) / A new employee is being created A new employee is being created / WHEN VALUE WHEN VALUE_IS('= BEFINS BEFINS') GET_ENTRY NUMBER GET_ENTRY NUMBER(1) FROM FROM_LIST(#TRIG_LIST) << calculate correct value into field WEEKPAY >> UPD_ENTRY IN << calculate correct value into field WEEKPAY >> UPD_ENTRY IN_LIST(#TRIG_LIST) / An existing salary has been changed An existing salary has been changed / WHEN VALUE WHEN VALUE_IS('= BEFUPD BEFUPD') GET_ENTRY NUMBER GET_ENTRY NUMBER(2) FROM FROM_LIST(#TRIG_LIST) #OLDSALARY #OLDSALARY := #SALARY GET_ENTRY NUMBER GET_ENTRY NUMBER(1) FROM FROM_LIST(#TRIG_LIST) << calculate correct value into WEEKPAY >> << using OLDSALARY in the calculations >> UPD_ENTRY IN << calculate correct value into WEEKPAY >> << using OLDSALARY in the calculations >> UPD_ENTRY IN_LIST(#TRIG_LIST) OTHERWISE ABORT MSGTXT('WEEKPAY trigger function invalidly invoked ABORT MSGTXT('WEEKPAY trigger function invalidly invoked') ENDCASE #TRIG_RETC := OK RETURN |
トリガー・ファンクションのアクティブ化
これで、トリガー・ファンクションが定義されました。次に、このトリガー・ファンクションをアクティブ化する必要があります。これを行うには、テーブルEMPLの定義にアクセスし、2つのトリガー呼び出しイベントをこの定義に関連付けます。
...
2つ目は、「UPDATE前」として指定し、以下のような条件を関連付けます。
| Code Block |
|---|
SALARY NEP SALARY すなわち、 SALARYが以前のSALARYと等しくないSALARY NEP SALARY すなわち、 SALARYが以前のSALARYと等しくない |
これにより、トリガーは、従業員のSALARYが変更された場合のみ、「UPDATE前」にアクティブ化されます。
...
SALARYが変更されるか、従業員が勤務するCOMPANYが変更されたときに、WEEKPAYを再計算する必要がある場合は、代わりに以下のような呼び出しイベントを定義します。
| Code Block |
|---|
SALARY NEP SALARY
OR COMPANY NEP COMPANY
すなわち SALARYが以前のSALARYと等しくない
または COMPANYが以前のCOMPANYと等しくない |
SALARY NEP SALARY
OR COMPANY NEP COMPANY
すなわち、
SALARYが以前のSALARYと等しくない
または COMPANYが以前のCOMPANYと等しくない |
WEEKPAYを必ず再計算する場合は、2つの呼び出しイベントを別々に定義する必要はありません。単純に1つのイベントWEEKPAYを必ず再計算する場合は、2つの呼び出しイベントを別々に定義する必要はありません。単純に1つのイベント(条件なし)を定義し、「INSERT前」および「UPDATE前」にトリガーを呼び出すよう指定します。
この場合、当然ながら、従業員の挿入または更新を行うたびに、トリガー・ファンクションが呼び出されることになります。
この例についての注意点
この例には、優れたトリガーの設計と使用のために重要になる要素がいくつか示されています。
- 「カプセル化」原理。WEEKPAYを計算するための「具体的な処理」が、1つのファンクションに「カプセル化」されています。そのため、必要な変更を1箇所で行えます。1つのファンクションに「カプセル化」されています。そのため、必要な変更を1箇所で行えます。
- 必要が生じてからの設計。システム設計の初期段階では、WEEKPAYの具体的な処理の存在を定義する必要はありません。また、具体的な処理を想定して全体の設計を進める必要もありません。 逆に言うと、設計工程のどの時点でも、必要になった時点で具体的な中身を決めてよい、ということです。例えば、従業員を作成したり更新したりするアプリケーションが決まっていない段階で、WEEKPAYの具体的な処理を定義する必要はありません。まず、作成/更新アプリケーションを定義し、検査することができます。WEEKPAYの具体的な処理を作成、定義した時点から、既存のアプリケーションの処理に反映されるようになります。
- 再利用可能性。WEEKPAYを計算する具体的な処理は、従業員の詳細を作成または変更するアプリケーションによって自動的かつ暗黙的に再利用されます。トリガーは、通常のNPTデバイスから「従業員データ保守」ファンクションを通して、またはPCアプリケーションからLANSA Open機能を通してアクティブ化される可能性があります。
- 情報隠蔽。WEEKPAYというロジックが存在し、使用されているという事実は、「従業員データ保守」ファンクションを作成するRDMLビルダーからは見えません。また、RDMLビルダーにとっては意味がないものでしょう。
- 「具体的な処理」と「イベント」の分離。トリガー・ファンクションでは、「イベント」が発生したときに何を行うか(すなわち「具体的な処理」)を定義します。 ただし、イベントの発生を検出する必要はありません。
ただし、イベントの発生を検出する必要はありません。
例えば、前に定義したファンクションでは、「週給の計算」という「具体的な処理」を定義しています。
業務上の規則では、新しい従業員が採用された場合、既存の従業員の給与が変更された場合、または既存の従業員が転職した場合に、週給を(再)計算しなければならないことを規定しています。
実際の「イベント」は、LANSAデータ・ディクショナリで定義します。