Skip to main content

This documentation is for an older version of this product. See the latest version of this content.Opens in a new tab

CREATE TRIGGER (SQL)

トリガを作成します。

Synopsis

CREATE [OR REPLACE] TRIGGER trigname {BEFORE | AFTER} event [,event]
          [ORDER integer]
          ON table
          [REFERENCING {OLD | NEW} [ROW] [AS] alias]
         action

引数

引数 説明
trigname 作成するトリガの名前識別子です。トリガ名は修飾、未修飾のどちらでもかまいません。修飾する場合、そのスキーマ名はテーブルのスキーマ名と同じである必要があります。詳細は、"InterSystems SQL の使用法" の “識別子” の章を参照してください。

BEFORE event

AFTER event

event でトリガを実行するタイミング (BEFORE または AFTER)。

トリガ・イベント、またはトリガ・イベントのコンマ区切りリスト。指定できる event リスト・オプションは、INSERT、DELETE、および UPDATE です。

指定できる UPDATE OF event.は 1 つです。UPDATE OF 節の後には、列名またはコンマで区切られた列名のリストが続きます。UPDATE OF 節は、LANGUAGE が SQL の場合にのみ指定できます。UPDATE OF 節は、コンマ区切りの event リストでは指定できません。

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 節、トリガされるアクションの実行を制御する述語条件を含む WHEN 節、および LANGUAGE SQL または LANGUAGE OBJECTSCRIPT のいずれかを指定する LANGUAGE 節をこの順序で並べた、各種オプション・キーワード節を含めることができます。LANGUAGE 節を省略する場合は、SQL が既定です。 これらの節の後に、トリガが実行されたときに実行するアクションを指定する SQL トリガ・コードまたは ObjectScript トリガ・コードを 1 行以上記述します。

概要

CREATE TRIGGER コマンドは、トリガ、つまり、指定のテーブルのデータが変更されたときに実行されるコードのブロックを定義します。指定のテーブルへの新しい行の挿入など、具体的なトリガ・イベントが発生すると、トリガが実行 (“起動” または “プル”) されます。トリガによって、ユーザが指定したトリガ・コードが実行されます。ユーザは、トリガ・イベントの前または後にそのコードを実行するようにトリガを指定できます。トリガは指定のテーブルに固有です。

  • トリガは、指定した event、つまり INSERTDELETE、または UPDATE のいずれかの操作で起動できます。events のコンマ区切りのリストを指定すると、指定したいずれかのイベントが指定のテーブルで発生したときにトリガを実行できます。

  • トリガは、event によって複数回起動されることも、1 回だけ起動されることもあります。行レベルのトリガは変更した行ごとに 1 回起動されます。文レベルのトリガは event に対して 1 回起動されます。このトリガ・タイプは FOR EACH 節を使用して指定します。行レベルのトリガが既定のトリガ・タイプです。

  • 一般的には、トリガ・コードを起動すると、ログ操作の実行やメッセージの表示など、別のテーブルまたはファイルに対する操作が実行されます。トリガを起動することでトリガ・レコードのデータを変更することはできません。例えば、レコード 7 の更新によってトリガが起動される場合、そのトリガのコード・ブロックでレコード 7 を更新または削除することはできません。トリガを呼び出したテーブルと同じテーブルをトリガで変更することはできますが、再帰トリガの無限ループを防ぐため、トリガ event とトリガ・コードの処理は異なっている必要があります。

オプションのキーワード OR REPLACE によって、既存のトリガを変更または置換できます。CREATE OR REPLACE TRIGGER には、DROP TRIGGER を呼び出して古いバージョンのトリガを削除し、続いて CREATE TRIGGER を呼び出す操作と同じ効果があります。DROP TABLE コマンドを実行すると、そのテーブルに関連付けられているトリガはすべて削除されます。

特権とロック

CREATE TRIGGER コマンドの実行には特権が必要です。CREATE TRIGGER を実行するには、ユーザは %CREATE_TRIGGER 管理特権を持っている必要があります。持っていない場合、SQLCODE –99 エラーが発生し、%msg が "ユーザ 'name' は %CREATE_TRIGGER 特権を持っていません" に設定されます。

ユーザは、指定されたテーブルに対する %ALTER 特権を持っている必要があります。ユーザがテーブルの所有者 (作成者) である場合、ユーザにはそのテーブルに対する %ALTER 特権が自動的に付与されます。そうでない場合は、ユーザにテーブルに対する %ALTER 特権を付与する必要があります。持っていない場合、SQLCODE –99 エラーが発生し、%msg が "ユーザ 'name' は 'Schema.TableName' にテーブルを作成するために必要な %ALTER 特権を持っていません。" に設定されます。

