Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (日本語) » SQL Anywhere サーバ - SQL の使用法 » ストアド・プロシージャとトリガ » プロシージャ、トリガ、バッチの使用 » トリガの概要 » トリガに関する詳細情報

 

INSTEAD OF トリガ

INSTEAD OF トリガは、トリガが実行されるとトリガ元アクションはスキップされ、代わりに指定されたアクションが実行される点で BEFORE トリガや AFTER トリガと異なります。

INSTEAD OF トリガに固有の機能や制限を次に示します。

  • INSTEAD OF トリガは、特定のテーブルのトリガ・イベントごとに 1 つだけ指定できます。

  • INSTEAD OF トリガはテーブルまたはビューに定義できます。ただし、INSTEAD OF トリガはマテリアライズド・ビューには定義できません。マテリアライズド・ビューには INSERT 文、DELETE 文、UPDATE 文などの DML 操作を実行できないからです。

  • INSTEAD OF トリガを定義するときは、ORDER 句または WHEN 句は指定できません。

  • INSTEAD OF トリガは、UPDATE OF column-list トリガ・イベントには定義できません。CREATE TRIGGER 文を参照してください。

  • INSTEAD OF トリガが再帰を実行するかどうかは、トリガのターゲットがベース・テーブルであるか、ビューであるかで異なります。ビューの場合は再帰が発生しますが、ベース・テーブルの場合は発生しません。たとえば、INSTEAD OF トリガによって、トリガが定義されているベース・テーブルに対して DML 操作が実行されても、これらの操作でトリガは実行されません (BEFORE トリガや AFTER トリガを含む)。ターゲットがビューの場合は、ビューに対して実行された操作ですべてのトリガが実行されます。

  • テーブルに INSTEAD OF トリガが定義されている場合、ON EXISTING 句を含む INSERT 文をテーブルに対して実行できません。実行しようとすると、SQLE_INSTEAD_TRIGGER エラーが返されます。

  • WITH CHECK OPTION を指定して定義されているか、WITH CHECK OPTION を指定して定義されている別のビューにネストされており、INSTEAD OF INSERT トリガが定義されているビューに対して INSERT 文を実行できません。UPDATE 文と DELETE 文も同様です。実行しようとすると、SQLE_CHECK_TRIGGER_CONFLICT エラーが返されます。

  • 位置付け更新、位置付け削除、PUT 文、またはワイド挿入操作の結果として INSTEAD OF トリガが実行されると、SQLE_INSTEAD_TRIGGER_POSITIONED エラーが返されます。

INSTEAD OF トリガを使用した更新不可のビューの更新

INSTEAD OF トリガを使用すると、派生の関係で更新不可能なビューに対して INSERT 文、UPDATE 文、または DELETE 文を実行できます。トリガの本文で、対応する INSERT、UPDATE、DELETE 文を実行する意味を定義します。たとえば、次のビューを作成するとします。

CREATE VIEW V1 ( Surname, GivenName, State ) 
   AS SELECT DISTINCT Surname, GivenName, State 
        FROM Contacts;

DISTINCT キーワードによって、派生の関係で V1 が更新不可能になるので、V1 のローは削除できません。つまり、データベース・サーバでは、V1 からローを削除する意味を明確に特定できません。ただし、V1 への削除操作を実装する INSTEAD OF DELETE トリガを定義することはできます。たとえば、次のトリガでは、指定した Surname、GivenName、State のローが Contacts から削除されるときに、そのすべてのローが削除されます。

CREATE TRIGGER V1_Delete
  INSTEAD OF DELETE ON V1
  REFERENCING OLD AS old_row
  FOR EACH ROW
BEGIN
    DELETE FROM Contacts
      WHERE Surname = old_row.Surname
        AND GivenName = old_row.GivenName
        AND State = old_row.State
END;

V1_Delete トリガを定義すると、V1 からローを削除できます。さらに、V1 で INSERT 文と UPDATE 文を実行させる他の INSTEAD OF トリガを定義することもできます。

INSTEAD OF DELETE トリガが定義されたビューが別のビューにネストされている場合は、DELETE に対する更新可能性を確認するためにベース・テーブルのように処理されます。INSERT 操作と UPDATE 操作も同様です。前の例の続きで、別のビューを作成します。

CREATE VIEW V2 ( Surname, GivenName ) AS
  SELECT Surname, GivenName from V1;

V1_Delete トリガがなければ、V2 からローを削除することはできません。これは、派生の関係で V1 は更新不可能なので、V2 も更新不可能になるからです。しかし、V1 に INSTEAD OF DELETE トリガを定義すれば、V2 からローを削除できます。V2 からローが削除されるたびに V1 からローが削除され、V1_Delete トリガが実行されます。

INSTEAD OF トリガをネストされているビューに定義する場合は、これらのトリガが実行されるときに、意図しない影響がある可能性があるため、注意してください。意図する動作を明示的にするには、ネストされているビューを参照するすべてのビューに INSTEAD OF トリガを定義します。

次のトリガを V2 に定義し、DELETE 文の意図した動作を実行できます。

CREATE TRIGGER V2_Delete
  INSTEAD OF DELETE ON V2
  REFERENCING OLD AS old_row
  FOR EACH ROW
BEGIN
    DELETE FROM Contacts
      WHERE Surname = old_row.Surname
        AND GivenName = old_row.GivenName
END;

V2_Delete トリガによって、V1 に対する INSTEAD OF DELETE トリガが削除または変更されても、V2 に対する削除操作の動作は変わりません。