CREATE TRIGGER ステートメント

CREATE TRIGGER ステートメントは、データベースにトリガーを定義します。 トリガーを作成することで、一般的形式の整合性規則や業務規則をサポートできます。 トリガーは、INSERT、UPDATE、または DELETE ステートメントを使用して実行される、つまりそれらのステートメントによって起動される一連のアクションを定義します。

呼び出し

このステートメントは、アプリケーション・プログラムに組み込んだり、動的 SQL ステートメントを使用して発行したりすることができます。 これは、DYNAMICRULES の実行動作がパッケージに効力を持つ場合にのみ、動的に準備できる実行可能ステートメントです (SQLSTATE 42509)。

許可

ステートメントの許可 ID によって保持されている特権には、少なくとも以下のいずれかの権限が含まれていなければなりません。
  • BEFORE または AFTER トリガーを定義する表に対する ALTER 特権
  • INSTEAD OF トリガーを定義するビューに対する CONTROL 特権
  • INSTEAD OF トリガーを定義するビューの所有者
  • トリガーを定義する表またはビューのスキーマに対する ALTERIN 特権
  • トリガーが定義されている表またはビューが含まれるスキーマに対する SCHEMAADM 権限。
  • DBADM 権限
および以下のいずれか
  • データベースに対する IMPLICIT_SCHEMA 権限 (トリガーの暗黙または明示のスキーマ名が存在しない場合)
  • スキーマに対する CREATEIN 特権 (トリガーのスキーマ名が既存のスキーマを指している場合)
  • スキーマに対する SCHEMAADM 権限 (トリガーのスキーマ名が既存のスキーマを指している場合)
  • DBADM 権限
このステートメントの許可 ID に DATAACCESS 権限がない場合には、トリガーが存在する限り、ステートメントの許可 ID が持つ特権 (グループ特権は除外) に、以下のすべての権限が含まれている必要があります。
  • 遷移変数または遷移表を指定する場合は、トリガーを定義する表に対する以下のもの
    • 遷移変数または遷移表を指定する場合は、トリガーを定義する表に対する SELECT 特権
    • 遷移変数または遷移表を指定する場合は、トリガーを定義する表が含まれるスキーマに対する SELECTIN 特権
    • 遷移変数または遷移表を指定する場合は、トリガーを定義する表に対する CONTROL 特権
    • 遷移変数または遷移表を指定する場合は、トリガーを定義する表が含まれるスキーマに対する DATAACCESS 権限
    • DATAACCESS 権限
  • トリガー・アクション条件で参照される表またはビューに対する以下のもの
    • トリガー・アクション条件で参照される表またはビューに対する SELECT 特権
    • トリガー・アクション条件で参照される表またはビューが含まれるスキーマに対する SELECTIN 特権
    • トリガー・アクション条件で参照される表またはビューに対する CONTROL 特権
    • トリガー・アクション条件で参照される表またはビューが含まれるスキーマに対する DATAACCESS 権限
    • DATAACCESS 権限
  • 指定したトリガー SQL ステートメントを呼び出すために必要な特権

グループ特権は、CREATE TRIGGER ステートメントで指定された表やビューに対しては考慮されません。

既存のトリガーを置換するには、ステートメントの許可 ID が既存のトリガーの所有者でなければなりません (SQLSTATE 42501)。

SECURED オプションを指定する場合は、 ステートメントの許可 ID が保持している特権に、SECADM または CREATE_SECURE_OBJECT 権限が追加で含まれている必要があります (SQLSTATE 42501)。

構文

Read syntax diagramSkip visual syntax diagramCREATEOR REPLACE TRIGGERtrigger-nameNO CASCADEBEFOREAFTERINSTEAD OFtrigger-eventON table-nameview-name REFERENCING12OLDAScorrelation-nameNEWAScorrelation-nameOLD TABLEASidentifierNEW TABLEASidentifierFOR EACH ROW3FOR EACH STATEMENTNOT SECUREDSECUREDtriggered-action
trigger-event
Read syntax diagramSkip visual syntax diagramORINSERTDELETEUPDATEOF,column-name4
triggered-action
Read syntax diagramSkip visual syntax diagram5WHEN(search-condition)label:SQL-procedure-statement
SQL-procedure-statement
Read syntax diagramSkip visual syntax diagramCALLCompound SQL (compiled)6Compound SQL (inlined)FORWITH,common-table-expressionfullselectGET DIAGNOSTICSIFINSERTITERATELEAVEMERGEsearched-deletesearched-updateSET VariableSIGNALWHILE
Notes:
  • 1 OLD and NEW can only be specified once each.
  • 2 OLD TABLE and NEW TABLE can only be specified once each, and only for AFTER triggers or INSTEAD OF triggers.
  • 3 FOR EACH STATEMENT may not be specified for BEFORE triggers or INSTEAD OF triggers.
  • 4 A trigger event must not be specified more than once for the same operation. For example, INSERT OR DELETE is allowed, but INSERT OR INSERT is not allowed.
  • 5 WHEN condition may not be specified for INSTEAD OF triggers.
  • 6 A compound SQL (compiled) statement cannot be specified if the trigger definition includes a REFERENCING OLD TABLE clause or a REFERENCING NEW TABLE clause. A compound SQL (compiled) statement also cannot be specified for a trigger definition in a partitioned database environment.

説明