適切な付与特権を持っている場合は、GRANT コマンドを使用して %CREATE_TRIGGER 特権および %ALTER 特権を割り当てることができます。

埋め込み 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 は、導入済みの永続クラスから投影されたテーブルでは使用できません。この操作は SQLCODE -400 エラーで失敗し、%msg が “導入済みのクラス classname を変更する DDL を実行できません” に設定されます。

CREATE TRIGGER 文は table に対してテーブル・レベルのロックを取得します。これにより、他のプロセスはこのテーブルのデータを変更できなくなります。このロックは CREATE TRIGGER 処理が終了すると自動的に解除されます。

トリガを作成する場合、そのテーブルを別のプロセスによって EXCLUSIVE MODE または SHARE MODE でロックしないでください。ロックされているテーブルで CREATE TRIGGER 操作を実行しようとすると、SQLCODE -110 エラーになり、%msg が "テーブル 'Sample.MyTest' の排他テーブルロックを取得できません" に設定されます。

その他のトリガ定義方法

SQL トリガをクラス・オブジェクトとして定義できます。"トリガ定義" を参照してください。以下はオブジェクト・トリガの例です。

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. */
}

引数

trigname

トリガ名にはテーブル名と同様の識別子要件があります。しかし一意性の要件は異なります。トリガ名はスキーマ内のすべてのテーブルに対して一意である必要があります。したがって、スキーマ内の異なるテーブルを参照しているトリガを同じ名前にすることはできません。この一意性の要件に違反すると、DROP TRIGGER エラーが発生する可能性があります。

トリガとそのトリガが関連するテーブルは同じスキーマ内に存在している必要があります。同じスキーマ内では、トリガとテーブルに同じ名前を使用できません。トリガの名前付け規約に違反すると、CREATE TRIGGER の実行時に SQLCODE -400 エラーが発生します。

トリガ名は、修飾、未修飾のどちらでもかまいません。修飾されたトリガ名は次のようになります。

schema.trigger

トリガ名が未修飾の場合、トリガのスキーマ名は、既定で、指定したテーブルのスキーマと同じスキーマになります。テーブル名が未修飾の場合、テーブルのスキーマ名は、既定で、指定したトリガのスキーマと同じスキーマになります。両方が未修飾の場合は、既定のスキーマ名が使用されます。スキーマ検索パスは使用されません。両方を修飾する場合は、トリガのスキーマ名がテーブルのスキーマ名と同じである必要があります。スキーマ名が一致しないと SQLCODE -366 エラーになります。これはトリガ名とテーブル名の両方が修飾されていて、異なるスキーマ名を指定しているときにのみ起こります。

トリガ名は、識別子の規則に従い、以下のような制約を受けます。既定のトリガ名は、簡単な識別子です。トリガ名は 128 文字を超えることはできません。トリガ名は、大文字と小文字が区別されません。

InterSystems IRIS では、trigname を使用して InterSystems IRIS クラスの対応するトリガ名を生成します。対応するクラス・トリガ名には英数字 (文字と数字) のみを使用でき、最大長は 96 文字です。この識別子名を生成するために、InterSystems IRIS は最初にトリガ名から句読点を削除し、次に 96 文字 (未満) の一意の識別子を生成します。その際、トリガ名の一意性を維持するために、必要に応じて最後の文字を数字に置き換えます。トリガの名前を付ける際には、この名前生成に伴う以下の制約について考慮する必要があります。

  • トリガ名には、最低でも 1 文字を含める必要があります。トリガ名の先頭の文字または最初の句読点に続く文字は、数字以外の文字にする必要があります。

  • InterSystems IRIS は 16 ビット (ワイド) 文字のトリガ名をサポートします。$ZNAME テストに合格した文字は、有効な文字です。

  • InterSystems IRIS クラスに対して生成される名前には句読点が含まれないため、句読点のみが異なるトリガ名の作成は可能であっても、お勧めできません。

  • トリガ名は 96 文字よりも大幅に長くすることができますが、最初の 96 の英数文字が異なるようにトリガ名を作成すると処理がはるかに容易になります。

既存のトリガの名前を使用して CREATE TRIGGER を発行すると、SQLCODE -365 “トリガ名がユニークでありません” エラーが発行されます。オプションの OR REPLACE キーワードを使用するか、先に DROP TRIGGER で古いトリガを削除します。

