4D v16.3トリガ |
||
|
4D v16.3
トリガ
トリガ
トリガーはテーブルに付属するメソッドであり、テーブルのプロパティです。トリガーを呼び出す必要はありません。テーブルレコードを操作 (追加、削除、修正) するたびに4Dのデータベースエンジンが自動的に呼び出します。まず簡単なトリガーを記述し、後からより洗練されたものにすることができます。 トリガーを使用すれば、データベースのレコードに対して "不正な" 操作が行われるのを防ぐことができます。偶発的なデータの紛失や改ざんを防ぎ、テーブル上での操作を制限することのできる非常に強力なツールです。例えば請求書システムにおいては、請求書の送付先である顧客を指定せずに誰かが請求書を追加するのを防止することができます。 注: 4Dのセキュリティ機能の概要については、4D blogの4D Security guide を参照してください。 デザインモードでテーブルを作成したときには、デフォルトでテーブルにトリガーがありません。 テーブルのトリガーを使用するには、以下を実行する必要があります。
まだメソッドとして記述されていないトリガーをアクティブにする、あるいはトリガーをアクティブにしないでメソッドに記述しても、テーブルに対して実行される操作に影響を与えることはありません。 テーブルのトリガーをアクティブにするには、ストラクチャーのインスペクターウィンドウでテーブルのトリガー オプション (データベースイベント) を選択しなければなりません。 このオプションを選択すると、テーブルのレコードが修正されるたびに、トリガーが起動します。
[thetable]thefield:=[thetable]thefield このオプションを選択すると、テーブルのレコードが削除されるたびに、トリガーが起動します。
注: APPLY TO SELECTIONコマンドはトリガーを呼び出しません。 このオプションを選択すると、レコードがテーブルに追加されるたびに、トリガーが起動します。 以下の場合にトリガーが起動します。
テーブルのトリガーを作成するには、エクスプローラーを使用するか、ストラクチャーエディターのインスペクターウィンドウにある編集... ボタンをクリックするか、Alt (Windowsの場合) または Option (Mac OSの場合) キーを押して、ストラクチャーエディターのテーブルタイトルをダブルクリックしてください。詳細については、4D Design Referenceを参照してください。 トリガーは、前述の3つのデータベースイベントのいずれかに対して起動することができます。トリガー内でTrigger event関数を呼び出すことによって、どのイベントが発生しているかを検出します。この関数はデータベースイベントを示す数値を返します。 一般的には、Trigger eventから返される結果に関して、 Case of ストラクチャーを用いて、トリガーを記述します。_o_LAST SUBRECORDテーマの定数を使用できます。 // トリガー用の[anyTable] テーブル トリガーには、2つの目的があります。
[Documents] テーブルにレコードが保存 (追加または修正) されるたびに、作成時を示すタイムスタンプと最新の修正時を示すタイムスタンプでレコードを "マーク" したいとします。この場合、以下のようなトリガーを記述できます。 `トリガー用の [Documents] テーブル 注: この例題で使用している Time stamp 関数は、固定日付が任意に選択された時点から経過数秒を返す小さなプロジェクトメソッドです。 いったんこのトリガーを記述してアクティブにすると、ユーザーがどのような方法で [Documents] テーブルにレコードを追加または修正しても (データ入力、読み込み、プロジェクトメソッド、4Dプラグイン) 、レコードが最終的にディスクに書き込まれる前に、トリガーによって、[Documents]Creation Stamp フィールドと [Documents]Modification Stamp フィールドに自動的に日付が割り当てられます。 注: この例の詳細についてはGET DOCUMENT PROPERTIESコマンドの例を参照してください。 データベース操作を許可または拒絶するために、トリガーは、戻り値 $0 にトリガーエラーコードを返さなければなりません。 [Employees] テーブルの場合を取り上げてみましょう。データ入力時に、[Employees]Social Security number フィールドで規則を強制します。確認ボタンをクリックする際に、ボタンのオブジェクトメソッドを使用してそのフィールドをチェックします。 ` bAcceptボタンのオブジェクトメソッド フィールド値が有効な場合、データ入力を受け入れます。フィールド値が無効な場合、警告を表示して、データ入力の状態になります。 [Employees] レコードをプログラムで作成した場合、以下のコードはプログラムとしては正当ですが、前述のオブジェクトメソッドで強制した規則に違反します。 `プロジェクトメソッドから抽出する [Employees] テーブルのトリガーを使用して、データベースのすべてのレベルで[Employees]SS number の規則を強制することができます。トリガーは以下のようになります。 `[Employees] のトリガー いったんこのトリガーを記述しアクティブにすると、SAVE RECORD ([Employees]) 行はデータベースエンジンエラー-15050を生成し、そのレコードは保存されません。 同様に4Dプラグインが無効な保険証番号で[Employees] レコードを保存しようとしても、トリガーは同じエラーを生成しレコードは保存されません。 トリガーを使用すれば、誰も (ユーザー、データベース設計者、プラグイン) 保険証番号の規則を故意にまたは偶発的に違反できないことが保証されます。 テーブルのトリガーが無くても、レコードを保存または削除しようとしているときに、データベースエンジンエラーが生じる場合があるので注意してくださ い。例えば、重複不可属性を持つインデックスフィールドで重複する値を持つレコードを保存しようとすると、エラー-9998が返されます。 したがって、エラーを返すトリガーは、新しいデータベースエンジンエラーをアプリケーションへ追加します。
重要: エラーコード値は任意のものを返すことができます。ただし、4Dデータベースエンジンによって既に確保されているエラーコードは使用できません。 -32000 から -15000 の間のエラーコードを使用することを強く勧めます。 -15000を超えるエラーコードは、データベースエンジン用に予約されています。 プロセスレベルでは、データベースエンジンエラーと同じ方法で、トリガーエラーを処理します。
注:
トリガーがエラーを返さないからといって ($0:=0) 、データベース操作が成功したという意味ではありません。重複不可なインデックス違反が生じる場合があります。操作がレコードの更新である場合、レコードがロックされたり I/O エラーが生じたりすることがあります。トリガーの実行後にチェックが終了します。ただしプロセスを実行する高レベルにおいては、データベースエンジンまたはトリガーによって返されるエラーは同じものです。トリガーエラーはデータベースエンジンエラーです。 トリガーはデータベースエンジンレベルで実行されます。以下の図にその様子をまとめています。 データベースエンジンが実際に配置されているマシンでトリガーは実行されます。これはシングルユーザー版の4Dでは明白です。4D Serverではクライアントマシンではなく、サーバーマシン (トリガーを起動させるプロセスの "対の" プロセスで) 上で動作しているプロセス内でトリガーは実行されます。 トリガーが起動される場合、トリガーはデータベース操作を実行しようとするプロセスのコンテキスト内で実行されます。トリガーの実行を引き起こすこのプロセスは起動プロセスと呼ばれます。
4D環境の他のデータベースオブジェクトや言語オブジェクトは注意して使用してください。これは、トリガーが起動プロセスのマシンとは別のマシン上で実行される可能性があるためです。4D Serverがこれに当てはまります。
4Dパスワードシステムを使用した場合、トリガー内でCurrent user コマンドを使用できることに注意して下さい。これを使用すると、例えばジャーナルを取っているテーブルのトリガー呼び出し元にユーザー名を保存することができます(クライアント・サーバーモードにおいても可能です)。 トランザクションは起動プロセスレベルで処理されなければなりません。トリガーレベルでトランザクションを管理してはいけません。一つのトリガーを実行してい る間に、複数のレコード (下記の例を参照) を追加、修正、削除する必要がある場合、最初にトリガー内からIn transactionコマンド を使用して、起動プロセスが現在トランザクション内にあるかどうかテストしなければなりません。そうでない場合には、トリガーがロックされたレコードに出く わす可能性があります。そのため、起動プロセスがトランザクション内に無い場合は、レコードに対する操作を開始しないでください。起動プロセスに、実行し ようとしているデータベース操作はトランザクション内で実行されなければならないことを知らせるためにエラーを$0 に返すだけにしてください。そうしないとロックされたレコードに出くわした場合、起動プロセスにはトリガーの動作をロールバックする方法がなくなります。 注: トリガーとトランザクションを統合した操作を最適化するため、4DではVALIDATE TRANSACTIONを実行した後、トリガーは呼び出されません。これにより、トリガーの実行を2度繰り返すことを防ぎます。 以下の例のようなストラクチャーがあるとします。 注: 上記のテーブルは簡略化されています。実際には、テーブルにはここに示したよりも多くのフィールドがあります。 データベースがある請求書の削除を "許可" するとしましょう。そのような操作がトリガーレベルでどのように処理されるか検討してみます (プロセスレベルで削除を実行することも可能です) 。 リレートに関するデータの整合性を維持するには、請求書の削除において、[Invoices] のトリガー内で実行される以下の動作が必要となります。
最初に、 [Invoices] のトリガーは、起動プロセスがトランザクション内にある場合に限り、これらの動作を実行しなければなりません。そのため、ロックされたレコードに出くわした場合にロールバックが可能になります。 次に、 [Line Items] のトリガーは、 [Invoices] のトリガーとカスケードしています。明細品目の削除は [Invoices] のトリガー内からDELETE SELECTIONを呼び出した結果であるため、 [Line Items] のトリガーは [Invoices] のトリガーの実行の "範囲内で" 実行されます。 この例題にあるすべてのテーブルは、すべてのデータベースイベント対してアクティブなトリガーを持っているとします。トリガーのカスケードは以下のようになります。
こ のカスケードの関係においては、[Invoices] のトリガーはレベル1で、 [Customers]、 [Line Items]、 と [Payments] のトリガーはレベル2で、そして [Products] のトリガーはレベル3で実行されていると言えます。 トリガー内からTrigger levelコマンドを使用して、トリガーが実行されるレベルを検出します。更にTRIGGER PROPERTIESコマンドを使用して、他のレベルに関する情報を入手することができます。 例えば、 [Products] レコードがプロセスレベルで削除されている場合、 [Products] のトリガーは、レベル3ではなく、レベル1で実行されます。 Trigger levelとTRIGGER PROPERTIESを使用すれば、動作の原因を検出できます。前述の例では、請求書がプロセスレベルで削除されています。[Customers] レコードをプロセスレベルで削除すると、 [Customers] のトリガーは、その顧客に関連するすべての請求書を削除しようとします。これにより、前述の例と同じように、 [Invoices] のトリガーが起動されることになりますが、起動される理由は異なります。[Invoices] トリガー内から、そのトリガーがレベル1で実行されたか、レベル2で実行されたかを、検出することができます。トリガーがレベル2で実行された場合には、次に、 それが [Customers] レコードが削除されたためであるかどうかをチェックできます。そうであれば、総売上フィールドの更新にわずらわされる必要はありません。
参照
Record number
|
プロパティ
プロダクト: 4D
履歴
ARTICLE USAGE
ランゲージリファレンス ( 4D v16) |