OR REPLACE
トリガーの定義が現行のサーバーにある場合にそれを置き換えることを指定します。 既存の定義が実際にドロップされてから、カタログ内で新しい定義が置き換えられます。 トリガーの定義が現行のサーバーにない場合は、このオプションは無視されます。 このオプションは、オブジェクトの所有者しか指定できません。
トリガー名
トリガーの名前を指定します。 この名前 (暗黙または明示のスキーマ名を含む) は、カタログ内で既に記述されているトリガーを特定するものであってはなりません (SQLSTATE 42710)。 2 部構成の名前指定する場合は、スキーマ名の先頭を「SYS」にすることはできません (SQLSTATE 42939)。
NO CASCADE BEFORE
サブジェクト表の実際の更新による変更がデータベースに適用される前に、関連したトリガー・アクションが適用されることを指定します。 また、このトリガーのトリガー・アクションが、 他のトリガーをアクティブ化することがないことも指定します。
AFTER
サブジェクト表の実際の更新による変更がデータベースに適用された後に、関連したトリガー・アクションが適用されることを指定します。
INSTEAD OF
サブジェクト・ビューに対するアクションを、ここで関連付けるトリガー・アクションに置換することを指定します。 INSTEAD OF トリガーは、サブジェクトとなる特定のビューに対する各操作ごとに 1 つだけ許可されます (SQLSTATE 428FP)。
trigger-event
これを指定すると、サブジェクト表またはサブジェクト・ビューにいずれかのイベントが適用される場合には必ず、このトリガーに関連するトリガー・アクションが実行されます。 任意の組み合わせのイベントを指定できますが、各イベント (INSERT、DELETE、および UPDATE) は 1 回しか指定できません (SQLSTATE.42613)。 複数のイベントを指定する場合、トリガー・アクションはコンパウンド SQL (コンパイル済み) ステートメントでなければなりません (SQLSTATE 42601)。
INSERT
サブジェクト表またはサブジェクト・ビューに INSERT 操作が適用される場合には必ず、 このトリガーに関連するトリガー・アクションを実行することを指定します。
DELETE
サブジェクト表またはサブジェクト・ビューに DELETE 操作が適用される場合には必ず、 このトリガーに関連するトリガー・アクションを実行することを指定します。
UPDATE
指定した列または暗黙に指定される列に従って、 サブジェクト表またはサブジェクト・ビューに UPDATE 操作が適用される場合には必ず、 このトリガーに関連するトリガー・アクションを実行することを指定します。
オプションの column-name のリストの指定がない場合、 暗黙に表またはビューのすべての列が指定されます。 したがって、column-name リストを省略すると、 表またはビューの列のいずれかの更新によってトリガーがアクティブ化されることが暗に指定されます。
OF column-name, ...
それぞれの column-name には、基本表の列を指定する必要があります (SQLSTATE 42703)。 トリガーが BEFORE トリガーの場合は、column-name に ID 列以外の生成された列を指定することはできません (SQLSTATE 42989)。 column-name のリストでは、同じ column-name を複数回使用することはできません (SQLSTATE 42711)。 トリガーがアクティブになるのは、column-name のリストで指定した列の更新時のみです。 この節は INSTEAD OF トリガーには指定できません (SQLSTATE 42613)。
ON
table-name
BEFORE トリガーまたは AFTER トリガーの定義のサブジェクト表を指定します。 この名前は、基本表か、基本表に解決される別名を指定するものでなければなりません (SQLSTATE 42704 または 42809)。 この名前に、カタログ表 (SQLSTATE 42832)、マテリアライズ照会表 (SQLSTATE 42997)、作成済み一時表 、宣言済み一時表 (SQLSTATE 42995)、あるいはニックネーム (SQLSTATE 42809) を指定することはできません。
ビュー名
INSTEAD OF トリガー定義のサブジェクト・ビューを指定します。 その名前では、型なしビュー、またはタイプ XML の列を含まない型なしビューに解決できる別名を指定しなければなりません (SQLSTATE 42704 または 42809)。 指定する名前は、カタログ・ビューであってはなりません (SQLSTATE 42832)。 指定する名前は、WITH CHECK OPTION (対称ビュー) を使用して定義されるビュー、 または対称ビューが直接的または間接的に定義されたビューであってはなりません (SQLSTATE 428FQ)。
NOT SECURED または SECURED
トリガーがセキュアであるとみなされるかどうかを指定します。 デフォルトは NOT SECURED です。
NOT SECURED
トリガーがセキュアでないとみなされることを指定します。
SECURED
トリガーがセキュアであるとみなされることを指定します。 行レベルまたは列レベルのアクセス制御がアクティブになっている表をサブジェクト表として持つトリガーには、SECURED を指定する必要があります (SQLSTATE 428H8)。 同様に、あるトリガーがビューに対して作成され、そのビュー定義の 1 つ以上の基礎表の行レベルまたは列レベルのアクセス制御がアクティブになっている場合、そのトリガーには、SECURED を指定する必要があります (SQLSTATE 428H8)。
REFERENCING
遷移変数 の相関名と遷移表 の表名を指定します。 相関名は、トリガー SQL 操作の影響を受ける行セット内の特定の行を指定します。 表名には、影響を受ける行の集合全体を指定します。 以下のように correlation-names を指定して列を修飾すると、トリガー SQL 操作の影響を受ける各行をトリガー・アクションで使用できます。
OLD AS 相関名
トリガーとなる SQL 操作の前の時点での行の状態を指定する相関名を指定します。
NEW AS 相関名
トリガーとなる SQL 操作および、既に実行された BEFORE トリガーの SET ステートメントによって、変更された時の行の状態を指定する 相関名を指定します。

トリガーとなる SQL 操作によって影響を受ける行全体の集合をトリガー・アクションで使用するには、 次のように指定される一時表名を使用します。