1 つのスキーマ内の異なるテーブルを参照している 2 つのトリガが同じ名前である場合、DROP TRIGGER を実行すると、SQLCODE -365 “トリガ名がユニークでありません” エラーが、メッセージ “トリガ 'MyTrigName' が 2 つのクラスで見つかりました” と共に表示されることがあります。

event

トリガ起動のタイミングは、BEFORE キーワードまたは AFTER キーワードで指定します。これらのキーワードで、トリガ操作をトリガの event の発生前に実行するか、発生後に実行するかを指定します。BEFORE トリガが実行される時点は、指定した event の実行前で、その event の検証が終了した後です。例えば、BEFORE DELETE トリガを実行できるのは、DELETE 文が指定の行に対して有効で、DELETE の実行 (外部キー参照の整合性チェックなど) に必要な特権がプロセスに与えられている場合のみです。指定した event をプロセスで実行できない場合は、event に対してエラー・コードが発行され、BEFORE トリガは実行できません。

BEFORE キーワードまたは AFTER キーワードの後に、トリガ・イベントの名前、またはトリガ・イベントのコンマ区切りリストを続けます。INSERT として指定したトリガは、指定のテーブルに行を挿入したときに実行されます。DELETE として指定したトリガは、指定のテーブルから行を削除したときに実行されます。UPDATE として指定したトリガは、指定のテーブルの行を更新したときに実行されます。1 つのトリガ・イベントを指定することも、INSERT、UPDATE、または DELETE の各トリガ・イベントを任意の順序で記述したコンマ区切りリストを指定することもできます。

UPDATE OF として指定したトリガは、指定のテーブルにある行で 1 つ以上の指定した列を更新したときにのみ実行されます。列名はコンマ区切りのリストで指定します。列名は任意の順序で指定できます。UPDATE OF トリガには以下の制限があります。

  • UPDATE OF は、トリガ・コードの言語が SQL (既定) の場合にのみ有効です。トリガ・コードの言語が OBJECTSCRIPT の場合、SQLCODE -50 エラーが発行されます。

  • UPDATE OF を他のトリガ・イベントと組み合わせることはできません。トリガ・イベントのコンマ区切りリストで UPDATE OF を指定すると、SQLCODE -1 エラーが発行されます。

  • UPDATE OF で存在しないフィールドを指定することはできません。指定すると、SQLCODE -400 エラーが発行されます。

  • UPDATE OF で重複するフィールド名を指定することはできません。指定すると、SQLCODE -58 エラーが発行されます。

以下に、event タイプの例を示します。

CREATE TRIGGER TrigBI BEFORE INSERT ON Sample.Person
       INSERT INTO TLog (Text) VALUES ('before insert')
CREATE TRIGGER TrigAU AFTER UPDATE ON Sample.Person
       INSERT INTO TLog (Text) VALUES ('after update')
CREATE TRIGGER TrigBUOF BEFORE UPDATE OF Home_Street,Home_City,Home_State ON Sample.Person
       INSERT INTO TLog (Text) VALUES ('before address update')
