CREATE TRIGGER
Synopsis
CREATE TRIGGER trigname {BEFORE | AFTER} event [ORDER integer] ON table [REFERENCING {OLD | NEW} [ROW] [AS] alias] action
引数
trigname | 作成するトリガの名前。識別子です。トリガ名は修飾、未修飾のどちらでもかまいません。修飾する場合、そのスキーマ名はテーブルのスキーマ名と同じである必要があります。詳細は、"Caché SQL の使用法" の “識別子“ の章を参照してください。 |
BEFORE event AFTER event |
トリガ・イベントのタイミング (BEFORE または AFTER) とタイプ。指定できる event オプションは、INSERT、DELETE、UPDATE、および UPDATE OF です。UPDATE OF 節の後には、列名またはコンマで区切られた列名のリストが続きます。UPDATE OF 節は、LANGUAGE が SQL の場合にのみ指定できます。 |
ORDER integer | オプション — 同じタイミングとイベントのトリガがテーブルに複数存在する場合に、それらのトリガを実行する順番。順番の指定を省略したトリガには、順番 0 が割り当てられます。 |
ON table | トリガが作成されるテーブル。テーブル名は修飾、未修飾のどちらでもかまいません。修飾する場合は、トリガがテーブルと同じスキーマにある必要があります。 |
REFERENCING OLD ROW AS alias REFERENCING NEW ROW AS alias |
オプション — REFERENCING 節は、LANGUAGE が SQL の場合にのみ使用できます。REFERENCING 節を使用して、列の参照に使用できるエイリアスを指定できます。REFERENCING OLD ROW を指定すると、UPDATE または DELETE トリガの実行中に、列の元の値を参照できます。REFERENCING NEW ROW を指定すると、INSERT または UPDATE トリガの実行中に、列の新しい値を参照できます。ROW AS キーワードは省略可能です。UPDATE では、REFERENCING OLD oldalias NEW newalias のように、OLD と NEW の両方を同じ REFERENCING 節で指定できます。 |
action | トリガのプログラム・コード。action 引数には、FOR EACH ROW 節、トリガされるアクションの実行を制御する述語条件を含む WHEN 節、および LANGUAGE SQL または LANGUAGE OBJECTSCRIPT のいずれかを指定する LANGUAGE 節をこの順序で並べた、各種オプション・キーワード節を含めることができます。LANGUAGE 節を省略する場合は、SQL が既定です。これらの節の後に、トリガが実行されたときに実行するアクションを指定するコードを 1 行以上記述します。 |
概要
CREATE TRIGGER コマンドは、トリガ、つまり、指定のテーブルのデータが変更されたときに実行されるコードのブロックを定義します。指定のテーブルへの新しい行の挿入など、具体的なトリガ・イベントが発生すると、トリガが実行 (“起動”) されます。トリガ・イベントでは、INSERT、DELETE、または UPDATE のいずれかのコマンドを使用できます。トリガによって、ユーザが指定したトリガ・コードが実行されます。ユーザは、トリガ・イベントの前または後にそのコードを実行するようにトリガを指定できます。トリガは指定のテーブルに固有です。
シングルイベント・トリガは、指定した INSERT、DELETE、または UPDATE のいずれかの操作でトリガできます。マルチイベント・トリガは、指定したテーブルで、指定したイベントのいずれか 1 つが発生したときに実行するように定義します。マルチイベント・トリガとして、INSERT/UPDATE、UPDATE/DELETE、または INSERT/UPDATE/DELETE を定義できます。
トリガの action コードでは、トリガ・レコードのデータを変更できません。例えば、テーブル列内のデータの更新でトリガが起動される場合、そのトリガのコード・ブロックによって、そのテーブル内のレコードのいずれかで、データの挿入、更新、または削除を実行することはできません。
特権とロック
CREATE TRIGGER コマンドの実行には特権が必要です。CREATE TRIGGER を使用する前に、%CREATE_TRIGGER 特権を得る必要があります。特権がない場合は、SQLCODE -99 エラー (特権違反) が返されます。適切な付与特権を持っていれば、GRANT コマンドを使用して、%CREATE_TRIGGER 特権を割り当てることができます。
埋め込み SQL では、以下のように $SYSTEM.Security.Login()Opens in a new tab メソッドを使用して適切な特権を持ったユーザとしてログインできます。
DO $SYSTEM.Security.Login("_SYSTEM","SYS")
&sql( )
$SYSTEM.Security.Login メソッドを呼び出すには、%Service_Login:Use 特権が必要です。詳細は、"インターシステムズ・クラス・リファレンス" の "%SYSTEM.SecurityOpens in a new tab" を参照してください。
CREATE TRIGGER は、テーブル・クラスの定義に [DdlAllowed] が含まれている場合を除き、永続クラスを定義して作成したテーブルでは使用できません。使用すると、操作は SQLCODE -300 エラーで失敗し、%msg が“DDL がクラス schema.tablename に対して有効になっていません”に設定されます。
CREATE TRIGGER 文は table に対してテーブル・レベルのロックを取得します。これにより、他のプロセスはこのテーブルのデータを変更できなくなります。このロックは CREATE TRIGGER 処理が終了すると自動的に解除されます。
その他のトリガ定義方法
FOREACH = ROW/OBJECT 文を組み込むことで、SQL トリガを Caché オブジェクトとして定義できます。以下はオブジェクト・トリガの例です。
Trigger SQLJournal [ CodeMode = objectgenerator, Event = INSERT/UPDATE, ForEach = ROW/OBJECT, Time = AFTER ]
{ /* ObjectScript trigger code
that updates a journal file
after a row is inserted or updated. */
}
Caché SQL トリガは、%OnBeforeSave()、%OnAfterSave()、また %Save() メソッドの発行時に呼び出される可能性のある %AddToSaveSet()Opens in a new tab などの Caché クラス・メソッドから全面的に独立しており、また、これらのいずれも Caché MultiValue トリガ から全面的に独立しています。いずれかのレルムでデータ変更の操作が発生した場合、そのレルムで定義されたトリガのみが起動します。例えば、Caché SQL データ変更操作によって Multivalue トリガを起動することはできません。Caché MultiValue データ変更操作で Caché SQL トリガを起動することもできません。
引数
trigname
トリガ名にはテーブル名と同様の識別子要件があります。しかし一意性の要件は異なります。トリガ名はスキーマ内のテーブルに対して一意である必要があります。したがって、スキーマ内の異なるテーブルを参照しているトリガの名前が同じ場合もあります。トリガとそのトリガが関連するテーブルは同じスキーマ内に存在している必要があります。同じスキーマ内では、トリガとテーブルに同じ名前を使用できません。トリガの名前付け規約に違反すると、CREATE TRIGGER の実行時に SQLCODE -400 エラーが発生します。
トリガ名は、修飾、未修飾のどちらでもかまいません。修飾されたトリガ名は次のようになります。
schema.trigger
トリガ名が未修飾の場合、トリガ・スキーマ名は既定で table のスキーマと同じになります。どちらも未修飾であれば、システムの既定スキーマが使用されます。トリガ名を修飾する場合は、トリガ・スキーマ名をテーブル・スキーマ名と同じにする必要があります。テーブル・スキーマ名が指定されていない場合は、トリガ・スキーマ名が使用されます。スキーマ名が一致しないと SQLCODE -366 エラーになります。これはトリガ名とテーブル名の両方が修飾されていて、異なるスキーマ名を指定しているときにのみ起こります。
現在のプロセスの既定スキーマ名を返すには、$SYSTEM.SQL.DefaultSchema()Opens in a new tab メソッドを使用します。既定のスキーマ名を構成するには、$SYSTEM.SQL.SetDefaultSchema()Opens in a new tab メソッドを使用します。
トリガ名は、識別子の規則に従い、以下のような制約を受けます。既定のトリガ名は、簡単な識別子です。トリガ名は 128 文字を超えることはできません。トリガ名は、大文字と小文字が区別されません。
Caché では、trigname を使用して Caché クラスの対応するトリガ名を生成します。対応するクラス・トリガ名には英数字 (文字と数字) のみを使用でき、最大長は 96 文字です。この Caché 識別子名を生成するために、Caché は最初にトリガ名から句読点を削除し、次に 96 文字 (未満) の一意の識別子を生成します。その際、トリガ名の一意性を維持するために、必要に応じて最後の文字を数字に置き換えます。トリガの名前を付ける際には、この名前生成に伴う以下の制約について考慮する必要があります。
-
トリガ名には、最低でも 1 文字を含める必要があります。トリガ名の先頭の文字または最初の句読点に続く文字は、数字以外の文字にする必要があります。
-
Caché は Unicode システムで、16 ビット (ワイド) 文字のトリガ名をサポートします。$ZNAME テストに合格した文字は、有効な文字です。
-
Caché クラスに対して生成される名前には句読点が含まれないため、句読点のみが異なるトリガ名の作成は可能であっても、お勧めできません。
-
トリガ名は 96 文字よりも大幅に長くすることができますが、最初の 96 の英数文字が異なるようにトリガ名を作成すると処理がはるかに容易になります。
event
INSERT として指定したトリガは、指定のテーブルに行を挿入したときに実行されます。DELETE として指定したトリガは、指定のテーブルから行を削除したときに実行されます。UPDATE として指定したトリガは、指定のテーブルの行を更新したときに実行されます。
UPDATE OF として指定したトリガは、指定のテーブルにある行で 1 つ以上の指定した列を更新したときにのみ実行されます。列名はコンマ区切りのリストで指定します。列名は任意の順序で指定できますが、重複して使用することはできません。重複していると、コンパイル時に SQLCODE -58 エラーが発生します。UPDATE OF 節はトリガ・コード LANGUAGE が SQL (既定) の場合のみ有効です。
トリガ起動のタイミングは、BEFORE キーワードまたは AFTER キーワードで指定します。これらのキーワードで、トリガ操作をトリガの event の発生前に実行するか、発生後に実行するかを指定します。BEFORE トリガが実行される時点は、指定した event の実行前で、その event の検証が終了した後です。例えば、BEFORE DELETE トリガを実行できるのは、DELETE 文が指定の行に対して有効で、DELETE の実行 (外部キー参照の整合性チェックなど) に必要な特権がプロセスに与えられている場合のみです。指定した event をプロセスで実行できない場合は、event に対してエラー・コードが発行され、BEFORE トリガは実行できません。
以下に、組み合わせ可能な 8 つの event タイプの中の 4 つの例を示します。
CREATE TRIGGER TrigBI BEFORE INSERT ON Sample.Person
INSERT INTO TLog VALUES ('before insert');
CREATE TRIGGER TrigAU AFTER UPDATE ON Sample.Person
INSERT INTO TLog VALUES ('after update');
CREATE TRIGGER TrigBUOF BEFORE UPDATE OF Home_City,Home_State ON Sample.Person
INSERT INTO TLog VALUES ('before address update');
CREATE TRIGGER TrigAD AFTER DELETE ON Sample.Person
INSERT INTO TLog VALUES ('after delete');
ORDER
ORDER 節は、同じタイミングとイベントのトリガが 1 つのテーブルに複数存在する場合に、それらのトリガを実行する順番を指定します。例えば、2 つの AFTER DELETE トリガのような場合です。ORDER の整数値が最小のトリガが最初に実行され、その後は、次に高い整数値を持つトリガが順次実行されます。ORDER 節が指定されない場合は、ORDER 値に 0 (ゼロ) が割り当てられてトリガが生成されます。したがって、ORDER 節を持たないトリガは、必ず ORDER 節を持つトリガの前に実行されます。
複数のトリガに同じ ORDER 値を割り当てることができます。また、ORDER が 0 (明示的または暗黙的) のトリガを複数作成することもできます。タイミング、イベント、および順序が同じ複数のトリガは、任意の順序でまとめて実行されます。
トリガはタイミング、順序、イベントの順に実行されます。BEFORE INSERT トリガと BEFORE INSERT/UPDATE トリガがある場合は、ORDER 値が最も小さいトリガが最初に実行されます。BEFORE INSERT トリガと BEFORE INSERT/UPDATE トリガがあり、ORDER 値が同じ場合は、INSERT が INSERT/UPDATE よりも前に実行されます。タイミングと順序が同じ場合、シングル・イベント・トリガは常にマルチ・イベント・トリガの前に実行されるためです。2 つ (またはそれ以上) のトリガでタイミング、順序、イベントの値が同じ場合は、命令の実行はランダムになります。
以下の例は、ORDER 値がどのように機能するかを示します。以下のどの CREATE TRIGGER 文でも、同じイベントで実行するトリガが作成されます。
CREATE TRIGGER TrigA BEFORE DELETE ON doctable
INSERT INTO TLog VALUES ('doc deleted');
-- Assigned ORDER=0
CREATE TRIGGER TrigB BEFORE DELETE ORDER 4 ON doctable
INSERT INTO TReport VALUES ('doc deleted')
-- Specified as ORDER=4
CREATE TRIGGER TrigC BEFORE DELETE ORDER 2 ON doctable
INSERT INTO Ttemps VALUES ('doc deleted')
-- Specified as ORDER=2
CREATE TRIGGER TrigD BEFORE DELETE ON doctable
INSERT INTO Tflags VALUES ('doc deleted')
-- Also assigned ORDER=0
これらのトリガは、(TrigA または TrigD)、TrigC、TrigB の順に実行されます。TrigA と TrigD は同じ ORDER 値となるので、任意の順序で実行されます。
REFERENCING
REFERENCING 節では、行の元の値、新しい値、またはその両方に対してエイリアスを指定できます。元の値とは、UPDATE または DELETE トリガのトリガ動作が実行される前の行の値のことです。新しい値とは、UPDATE または INSERT トリガのトリガ動作が実行された後の行の値のことです。UPDATE トリガの場合は、以下のようにして、元の行値と新しい値の両方にエイリアスを指定できます。
REFERENCING OLD ROW AS oldalias NEW ROW AS newalias
キーワードの ROW と AS は省略可能です。したがって、同じ節を以下のように指定することもできます。
REFERENCING OLD oldalias NEW newalias
INSERT 前の元の値や DELETE 後の新しい値を参照することには、意味がありません。それらを参照すると、コンパイル時に SQLCODE -48 が返されます。
REFERENCING 節は action プログラム・コードが SQL の場合にのみ、使用できます。LANGUAGE OBJECTSCRIPT 節と共に REFERENCING 節を指定すると、SQLCODE -49 エラーになります。
action
トリガ動作は、以下の要素から構成されます。
-
オプションの FOR EACH 節。使用できる値は、FOR EACH ROW、FOR EACH ROW_AND_OBJECT、および FOR EACH STATEMENT です。FOR EACH ROW は、このトリガが SQL ファイリング操作によって呼び出されたことを表します。 FOR EACH ROW_AND_OBJECT は、このトリガが SQL ファイリング操作または Caché Objects ファイリング操作によって呼び出されたことを表します。FOR EACH STATEMENT は、TSQL トリガとの互換性のために用意されています。
-
オプションの WHEN 節。WHEN 節は、WHEN キーワードとその後の括弧で囲まれた (単純または複雑な) 述語条件から成ります。述語条件が True に評価されると、トリガが実行されます。WHEN 節は、LANGUAGE が SQL の場合にのみ使用できます。WHEN 節は、oldalias 値または newalias 値を参照できます。述語条件式の詳細、および使用可能な述語のリストは、本ドキュメントの "述語の概要" のページを参照してください。
-
オプションの LANGUAGE 節。LANGUAGE SQL または LANGUAGE OBJECTSCRIPT を指定できます。既定は LANGUAGE SQL です。
-
トリガが実行されたときに実行するユーザ記述のコードです。
SQL トリガ・コード
LANGUAGE SQL の場合、既定でトリガ文は SQL プロシージャ・ブロックです。SQL プロシージャ・ブロックは、1 つの SQL プロシージャ文とその後のセミコロン、またはキーワード BEGIN で始まりキーワード END で終わる 1 つ以上の SQL プロシージャ文と各文の後のセミコロンから成ります。
トリガ動作はアトミックで、完全に適用されるかまったく適用されないかのどちらかです。これに COMMIT 文または ROLLBACK 文を含めることはできません。キーワード BEGIN ATOMIC は、キーワード BEGIN と同義です。
LANGUAGE SQL の場合、CREATE TRIGGER 文はオプションで REFERENCING 節、WHEN 節、および/または UPDATE OF 節を含むことができます。UPDATE OF 節は、トリガに指定した 1 つ以上の列で UPDATE が実行されたときにのみ、トリガを実行することを指定します。LANGUAGE OBJECTSCRIPT の CREATE TRIGGER 文では、これらの節を含むことができません。
SQL トリガ・コードは埋め込み SQL として実行されます。これは、Caché で SQL トリガ・コードが ObjectScript に変換されることを意味します。したがって、スタジオを使用して SQL トリガ・コードに対応するクラス定義を表示すると、スタジオのトリガ定義では言語モードが Caché として表示されることになります。
SQL トリガ・コードの実行時に、システムは自動的に、トリガ・コード内で使用されているすべての変数をリセット (NEW) します。各 SQL 文の実行後に、Caché は SQLCODE をチェックします。エラーが発生すると、Caché は %ok 変数に 0 をセットし、トリガ・コードの処理および関連する INSERT、UPDATE、または DELETE を中止してロールバックします。
ObjectScript トリガ・コード
LANGUAGE OBJECTSCRIPT の場合、CREATE TRIGGER 文は REFERENCING 節、WHEN 節、または UPDATE OF 節を含むことができません。これらの SQL 限定である節を LANGUAGE OBJECTSCRIPT と共に指定すると、それぞれコンパイル時に SQLCODE エラーの -49、-57、または -50 が発生します。
LANGUAGE OBJECTSCRIPT の場合、トリガ文は、中括弧で囲まれた 1 つ以上の ObjectScript 文からなるブロックです。
トリガのコードはプロシージャとして生成されないため、トリガ内のすべてのローカル変数はパブリック変数となります。つまり、トリガ内のすべての変数は NEW 文で明示的に宣言される必要があります。これにより、トリガを呼び出すコード内の変数との競合を避けることができます。
トリガ・コードに Caché マクロ・プリプロセッサ文 (# コマンド、## 関数、または $$$ マクロ参照) が含まれる場合、これらの文は CREATE TRIGGER DDL コード本体より前にコンパイルされます。
%ok 変数を 0 に設定することで、トリガ・コードからエラーを発行できます。この設定によって、実行時エラーを生成し、トリガの実行が中止されます。また、トリガ・コードでは %msg 変数に実行時エラーの起きた節を記述する文字列を設定することもできます。
バージョン 2012.1 以降、システムによってトリガ・コードが 1 度だけ生成されます。これは、マルチ・イベント・トリガの場合でも同様です。
フィールド参照および擬似フィールド参照
ObjectScript で記述するトリガ・コードには、{fieldname} で指定するフィールド参照を含めることができます。ここで、fieldname は現在のテーブルの既存フィールドを指定します。中括弧内に空白スペースは許可されません。
fieldname の後に *N (新)、*O (旧)、または *C (比較) を付けて、挿入、更新、または削除されたフィールドのデータ値の処理方法を以下のとおりに指定できます。
-
{fieldname*N}
-
UPDATE の場合は、指定された変更が行われた後の新しいフィールド値を返します。
-
INSERT の場合は、挿入した値を返します。
-
DELETE の場合は、削除前のフィールド値を返します。
-
-
{fieldname*O}
-
UPDATE の場合は、指定された変更が行われる前の元のフィールド値を返します。
-
INSERT の場合は、NULL を返します。
-
DELETE の場合は、削除前のフィールド値を返します。
-
-
{fieldname*C}
-
UPDATE の場合は、新しい値が古い値と異なる場合に 1 (TRUE) を返します。そうでない場合は 0 (FALSE) を返します。
-
INSERT の場合は、挿入した値が NULL でない場合に 1 (TRUE) を返します。そうでない場合は 0 (FALSE) を返します。
-
DELETE の場合は、削除される値が NULL でない場合に 1 (TRUE) を返します。そうでない場合は 0 (FALSE) を返します。
-
UPDATE、INSERT、または DELETE では、{fieldname} は {fieldname*N} と同じ値を返します。
フィールド値を設定する文の中では改行ができません。詳細は、"Caché クラス定義リファレンス" の "SqlComputeCode" プロパティ・キーワードを参照してください。
GetColumns()Opens in a new tab メソッドを使用すると、テーブルのために定義されているフィールド名をリストできます。詳細は、"Caché SQL の使用法" の “テーブルの定義” の章にある "列の名前と番号" を参照してください。
また、ObjectScript で記述するトリガ・コードには、擬似フィールド参照変数の {%%CLASSNAME}、{%%CLASSNAMEQ}、{%%OPERATION}、{%%TABLENAME}、および {%%ID} を含めることもできます。擬似フィールドは、クラスのコンパイル時に特定の値に変換されます。これらの擬似フィールド・キーワードは、すべて大文字と小文字が区別されません。
-
{%%CLASSNAME} と {%%CLASSNAMEQ} は、ともに SQL テーブル定義を投影するクラスの名前に変換されます。{%%CLASSNAME} は引用符なし文字列を返し、{%%CLASSNAMEQ} は引用符付き文字列を返します。
-
{%%OPERATION} は、トリガを呼び出した操作に応じて、文字列リテラル (INSERT、UPDATE、または DELETE のいずれか) に変換されます。
-
{%%TABLENAME} はテーブルの完全修飾名に変換され、引用符付き文字列を返します。
-
{%%ID} は RowID 名に変換されます。この参照は、RowID フィールドの名前がわからないときに役立ちます。
ストリーム・プロパティの参照
{StreamField}、{StreamField*O}、または {StreamField*N} など、ストリーム・フィールド/プロパティがトリガ定義で参照される場合は、{StreamField} 参照の値がストリームの OID (オブジェクト ID) 値となります。
BEFORE INSERT または BEFORE UPDATE トリガについては、新しい値が INSERT/UPDATE/ObjectSave によって指定される場合、{StreamField*N} 値が一時的ストリーム・オブジェクトの OID 、または新しいリテラル・ストリーム値のどちらかとなります。BEFORE UPDATE トリガについては、新しい値がストリーム・フィールド/プロパティに対して指定されていない場合、{StreamField*O} および {StreamField*N} は両方とも現在のフィールド/プロパティ・ストリーム・オブジェクトの OID になります。
SQLComputed プロパティの参照
一時 SqlComputed フィールド/プロパティ ("Calculated" または明示的な "Transient" のどちらか) がトリガ定義で参照される場合、そのトリガは Get()/Set() メソッドのオーバーライドを認識しません。プロパティの Get() または Set() メソッドをオーバーライドするのではなく、SQLCOMPUTED/SQLCOMPUTONCHANGE を使用してください。
Get()/Set() メソッドのオーバーライドを使用すると、{property*O} 値の決定に SQL が使用されて、オーバーライドされた Get()/Set() メソッドが使用されないという誤った結果がもたらされる可能性があります。プロパティがディスク上に格納されないため、{property*O} では SqlComputeCode が使用されて古い値が "再作成" されます。ただし、{property*N} は、オーバーライドされた Get()/Set() メソッドを使用してプロパティの値にアクセスします。その結果、プロパティが実際に変更されなかった場合でも、{property*O} と {property*N} は異なる場合があります (したがって、{property*C}=1) 。
ラベル
トリガ・コードには、行ラベル (タグ) が含まれる場合があります。トリガ・コードでラベルを指定するには、ラベル行の先頭にコロンを付けて、その行が最初の列で始まることを示します。Caché はコロンを削除して、残りの行をラベルとして処理します。ただし、トリガ・コードはプロシージャ・ブロックの範囲外で生成されるため、すべてのラベルはクラス定義に対して一意である必要があります。クラスのルーチンにコンパイルされるその他すべてのコードには、同じラベルを定義することはできません。これには、その他のトリガ、プロシージャ・ブロックを使用しないメソッド、SqlComputeCode などが含まれます。
ラベル用のコロン接頭語の使用は、ホスト変数参照用のコロン接頭語の使用よりも優先されます。この競合を回避するために、埋め込み SQL トリガ・コード行の先頭にホスト変数参照を記述しないことをお勧めします。トリガ・コード行の先頭にホスト変数参照を記述する必要がある場合は、二重のコロン接頭語を使用することで、それがホスト変数でありラベルでないことを明示してください。
メソッドの呼び出し
クラス・メソッドは開いているオブジェクトの有無に依存しないため、クラス・メソッドをトリガ・コード内から使用できます。クラス・メソッドを呼び出すには、##class(classname).Method() 構文を使用する必要があります。..Method() 構文では、現在開いているオブジェクトが必要なので、この構文は使用できません。
クラス・メソッドの引数として現在の行のフィールドの値を渡すことができますが、クラス・メソッド自体はフィールド構文を使用できません。
既存のトリガのリスト
INFORMATION.SCHEMA.TRIGGERSOpens in a new tab クラスを使用して、現在定義されているトリガをリストできます。このクラスは各トリガについて、トリガ名、関連するスキーマとテーブル名、およびトリガ作成タイムスタンプをリストします。各トリガについて、EVENT_MANIPULATION プロパティ (INSERT、UPDATE、DELETE、INSERT/UPDATE、INSERT/UPDATE/DELETE) と ACTION_TIMING プロパティ (BEFORE、AFTER) をリストします。また、生成された SQL トリガ・コードである ACTION_STATEMENT もリストします。
トリガの実行時エラー
トリガおよびそのトリガが起動するイベントは、単一行ベースでアトミック処理として実行されます。つまり、以下のように処理されます。
-
失敗した BEFORE トリガはロールバックされ、関連する INSERT、UPDATE、または DELETE 操作は実行されません。さらに行のすべてのロックは解放されます。
-
失敗した AFTER トリガはロールバックされ、関連する INSERT、UPDATE、または DELETE 操作がロールバックされます。さらに行のすべてのロックは解放されます。
-
失敗した INSERT、UPDATE、または DELETE 操作はロールバックされ、関連する BEFORE トリガがロールバックされます。さらに行のすべてのロックは解放されます。
-
失敗した INSERT、UPDATE、または DELETE 操作はロールバックされ、関連する AFTER トリガは実行されません。さらに行のすべてのロックは解放されます。
整合性が維持されるのは、現在の行の操作のみであることに注意してください。アプリケーション・プログラムは、トランザクション処理文を使用して、複数行での操作も含めてデータの整合性の問題に対処する必要があります。
トリガはアトミック処理であるため、コミットやロールバックのようなトランザクション文は、トリガ・コード内ではコーディングできません。
INSERT、UPDATE、または DELETE 操作が複数のトリガを実行する場合、1 つのトリガが失敗すると残りすべてのトリガは実行されないままになります。
致命的なランタイム・エラーによってデータベース操作が失敗すると、Caché は SQLCODE -415 エラーを発行します。トリガ処理が失敗すると、Caché は失敗したトリガのタイプにより SQLCODE エラー・コードの -130 から -135 のうちの 1 つを発行します。トリガ・コード内で %ok 変数を 0 に設定することで、トリガを失敗させることができます。また、%msg 変数にトリガの失敗時に返すメッセージを含む文字列を設定することもできます。
例
以下の 2 つの埋め込み SQL プログラムは、ObjectScript INSERT トリガを使用した CREATE TRIGGER を示しています。最初の例では、テーブルおよびそのテーブルの INSERT トリガを作成します。2 番目のプログラムでは、テーブルに対して INSERT を発行し、メッセージを書き込むトリガを実行します。次にテーブルを削除し、このプログラムを繰り返し実行できるようにします。
DO $SYSTEM.Security.Login("_SYSTEM","SYS")
&sql(CREATE TABLE TestDummy (
testnum INT NOT NULL,
firstword CHAR (30) NOT NULL,
lastword CHAR (30) NOT NULL,
CONSTRAINT TestDummyPK PRIMARY KEY (testnum))
)
WRITE !,"SQL table code is: ",SQLCODE
&sql(CREATE TRIGGER TrigTestDummy AFTER INSERT ON TestDummy
LANGUAGE OBJECTSCRIPT
{WRITE "I just fired the trigger" }
)
WRITE !,"SQL trigger code is: ",SQLCODE
NEW SQLCODE,%ROWCOUNT,%ROWID
&sql(INSERT INTO TestDummy (testnum,firstword,lastword) VALUES
(46639,'hello','goodbye'))
IF SQLCODE=0 {
WRITE !,"Insert succeeded"
WRITE !,"Row count=",%ROWCOUNT
WRITE !,"Row ID=",%ROWID }
ELSE {
WRITE !,"Insert failed, SQLCODE=",SQLCODE }
&sql(DROP TABLE TestDummy)
以下の例では、SQL INSERT トリガとの CREATE TRIGGER の使用を実際に示します。1 つ目の埋め込み SQL プログラムでは、テーブル、そのテーブルの INSERT トリガ、およびそのトリガの使用を記録するログ・テーブルを作成します。2 つ目の埋め込み SQL プログラムでは、テーブルに対して INSERT を発行し、トリガを呼び出してログ・テーブルにエントリを記録します。ログ・エントリの表示後、プログラムは両方のテーブルを削除し、このプログラムを繰り返し実行できるようにします。
DO $SYSTEM.Security.Login("_SYSTEM","SYS")
&sql(CREATE TABLE TestDummy (
testnum INT NOT NULL,
firstword CHAR (30) NOT NULL,
lastword CHAR (30) NOT NULL,
CONSTRAINT TestDummyPK PRIMARY KEY (testnum))
)
WRITE !,"SQL table code is: ",SQLCODE
&sql(CREATE TABLE TestDummyLog (
entry CHAR (60) NOT NULL)
)
WRITE !,"SQL log table code is: ",SQLCODE
&sql(CREATE TRIGGER TrigTestDummy AFTER INSERT ON TestDummy
LANGUAGE SQL
BEGIN
INSERT INTO TestDummyLog (entry) VALUES
(CURRENT_TIMESTAMP||' INSERT to TestDummy');
END )
WRITE !,"SQL trigger code is: ",SQLCODE
NEW SQLCODE,%ROWCOUNT,%ROWID
&sql(INSERT INTO TestDummy (testnum,firstword,lastword) VALUES
(46639,'hello','goodbye'))
IF SQLCODE=0 {
WRITE !,"Insert succeeded"
WRITE !,"Row count=",%ROWCOUNT
WRITE !,"Row ID=",%ROWID }
ELSE {
WRITE !,"Insert failed, SQLCODE=",SQLCODE }
&sql(SELECT entry INTO :logitem FROM TestDummyLog)
WRITE !,"Log entry: ",logitem
&sql(DROP TABLE TestDummy)
&sql(DROP TABLE TestDummyLog)
WRITE !,"finished!"
以下に、括弧内の述語条件が満たされた場合にのみ action が実行されるように指定する WHEN 節の例を示します。
CREATE TRIGGER Trigger_2 AFTER INSERT ON Table_1
WHEN (f1 %STARTSWITH 'A')
BEGIN
INSERT INTO Log_Table VALUES (new_row.Category);
END
関連項目
-
"Caché SQL の使用法" の “トリガの使用法“ の章
-
"Caché エラー・リファレンス" にリストされた SQLCODE エラー・メッセージ