OLD TABLE AS ID
トリガーとなる SQL 操作が行われる前の操作対象行の完全なセットの値を指す一時表の名前を指定します。 トリガー・イベントが INSERT である場合、一時表は空になります。
NEW TABLE AS ID
トリガーとなる SQL 操作によって、また、既に実行された BEFORE トリガーの SET ステートメントによって変更された操作対象行の完全なセットの状態を指す一時表の名前を指定します。 トリガー・イベントが DELETE である場合、一時表は空になります。
REFERENCING 節には、次の規則が適用されます。
  • OLD および NEW の相関名と、OLD TABLE および NEW TABLE の名前は、 いずれも同じであってはなりません (SQLSTATE 42712)。
  • 1 つのトリガーには、correlation-name として、 1 つの OLD と 1 つの NEW だけしか指定できません (SQLSTATE 42613)。
  • 1 つのトリガーには、 identifier として 1 つの OLD TABLE と 1 つの NEW TABLE しか 指定できません (SQLSTATE 42613)。
  • OLD TABLE または NEW TABLE の ID は、BEFORE トリガーには定義できません (SQLSTATE 42898)。
  • NEW 遷移変数は、BEFORE トリガーにおいてのみ割り当てのターゲットにできます。 それ以外の場合、遷移変数は割り当てのターゲットにすることはできません (SQLSTATE 42703 または 42987)。
  • OLD または NEW の相関名は、FOR EACH STATEMENT トリガーには定義できません (SQLSTATE 42899)。
  • 遷移表は変更できません (SQLSTATE 42807)。
  • トリガー・アクションの中での遷移表の列と遷移変数への参照の合計回数が、 表内の列数の限界を超えてはなりません。また、その長さの合計が、 表の中の行の最大長を超えてはなりません (SQLSTATE 54040)。
  • correlation-name と各 identifier の有効範囲は、 トリガー定義全体です。
  • triggered-action にコンパウンド SQL (コンパイル済み) ステートメントが含まれる場合には、以下のようになります。
    • OLD TABLE または NEW TABLE の ID は、定義できません。
    • 操作が DELETE 操作の場合、OLD correlation-name では、削除された行の値が取り込まれます。 操作が UPDATE 操作の場合、 その UPDATE 操作の前の時点での行の値を捕らえるものとなります。 挿入操作の場合、OLD correlation-name を使用すると、特定の行の各列の NULL 値が取り込まれます。
    • 挿入操作または更新操作の場合、値 NEW を使用すると、元の操作によって提供され、その時点までに実行された BEFORE トリガーによって変更された、行の新しい状態が取り込まれます。 削除操作の場合、NEW correlation-name を使用すると、特定の行の各列の NULL 値が取り込まれます。 BEFORE DELETE トリガーでは、新しい遷移変数に割り当てられた NULL 以外の値は、割り当てが行われたトリガーの中でのみ持続します。
  • triggered-action にコンパウンド SQL (コンパイル済み) ステートメントが含まれない場合には、以下のようになります。
    • OLD correlation-name と OLD TABLE identifier は、 トリガー・イベントが DELETE 操作または UPDATE 操作のいずれかである場合にしか 使用できません (SQLSTATE 42898)。 操作が DELETE 操作の場合、OLD correlation-name では、削除された行の値が取り込まれます。 操作が UPDATE 操作の場合、 その UPDATE 操作の前の時点での行の値を捕らえるものとなります。 同じことが OLD TABLE identifier と それによって影響を受ける行の集合にも適用されます。
    • NEW correlation-name と NEW TABLE identifier は、 トリガー・イベントが INSERT 操作または UPDATE 操作のいずれかである場合にしか 使用できません (SQLSTATE 42898)。 どちらの操作でも、NEW の値は、元の操作によって提供されたが、 その時点までに実行された BEFORE トリガーによってさらに変更された、行の新しい状態を捕らえます。 同じことが NEW TABLE identifier とそれによって影響を受ける行の集合にも 適用されます。
FOR EACH ROW
トリガーとなる SQL 操作によって影響を受けるサブジェクト表またはサブジェクト・ビューの各行ごとに、 トリガー・アクションが一度ずつ適用されるよう指定します。
FOR EACH STATEMENT
トリガー・アクションがステートメント全体に対して 1 回のみ適用されることを指定します。 このタイプのトリガー精度は、BEFORE トリガーまたは INSTEAD OF トリガーには指定できません (SQLSTATE 42613)。 指定すると、 トリガーとなる UPDATE または DELETE ステートメントによって影響を受ける行がない場合でも、 UPDATE トリガーまたは DELETE トリガーがアクティブ化されることになってしまいます。
triggered-action
トリガーをアクティブ化するときに実行されるアクションを指定します。 トリガー・アクションは SQL-procedure-statement、 および SQL-procedure-statement 実行のオプション条件から構成されています。

トリガー・イベント述部は、コンパウンド SQL (コンパイル済み) ステートメントを SQL-procedure-statement として使用する CREATE TRIGGER ステートメントのトリガー・アクションのどこにでも使用できます。

WHEN
(検索条件)
真、偽、または不明の条件を指定します。 search-condition を使用すると、特定のトリガー・アクションを実行する必要があるかどうかを判別することができます。 関連したアクションは、指定した検索条件が真と評価される場合のみ実行されます。 WHEN 節が省略されると、関連する SQL-procedure-statement が常に実行されます。

WHEN 節を INSTEAD OF トリガーに指定することはできません (SQLSTATE 42613)。

XML データ・タイプを使用する遷移変数の参照は、VALIDATED 述部でのみ使用できます。

label:
SQL プロシージャー・ステートメントのラベルを指定します。 ラベルは、リスト内でネストされたコンパウンド・ステートメントを含め、SQL プロシージャー・ステートメントの リスト内でユニークでなければなりません。 ネストされていないコンパウンド・ステートメントは、同じラベルを使用できることに注意してください。 SQL プロシージャー・ステートメントのリストは、おそらく SQL 制御ステートメントの中にあります。

FOR ステートメント、WHILE ステートメント、 およびコンパウンド SQL ステートメントだけにラベルを組み込むことができます。

SQL-procedure-statement
トリガー・アクションの一部にする SQL ステートメントを指定します。 コンパウンド SQL 内のニックネームに対する検索更新、検索削除、挿入、またはマージ操作はサポートされません。

XML タイプの列に対する BEFORE トリガーのトリガー・アクションで、SET ステートメントを介して XMLVALIDATE 関数を呼び出す、XML タイプの値を変更せずにそのままにしておく、または SET ステートメントを使用して XML タイプの値に NULL を割り当てることができます。

SQL-procedure-statement には、 サポートされていないステートメントを入れることはできません (SQLSTATE 42987)。

SQL-procedure-statement は、未定義の遷移変数 (SQLSTATE 42703)、 フェデレーテッド・オブジェクト (SQLSTATE 42997)、または宣言済み一時表 (SQLSTATE 42995) を参照できません。 また、BUSINESS_TIME 期間の開始列および終了列も参照できません (SQLSTATE 42808)。