CREATE TRIGGER TrigAD AFTER UPDATE,DELETE ON Sample.Person
       INSERT INTO TLog (Text) VALUES ('after update or 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 (Text) VALUES ('doc deleted')
  /* Assigned ORDER=0 */
CREATE TRIGGER TrigB BEFORE DELETE ORDER 4 ON doctable
       INSERT INTO TReport (Text) VALUES ('doc deleted')
  /* Specified as ORDER=4 */
CREATE TRIGGER TrigC BEFORE DELETE ORDER 2 ON doctable
       INSERT INTO Ttemps (Text) VALUES ('doc deleted')
  /* Specified as ORDER=2 */
CREATE TRIGGER TrigD BEFORE DELETE ON doctable
       INSERT INTO Tflags (Text) 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 エラーになります。

以下は、INSERT と共に REFERENCING を使用する例です。

CREATE TRIGGER TrigA AFTER INSERT ON doctable
      REFERENCING NEW ROW AS new_row
BEGIN
      INSERT INTO Log_Table VALUES ('INSERT into doctable');
      INSERT INTO New_Log_Table VALUES ('INSERT into doctable',new_row.ID);
END

action

トリガ動作は、以下の要素から構成されます。

  • オプションの FOR EACH 節。使用できる値は、FOR EACH ROW、FOR EACH ROW_AND_OBJECT、および FOR EACH STATEMENT です。既定は FOR EACH ROW です。

    • FOR EACH ROW — このトリガは、トリガ文の影響を受ける各行によって起動されます。TSQL では、行レベル・トリガはサポートされていないことに注意してください。

    • FOR EACH ROW_AND_OBJECT — このトリガは、トリガ文の影響を受ける各行、またはオブジェクト・アクセスによる変更によって起動されます。TSQL では、行レベル・トリガはサポートされていないことに注意してください。

      このオプションは、統一トリガを定義します。SQL またはオブジェクト・アクセスにより発生するデータ変更によって起動されるトリガであるため、そのように呼ばれます (対照的に、他のトリガを使用すると、オブジェクト・アクセスによる変更の発生時に同じ論理を使用するには、%OnDelete() などのコールバックを実装する必要があります)。

    • FOR EACH STATEMENT — このトリガは、文全体で 1 回起動されます。文レベルのトリガは、ObjectScript トリガと TSQL トリガの両方でサポートされています。

    対応するトリガ・クラス・オプションについては、"FOREACH" を参照してください。

    INFORMATION.SCHEMA.TRIGGERSOpens in a new tabACTIONORIENTATION プロパティを使用して、各トリガの FOR EACH 値をリスト表示できます

  • オプションの 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 として実行されます。これは、InterSystems IRIS で SQL トリガ・コードが ObjectScript に変換されることを意味します。したがって、SQL トリガ・コードに対応するクラス定義を表示すると、トリガ定義では Language=objectscript が表示されることになります。

SQL トリガ・コードの実行時に、システムは自動的に、トリガ・コード内で使用されているすべての変数をリセット (NEW) します。各 SQL 文の実行後に、InterSystems IRIS は SQLCODE をチェックします。エラーが発生すると、InterSystems IRIS は %ok 変数に 0 をセットし、トリガ・コードの処理および関連する INSERTUPDATE、または DELETE を中止してロールバックします。

ObjectScript トリガ・コード

LANGUAGE OBJECTSCRIPT の場合、CREATE TRIGGER 文は REFERENCING 節、WHEN 節、または UPDATE OF 節を含むことができません。これらの SQL 限定である節を LANGUAGE OBJECTSCRIPT と共に指定すると、それぞれコンパイル時に SQLCODE エラーの -49、-57、または -50 が発生します。

LANGUAGE OBJECTSCRIPT の場合、トリガ文は、中括弧で囲まれた 1 つ以上の ObjectScript 文からなるブロックです。

トリガのコードはプロシージャとして生成されないため、トリガ内のすべてのローカル変数はパブリック変数となります。つまり、トリガ内のすべての変数は NEW 文で明示的に宣言される必要があります。これにより、トリガを呼び出すコード内の変数との競合を避けることができます。

トリガ・コードにマクロ・プリプロセッサ文 (# コマンド、## 関数、または $$$ マクロ参照) が含まれる場合、これらの文は CREATE TRIGGER DDL コード本体より前にコンパイルされます。

ObjectScript トリガ・コードには埋め込み SQL を含めることができます。

%ok 変数を 0 に設定して、トリガ・コードからエラーを発行できます。これにより、トリガの実行を中止してロール・バックする実行時エラーが生成されます。また、適切な SQLCODE エラー (例えば、SQLCODE -131 “After Insert トリガが失敗しました”) が生成され、トリガ・コード・エラーの原因を説明する文字列として %msg 変数のユーザ指定値が返されます。%ok を数値以外の値に設定すると、%ok=0 に設定されることに注意してください。

トリガ・コードは一度だけ生成されます。これは、マルチ・イベント・トリガの場合でも同様です。

フィールド参照および擬似フィールド参照

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) を返します。

UPDATEINSERT、または DELETE では、{fieldname} は {fieldname*N} と同じ値を返します。

例えば、以下のトリガは、Sample.Employee に新しく挿入された行の Name フィールドの値を返します (SQL シェルから INSERT を実行して、この結果を表示できます)。

CREATE TRIGGER InsertNameTrig AFTER INSERT ON Sample.Employee
   LANGUAGE OBJECTSCRIPT
   {WRITE "The employee ",{Name*N}," was ",{%%OPERATION},"ed on ",{%%TABLENAME},!}

フィールド値を設定する文の中では改行ができません。詳細は、"クラス定義リファレンス" の "SqlComputeCode" プロパティ・キーワードを参照してください。

GetAllColumns()Opens in a new tab メソッドを使用すると、テーブルのために定義されているフィールド名をリストできます。詳細は、"InterSystems 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)。

ラベル

トリガ・コードには、行ラベル (タグ) が含まれる場合があります。トリガ・コードでラベルを指定するには、ラベル行の先頭にコロンを付けて、その行が最初の列で始まることを示します。InterSystems IRIS はコロンを削除して、残りの行をラベルとして処理します。ただし、トリガ・コードはプロシージャ・ブロックの範囲外で生成されるため、すべてのラベルはクラス定義に対して一意である必要があります。クラスのルーチンにコンパイルされるその他すべてのコードには、同じラベルを定義することはできません。これには、その他のトリガ、プロシージャ・ブロックを使用しないメソッド、SqlComputeCode などが含まれます。

Note:

ラベル用のコロン接頭語の使用は、ホスト変数参照用のコロン接頭語の使用よりも優先されます。この競合を回避するために、埋め込み 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 トリガはロールバックされ、関連する INSERTUPDATE、または DELETE 操作は実行されません。さらに行のすべてのロックは解放されます。

  • 失敗した AFTER トリガはロールバックされ、関連する INSERTUPDATE、または DELETE 操作がロールバックされます。さらに行のすべてのロックは解放されます。

  • 失敗した INSERTUPDATE、または DELETE 操作はロールバックされ、関連する BEFORE トリガがロールバックされます。さらに行のすべてのロックは解放されます。

  • 失敗した INSERTUPDATE、または DELETE 操作はロールバックされ、関連する AFTER トリガは実行されません。さらに行のすべてのロックは解放されます。

整合性が維持されるのは、現在の行の操作のみであることに注意してください。アプリケーション・プログラムは、トランザクション処理文を使用して、複数行での操作も含めてデータの整合性の問題に対処する必要があります。

トリガはアトミック処理であるため、コミットやロールバックのようなトランザクション文は、トリガ・コード内ではコーディングできません。

INSERTUPDATE、または DELETE 操作が複数のトリガを実行する場合、1 つのトリガが失敗すると残りすべてのトリガは実行されないままになります。

  • SQLCODE -415 : トリガ・コードにエラーがある場合 (例えば、存在しないテーブルや未定義の変数への参照)、トリガ・コードの実行は実行時に失敗し、InterSystems IRIS は SQLCODE -415 エラー “SQL ファイラ内で致命的なエラーが発生しました” を発行します。

  • SQLCODE -130 ~ -135 : トリガ処理が失敗すると、InterSystems IRIS は失敗したトリガのタイプにより SQLCODE エラー・コードの -130 から -135 のうちの 1 つを実行時に発行します。トリガ・コード内で %ok 変数を 0 に設定することで、トリガを失敗させることができます。これにより、適切な SQLCODE エラー (例えば、SQLCODE -131 “After Insert トリガが失敗しました”) が発行され、トリガ・コード・エラーの原因を説明する文字列として %msg 変数のユーザ指定値が返されます。

以下の例では、ObjectScript DELETE トリガとの CREATE TRIGGER の使用を実際に示します。ここでは、レコードが含まれるデータ・テーブル (TestDummy) が存在することを想定しています。これは、埋め込み SQL を使用してログ・テーブル (TestDummyLog) と DELETE トリガを作成します。DELETE トリガは、データ・テーブルで削除が実行されたときにログ・テーブルへの書き込みを行います。このトリガは、データ・テーブルの名前、削除された行の RowId、現在の日付、および実行された操作のタイプ (%oper 特殊変数) (この場合は “DELETE”) を挿入します。

 &sql(CREATE TABLE TestDummyLog 
     (TableName VARCHAR(40),
      IDVal INTEGER,
      LogDate DATE,
      Operation VARCHAR(40))
     )
  WRITE !,"SQL log table code is: ",SQLCODE

  &sql(CREATE TRIGGER TrigTestDummy AFTER DELETE ON TestDummy
      LANGUAGE OBJECTSCRIPT {
      NEW id
      SET id = {ID}
      &sql(INSERT INTO TestDummyLog (TableName,IDVal,LogDate,Operation) 
            VALUES ('TestDummy',:id,+$HOROLOG,:%oper))
       }
  )
  WRITE !,"SQL trigger code is: ",SQLCODE

以下の例では、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)
    IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
    ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
    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

以下の例では、Sample.Employee での行の挿入、更新、または削除後に Name フィールドの古い値と新しい値を返すトリガを定義します (SQL シェルからこのトリガ・イベント操作を実行して、この結果を表示できます)。

CREATE TRIGGER EmployNameTrig AFTER INSERT,UPDATE,DELETE ON Sample.Employee
   LANGUAGE OBJECTSCRIPT
   {WRITE "Employee old name:",{Name*O}," new name:",{Name*N}," ",{%%OPERATION}," on ",{%%TABLENAME},!}

関連項目

FeedbackOpens in a new tab