BEFORE トリガー内の SQL-procedure-statement には、以下の制限があります。
  • INSERT、DELETE、UPDATE のいずれの操作も組み込むことはできません。これがコンパウンド SQL (コンパイル済み) でない場合には、MODIFIES SQL DATA で定義されたルーチンを呼び出すことはできません。
  • トリガー・サブジェクト表には DELETE と UPDATE のいずれの操作も組み込むことはできません。これがコンパウンド SQL (コンパイル済み) である場合には、そのような操作が組み込まれたルーチンを呼び出すことはできません。
  • REFRESH IMMEDIATE で定義されたマテリアライズ照会表を参照できません (SQLSTATE 42997)。
  • NEW 遷移変数内の ID 列以外の生成列を参照できません (SQLSTATE 42989)。

  • 既に行が含まれている表にトリガーを追加しても、 トリガー・アクションはアクティブ化されません。 そのため、トリガーが表内のデータに制約を適用するように設計されている場合、 既存の行についてはそれらの制約が満たされない可能性があります。
  • 2 つのトリガーのイベントが同時に発生する場合 (例えばイベント、アクティブ化のタイミング、 およびサブジェクト表が同じである場合)、最初に作成されたトリガーが最初に実行されます。 OR REPLACE オプションを使用して、以前に作成されたトリガーを置き換える場合は、作成時刻が変更されるので、トリガーの実行順序に影響する可能性があります。
  • トリガーの定義後にサブジェクト表に列が追加された場合、次の規則が適用されます。
    • トリガーが、明示的な列リストなしで指定された UPDATE トリガーである場合、 新しい列への更新によってトリガーがアクティブ化されます。
    • その列は、それ以前に定義されたトリガーのトリガー・アクションからは見えません。
    • OLD TABLE および NEW TABLE の各遷移表に、この列は含まれません。 したがって、遷移表に対して 「SELECT *」を実行しても、追加列は含められません。
  • トリガー・アクションで参照される表に 1 つの列を追加した場合、 新しい列はそのトリガー・アクションからは見えません。
  • トリガーの本体内で参照されるオブジェクトが存在しないか、無効とマークが付いているか、または定義者にこのオブジェクトに対するアクセス権が一時的にない場合で、データベース構成パラメーターの auto_reval が DISABLED に設定されていない場合でも、トリガーは正常に作成されます。 このトリガーは、無効とマークを付けられ、 次回呼び出されたときに再度有効化されます。
  • SQL-procedure-statement に指定されている全選択の結果は、 トリガーの内部または外部では使用不可です。
  • トリガー・コンパウンド・ステートメント内で呼び出されるプロシージャーは、 COMMIT または ROLLBACK ステートメントを発行できません (SQLSTATE 42985)。
  • 検索 UPDATE ステートメント、検索 DELETE ステートメント、または INSERT ステートメント内のニックネームへの参照を含むプロシージャーはサポートされていません (SQLSTATE 25000)。
  • 表アクセスの制限:: プロシージャーが READS SQL DATA または MODIFIES SQL DATA として定義されている場合は、プロシージャー内のステートメントは、このプロシージャーを呼び出したコンパウンド・ステートメントによって変更される表にアクセスすることはできません (SQLSTATE 57053)。 プロシージャーが MODIFIES SQL DATA として定義されている場合は、プロシージャー内のステートメントは、 このプロシージャーを呼び出したコンパウンド・ステートメントによって読み取られるまたは変更される表を変更できません (SQLSTATE 57053)。
  • カスケードされた参照制約のサイクルに関係のある表に対して定義された BEFORE DELETE トリガーには、そのトリガーが定義されている表への参照や、参照整合性制約のサイクルの評価中にカスケードされて変更された他の表への参照を含めないでください。 そのようなトリガーを含めると、結果がデータによってまちまちになり、 一貫性のない状態が生じてしまう可能性があります。

    最も簡単な形では、自己参照の参照制約のある表に対する BEFORE DELETE トリガーや CASCADE の削除規則に、triggered-action に関係のある表への参照を含めてはいけないということになります。

  • トリガーを作成すると、特定のパッケージは無効として扱われるようになります。
    • 明示的な列リストなしの UPDATE トリガーを作成した場合、 ターゲット表またはビューに対して更新操作を使用するパッケージは無効になります。
    • 列リストを指定した UPDATE トリガーを作成した場合、 ターゲット表に対して更新操作を使用するパッケージは、そのパッケージにおいて、 CREATE TRIGGER ステートメントの column-name リストの中の 少なくとも 1 つの列に対しても更新を使用する場合にのみ無効になります。
    • INSERT トリガーを作成した場合、 ターゲット表またはビューに対して挿入操作を使用するパッケージは無効になります。
    • 削除トリガーを作成した場合、 ターゲット表またはビューに対して削除操作を使用するパッケージは無効になります。
  • パッケージは、アプリケーション・プログラムが明示的にバインドまたは再バインドされるまで、 あるいはアプリケーション・プログラムが実行されてデータベース・マネージャーが自動的にそれを再バインドするまで、 無効のままになります。
  • 作動不能トリガー: 作動不能トリガー は、使用可能でなくなったためにアクティブ化されないトリガーです。 以下の場合、トリガーは操作不能になります。
    • トリガーを実行するため、そのトリガーの作成者が持っていなければならない特権が取り消された。
    • トリガーされたアクションが依存する、表、ビュー、または別名といったオブジェクトがドロップされた。
    • トリガーが定義されたビューが操作不能になった。
    • トリガーのサブジェクト表である別名がドロップされた。

    実際、操作不能トリガーは、DROP または REVOKE ステートメントのカスケード規則の 結果、トリガー定義がドロップされたトリガーです。 例えば、ビューがドロップされると、そのビューを持つ SQL プロシージャー・ステートメント 参照を含む を持つトリガーは作動不能になります。

    トリガーが操作不能になると、そのトリガーをアクティブ化していた操作を実行する ステートメントを持つパッケージはすべて無効とマークされます。 パッケージが (明示的または暗黙的に) 再バインドされると、操作不能トリガーは完全に無視されます。 同様に、トリガーをアクティブ化していた操作を実行する動的 SQL ステートメントを含むアプリケーションも、 作動不能トリガーを完全に無視します。

    トリガー名は、DROP TRIGGER および COMMENT ON TRIGGER の各ステートメントにも指定できます。

    操作不能トリガーは、その定義テキストを使用して CREATE TRIGGER ステートメントを 出すことによって再作成できます。 このトリガー定義テキストは、SYSCAT.TRIGGERS カタログ・ビューの TEXT 列に保管されています。 操作不能トリガーを再作成するため、そのトリガーを明示的にドロップする必要はありません。 操作不能トリガーと同じ trigger-name で CREATE TRIGGER ステートメントを 出すと、警告とともに、その操作不能トリガーは置換されます (SQLSTATE 01595)。

    作動不能トリガーであることは、 SYSCAT.TRIGGERS カタログ・ビューの VALID 列が X であることによって示されます。

  • トリガー実行中のエラー: トリガー SQL ステートメントの実行時に発生したエラーは、エラーが重大であると見なされた場合以外は SQLSTATE 09000 を使用して戻されます。 重大エラーであれば、重大エラー SQLSTATE が返されます。 重大エラーでない場合、SQLCA の SQLERRMC フィールドには、トリガー名、 SQLCODE、 SQLSTATE、および障害のあるトークンから入るだけの数のトークンが組み込まれます。

    SQL-procedure-statement には SIGNAL SQLSTATE ステートメント または RAISE_ERROR 関数が組み込まれていることがあります。 どちらの場合も、返される SQLSTATE は、SIGNAL SQLSTATE ステートメント または RAISE_ERROR 条件に指定されているものです。

  • まだ存在していないスキーマ名を用いてトリガーを作成すると、 ステートメントの許可 ID に IMPLICIT_SCHEMA 権限がある場合に限り、 そのスキーマが暗黙的に作成されます。 スキーマの所有者は SYSIBM になります。 スキーマに対する CREATEIN 特権が PUBLIC に付与されます。
  • DB2SECURITYLABEL 列: DB2SECURITYLABEL 列は BEFORE TRIGGER のトリガー本体で参照できますが、BEFORE トリガーの本体で変更することはできません (SQLSTATE 42989)。
  • BUSINESS_TIME 期間列: BUSINESS_TIME 期間の開始列および終了列は、BEFORE UPDATE トリガーの本体で変更することはできません (SQLSTATE 42808)。
  • 読み取り専用ビュー: あるビューに対して INSTEAD OF トリガーを追加すると、このビューの読み取り専用の特性に影響を与えます。 読み取り専用ビューに INSTEAD OF トリガーとの従属関係がある場合は、INSTEAD OF トリガーに定義された操作タイプにより、このビューが削除可能、挿入可能、または更新可能のいずれであるかが定義されます。
  • 遷移変数の値と INSTEAD OF トリガー: INSTEAD OF INSERT トリガー内で可視の新しい遷移変数または新しい遷移表の列のための初期値は、以下のように設定されます。
    • 挿入操作である値がある列に明示的に指定された場合は、対応する新しい遷移変数はその明示的に指定された値です。
    • 挿入操作である値がある列に明示的に指定されなかったか、または DEFAULT 節が指定された場合は、対応する新しい遷移変数は、以下のとおりです。
      • ビューの列が更新可能な場合 (INSTEAD OF トリガーなしで)、基礎表の列のデフォルト値
      • ビューの列が更新可能でない場合、NULL 値
    INSTEAD OF UPDATE トリガー内で可視の新しい遷移変数のための初期値は、以下のように設定されます。
    • 更新操作である値がある列に明示的に指定された場合は、対応する新しい遷移変数はその明示的に指定された値です。
    • 更新操作で DEFAULT 節がある列に明示的に指定された場合は、対応する新しい遷移変数は、以下のとおりです。
      • ビューの列が更新可能な場合 (INSTEAD OF トリガーなしで)、基礎表の列のデフォルト値
      • ビューの列が更新可能でない場合、NULL 値
    • 上記以外の場合は、対応する新しい遷移変数は行内のその列の既存の値です。
  • トリガーおよび型付き表: 表階層のどのレベルの型付き表にも、BEFORE または AFTER トリガーを付加することができます。 SQL ステートメントが複数のトリガーをアクティブ化する場合、 それらのトリガーは、それぞれ型付き表階層の別々の表に付加されていても、 作成順に実行されます。

    トリガーがアクティブ化されたとき、 その遷移変数 (OLD、NEW、OLD TABLE、NEW TABLE) 内に副表の行が入っていることがあります。 ただし、付加先の表で定義されている列しか入っていません。

    INSERT、UPDATE、および DELETE ステートメントの効果は次のとおりです。
    • 行トリガー: SQL ステートメントを使って表の行の INSERT、UPDATE、または DELETE を行うと、 このステートメントは、行の入った最も限定的な表と その表のすべてのスーパー表に付加されている行トリガーをアクティブ化します。 SQL ステートメントがどのように表にアクセスするかに関係なく、常にこのような規則になります。 例えば、UPDATE EMP コマンドを実行すると、 更新済みの行の一部が、副表 MGR に入ることがあります。 EMP 行の場合、EMP とそのスーパー表に付加されている行トリガーがアクティブ化されます。 MGR 行の場合、MGR とそのスーパー表に付加されている行トリガーがアクティブ化されます。
    • ステートメント・トリガー: INSERT、UPDATE、または DELETE ステートメントは、 このステートメントによって影響を受ける可能性のある表 (および そのスーパー表) に付加されているステートメント・トリガーをアクティブ化します。 そのような表内の実際の行が影響を受けたかどうかに関係なく、常にこのような規則になります。 例えば、INSERT INTO EMP コマンドで、 EMP とそのスーパー表のステートメント・トリガーをアクティブ化します。 別の例として、副表行が更新も削除もされていない場合でも、UPDATE EMP または DELETE EMP コマンドで、EMP とそのスーパー表と副表のステートメント・トリガーがアクティブ化されます。 同様に、UPDATE ONLY (EMP) または DELETE ONLY (EMP) コマンドは、 EMP とそのスーパー表のステートメント・トリガーをアクティブ化しますが、 副表のステートメント・トリガーはアクティブ化しません。
    DROP TABLE ステートメントの効果: DROP TABLE ステートメントは、 ドロップしようとしている表に付加されているどのトリガーもアクティブ化しません。 ただし、ドロップされる表が副表である場合、 そのドロップされる表の行すべては、スーパー表から削除されるものと見なされます。 したがって、表 T の場合は次のようになります。
    • 行トリガー: DROP TABLE T は、T の行ごとに、 T のすべてのスーパー表に付加されている行タイプの削除トリガーをアクティブ化します。
    • ステートメント・トリガー: DROP TABLE T は、T に行が入っているかどうかに関係なく、 T のすべてのスーパー表に付加されているステートメント・タイプの削除トリガーをアクティブ化します。
    ビューでのアクション: ビューでのアクションによってどのトリガーがアクティブ化されるかを予測するには、 ビュー定義を使ってそのアクションを、基本表でのアクションに変換します。 以下に例を示します。
    1. SQL ステートメントで UPDATE V1 を実行します。 V1 は、サブビュー V2 を持つ型付きビューです。 V1 は基礎表 T1 をもち、V2 は基礎表 T2 をもっているとします。 ステートメントは、T1、T2、およびそれらの副表内の行に影響を与える可能性があるので、 T1 と T2 およびそのすべての副表とスーパー表のステートメント・トリガーがアクティブ化されます。
    2. SQL ステートメントで UPDATE V1 を実行します。 V1 は、サブビュー V2 を持つ型付きビューです。 V1 は SELECT ... FROM ONLY(T1) と定義されていて、V2は SELECT ... FROM ONLY(T2) と定義されていると仮定します。 ステートメントは、T1 と T2 の副表内の行には影響を与えないので、 T1 と T2 およびそれぞれのスーパー表のステートメント・トリガーはアクティブ化されますが、 これらの表の副表のものはアクティブ化されません。
    3. SQL ステートメントは UPDATE ONLY (V1) を実行します。V1 は SELECT ... FROM T1 として定義された型付きビューです。 ステートメントは、T1 とその副表に影響を与える可能性があります。 したがって、T1 とそのすべての副表とスーパー表のステートメント・トリガーがアクティブ化されます。
    4. SQL ステートメントは UPDATE ONLY (V1) を実行します。V1 は SELECT ... FROM ONLY (T1)と定義された型付きビューです。 この場合、V1 がサブビューをもち T1 が副表をもっていても、 T1 だけがステートメントから影響を受けることができます。 したがって、T1 とそのスーパー表のステートメント・トリガーのみがアクティブ化されます。
  • MERGE ステートメントおよびトリガー: MERGE ステートメントは、更新、削除、および挿入操作を実行できます。 MERGE ステートメントの適用可能な UPDATE、DELETE、または INSERT トリガーは、 更新、削除、または挿入操作の実行時にアクティブ化されます。
  • 難読化: CREATE TRIGGER ステートメントを難読化形式でサブミットできます。 難読化されたステートメントでは、トリガー名のみを判読できます。 残りのステートメントは、読み取れないようにエンコードされますが、データベース・サーバーによりデコードできます。 難読化ステートメントの作成は、DBMS_DDL.WRAP 関数を呼び出すことによって行えます。
  • SECURED オプションを指定したトリガーの作成: 通常、SECADM 権限を持つユーザーは、トリガーやユーザー定義関数などのデータベース・オブジェクトを作成する特権を持ちません。 一般的に、このユーザーは、トリガーによってアクセスされるデータを検査し、 それがセキュアであることを確認してから、セキュア・トリガーの作成に必要な特権を持っているユーザーに CREATE_SECURE_OBJECT 権限を付与します。 トリガーの作成後、SECADM 権限を持つユーザーは、トリガー所有者の CREATE_SECURE_OBJECT 権限を取り消します。

    トリガーがセキュアであると見なされます。 データベース・マネージャーは、SECURED 属性を、トリガー本体のすべてのアクティビティーについての監査プロシージャーをユーザーが設定したことを宣言するアサーションとして処理します。 セキュア・トリガーがユーザー定義関数を参照する場合、データベース・マネージャーではそれらの関数について妥当性検査をすることなくセキュアであると見なします。 それらの関数が機密データにアクセスできる場合、SECADM 権限のあるユーザーは、それらの関数がこのデータへのアクセスを許可されていることと、後続のすべての ALTER FUNCTION ステートメント、または外部パッケージへの変更がこの監査プロセスで検査されていることを確認する必要があります。

    トリガーのサブジェクト表の行レベルまたは列レベルのアクセス制御がアクティブになっている場合、そのトリガーはセキュアにする必要があります。 同様に、トリガーのサブジェクト表がビューであり、そのビュー定義の 1 つ以上の基礎表の行レベルまたは列レベルのアクセス制御がアクティブになっている場合、そのトリガーはセキュアにする必要があります。

  • NOT SECURED オプションを指定したトリガーの作成: トリガーのサブジェクト表の行レベルまたは列レベルのアクセス制御がアクティブになっている場合、CREATE TRIGGER ステートメントを実行するとエラーが返されます。 同様に、トリガーがビューに対して定義され、そのビュー定義の 1 つ以上の基礎表の行レベルまたは列レベルのアクセス制御がアクティブになっている場合、CREATE TRIGGER ステートメントは失敗します。
  • 遷移変数および遷移表に対して強制適用されない行と列のアクセス制御: データベース保全性のためにトリガーが使用されます。そのため、セキュリティーとデータベース保全性の間でバランスが必要です。 サブジェクト表またはサブジェクト・ビューの基礎表において行レベルまたは列レベルのアクセス制御がアクティブになっている場合、行権限と列マスクは、遷移変数と遷移表の初期値には適用されません。 サブジェクト表またはサブジェクト・ビューの基礎表に対して強制適用される行レベルと列レベルのアクセス制御も、トリガー本体で参照される遷移変数と遷移表、およびトリガー本体で呼び出されるユーザー定義関数の引数として渡される遷移変数と遷移表において無視されます。 トリガー・アクションの SQL ステートメントで遷移変数と遷移表に含まれる機密データにアクセスするときのセキュリティー上の心配をなくすため、トリガーは SECURED オプションを指定して作成する必要があります。 トリガーがセキュアでない場合、CREATE TRIGGER ステートメントを実行するとエラーが返されます。
  • 暗黙的な隠し列に関する考慮事項: 遷移変数は、暗黙的な隠し列と定義された列に対して存在します。 暗黙的な隠し列に対応する遷移変数は、トリガーの本体で参照できます。
  • 従属パッケージの再バインド: すべてのコンパイル済みトリガーには、従属パッケージが存在します。 このパッケージは、REBIND_ROUTINE_PACKAGE プロシージャーを使用していつでも再バインドすることができます。 明示的に従属パッケージを再バインドしても、無効なトリガーの再有効化は行われません。 無効なトリガーは、自動再有効化を使用するか、または明示的に ADMIN_REVALIDATE_DB_OBJECTS プロシージャーを使用して再有効化してください。 トリガーの再有効化では、自動的に従属パッケージが再バインドされます。
  • 代替構文: Db2® の以前のバージョンおよび他のデータベース製品との互換性のために、以下の代替の構文がサポートされています。 これらの代替は非標準であり、使用すべきではありません。
    • OLD TABLE の代わりに OLD_TABLE、NEW TABLE の代わりに NEW_TABLE をそれぞれ指定できます。
    • MODE DB2SQL は、FOR EACH ROW または FOR EACH STATEMENT の後に指定できます。

  • 例 1: 会社が管理する従業員の数の自動追跡を実行する 2 つのトリガーを作成します。 このトリガーは、次の表に作用します。
    • EMPLOYEE 表 (列は ID、NAME、ADDRESS、および POSITION)
    • COMPANY_STATS 表 (列は NBEMP、NBPRODUCT、および REVENUE)
    最初のトリガーは、 新しい従業員を採用するたびに (つまり EMPLOYEE 表に新しい行が挿入されるたびに)、 従業員数に 1 を加算します。
       CREATE TRIGGER NEW_HIRED
         AFTER INSERT ON EMPLOYEE
         FOR EACH ROW
         UPDATE COMPANY_STATS SET NBEMP = NBEMP + 1
    2 番目のトリガーは、 従業員が会社を退職するたびに (つまり EMPLOYEE 表から行が削除されるたびに)、 従業員数から 1 を減算します。
       CREATE TRIGGER FORMER_EMP
         AFTER DELETE ON EMPLOYEE
         FOR EACH ROW
         UPDATE COMPANY_STATS SET NBEMP = NBEMP - 1
  • 例 2: 部品のレコードが更新されると、 以下の検査と (必要ならば) アクションを実行するトリガーを作成します。
    • 手持ち数量 (ON_HAND) が最大在庫量 (MAX_STOCKED) の 10% 未満になった場合、 その部品の品目数として最大在庫量から手持ち数量を引いた数を指定した出荷依頼書を発行します。

    このトリガーは、PARTNO、DESCRIPTION、ON_HAND、MAX_STOCKED、 および PRICE の列を含む PARTS 表に作用します。

    ISSUE_SHIP_REQUEST は、追加部品の注文書を、発注先に送るユーザー定義関数です。
       CREATE TRIGGER REORDER
         AFTER UPDATE OF ON_HAND, MAX_STOCKED ON PARTS
         REFERENCING NEW AS N
         FOR EACH ROW
         WHEN (N.ON_HAND < 0.10 * N.MAX_STOCKED)
         BEGIN ATOMIC
         VALUES(ISSUE_SHIP_REQUEST(N.MAX_STOCKED - N.ON_HAND, N.PARTNO));
         END
  • 例 3: 例 2 のシナリオを繰り返しますが、VALUES ステートメントの代わりに全選択を使用してユーザー定義関数を呼び出す点が違います。 この例では、行トリガーの代わりにステートメント・トリガーとしてトリガーを定義する方法も示します。 WHERE 節について真と評価する遷移表の行ごとに、部品の出荷要求を発行します。
       CREATE TRIGGER REORDER 
          AFTER UPDATE OF ON_HAND, MAX_STOCKED ON PARTS 
          REFERENCING NEW TABLE AS NTABLE
          FOR EACH STATEMENT
             BEGIN ATOMIC 
                SELECT ISSUE_SHIP_REQUEST(MAX_STOCKED - ON_HAND, PARTNO)
                   FROM NTABLE 
                WHERE (ON_HAND < 0.10 * MAX_STOCKED); 
          END
  • 例 4: 更新の結果、現行の給与の 10 % を超える昇給になった場合にエラーを生じさせるトリガーを作成します。
       CREATE TRIGGER RAISE_LIMIT
         AFTER UPDATE OF SALARY ON EMPLOYEE
         REFERENCING NEW AS N OLD AS O
         FOR EACH ROW
         WHEN (N.SALARY > 1.1 * O.SALARY)
                SIGNAL SQLSTATE '75000' SET MESSAGE_TEXT='Salary increase>10%'
  • 例 5: 株価の変更を記録し追跡するアプリケーションについて考えます。 データベースには、CURRENTQUOTE および QUOTEHISTORY という 2 つの表が含まれています。
       Tables: CURRENTQUOTE (SYMBOL, QUOTE, STATUS)
               QUOTEHISTORY (SYMBOL, QUOTE, QUOTE_TIMESTAMP)
    CURRENTQUOTE の QUOTE (相場) 列が更新されると、 新しい相場とタイム・スタンプを QUOTEHISTORY 表にコピーするようにします。 CURRENTQUOTE の STATUS (状況) 列も、 次のような株の状況が反映されるように更新します。
    1. 値上がり
    2. 今年の新高値
    3. 値下がり
    4. 今年の新安値
    5. 変わらず
    これを実現する CREATE TRIGGER ステートメントは、次のようになります。
    • 状況を設定するトリガーの定義
         CREATE TRIGGER STOCK_STATUS
           NO CASCADE BEFORE UPDATE OF QUOTE ON CURRENTQUOTE
           REFERENCING NEW AS NEWQUOTE OLD AS OLDQUOTE
           FOR EACH ROW
           BEGIN ATOMIC
              SET NEWQUOTE.STATUS =
                CASE
                   WHEN NEWQUOTE.QUOTE >
                         (SELECT MAX(QUOTE) FROM QUOTEHISTORY
                         WHERE SYMBOL = NEWQUOTE.SYMBOL
                         AND YEAR(QUOTE_TIMESTAMP) = YEAR(CURRENT DATE) )
                      THEN 'High'
                   WHEN NEWQUOTE.QUOTE <
      (SELECT MIN(QUOTE) FROM QUOTEHISTORY
                         WHERE SYMBOL = NEWQUOTE.SYMBOL
                         AND YEAR(QUOTE_TIMESTAMP) = YEAR(CURRENT DATE) )
                      THEN 'Low'
                   WHEN NEWQUOTE.QUOTE > OLDQUOTE.QUOTE
                      THEN 'Rising'
                   WHEN NEWQUOTE.QUOTE < OLDQUOTE.QUOTE
                      THEN 'Dropping'
                   WHEN NEWQUOTE.QUOTE = OLDQUOTE.QUOTE
                      THEN 'Steady'
                END;
           END
    • 変更内容を QUOTEHISTORY 表に記録するトリガーの定義
         CREATE TRIGGER RECORD_HISTORY
           AFTER UPDATE OF QUOTE ON CURRENTQUOTE
           REFERENCING NEW AS NEWQUOTE
           FOR EACH ROW
           BEGIN ATOMIC
             INSERT INTO QUOTEHISTORY
               VALUES (NEWQUOTE.SYMBOL, NEWQUOTE.QUOTE, CURRENT TIMESTAMP);
           END
  • 例 6: org 表の従業員レコードのロケーション・フィールドの変更をオーバーライドするトリガーを作成します。 小さな会社を買い取ったときに取得した新しい従業員レコードを処理して、従業員に割り振られているターゲット・ロケーションが「Toronto」の場合に、新しいターゲット・ロケーションを「Los Angeles」にする、といった場合に、このトリガーは便利です。 この BEFORE トリガーによって、アプリケーションがそのフィールドにどんな値を割り振るにしても、最終結果値を「Los Angeles」に設定できます。
    
       CREATE TRIGGER LOCATION_TRIGGER
         NO CASCADE
          BEFORE UPDATE ON ORG
          REFERENCING
            OLD AS PRE
            NEW AS POST
          FOR EACH ROW
          WHEN (POST.LOCATION = 'Toronto')
             SET POST.LOCATION = 'Los Angeles';
          END
    
  • 例 7: 新製品の記述を含んだ XML 文書を、SAMPLE データベースの PRODUCT 表に挿入する前に、自動的に妥当性検査するための BEFORE トリガーを作成します。
    
       CREATE TRIGGER NEWPROD NO CASCADE BEFORE INSERT ON PRODUCT
          REFERENCING NEW AS N
          FOR EACH ROW
          BEGIN ATOMIC
             SET (N.DESCRIPTION) = XMLVALIDATE(N.DESCRIPTION
                ACCORDING TO XMLSCHEMA ID product);
          END
    
  • 例 8: 会社が管理する従業員の数と給与を追跡する複数イベント・トリガーを作成します。 このトリガーは、次の列と表に作用します。
    • EMPLOYEE 表の ID、NAME、ADDRESS、SALARY、および POSITION 列
    • COMPANY_STATS 表の NBEMP、NBPRODUCT、および REVENUE 列
    このトリガーは、新しい従業員を採用するたびに従業員数に 1 を加算し、従業員が会社を辞めるたびに従業員数から 1 を減算します。さらに、更新時に昇給額が現在の給与の 10 % を超える場合にはエラーを発生させます。
    CREATE OR REPLACE TRIGGER HIRED
       AFTER INSERT OR DELETE OR UPDATE OF SALARY ON EMPLOYEE
       REFERENCING NEW AS N OLD AS O FOR EACH ROW
       BEGIN
          IF INSERTING THEN UPDATE COMPANY_STATS SET NBEMP = NBEMP + 1;
          ELSEIF DELETING THEN UPDATE COMPANY_STATS SET NBEMP = NBEMP - 1;
          ELSEIF (UPDATING AND (N.SALARY > 1.1 * O.SALARY))
             THEN SIGNAL SQLSTATE '75000' SET MESSAGE_TEXT='Salary increase>10%';
          END IF;
       END;
  • 例 9: 部品のレコードが更新される前に、以下の検査および (必要に応じて) アクションを実行するトリガーを作成します。
    • 手持ち数量が最大在庫量の 10% 未満になった場合は、ORDER 表に新しい注文レコードを配置し、その部品の品目数として最大在庫量から手持ち数量を引いた数を指定した出荷依頼書を発行します。
    このトリガーは、次の列と表に作用します。
    • PARTS 表の PARTNO、DESCRIPTION、ON_HAND、MAX_STOCKED、および PRICE 列
    • ORDER 表の PARTNO および PRICE 列
    ISSUE_SHIP_REQUEST は、追加部品の注文書を発注先に送り、注文書が発注先によって確認された後、ORDER 表から対応する行を削除するユーザー定義の SQL データ変更ストアード・プロシージャーです。
    CREATE TRIGGER REORDER
       BEFORE UPDATE OF ON_HAND, MAX_STOCKED ON PARTS
       REFERENCING NEW AS N
       FOR EACH ROW
       WHEN (N.ON_HAND < 0.10 * N.MAX_STOCKED)
       BEGIN
          INSERT INTO ORDERS VALUES (N.MAX_STOCKED - N.ON_HAND, N.PARTNO);
          CALL ISSUE_SHIP_REQUEST(N.MAX_STOCKED - N.ON_HAND, N.PARTNO);
       END;