2016年5月15日日曜日

トリガーの検証

トリガーについての検証です。

ここでは、以下の言葉を、以下の意味で使用します。

・元テーブル(test):トリガーとなる動作を受けるテーブル
・ダミーテーブル(dummy_test):トリガー自体の動作を受けるテーブル

元テーブルにデータを入れようとすると、ダミーテーブルにデータを入れるトリガーを使って
動作検証しました。

■正常系
testテーブルにデータを入れたら、dummy_testにもデータが入るトリガーを作成。

・元テーブル作成
SQL> create table test(a number);

表が作成されました。

・ダミーテーブル作成
SQL> create table dummy_test(a number);

表が作成されました。

・ダミーテーブルにデータを入れるトリガー作成
SQL> create or replace trigger t_ins_dummy_test
  2  before insert on test
  3  for each row
  4  begin
  5  insert into dummy_test values(:new.a);
  6  end;
  7  /

トリガーが作成されました。

・トリガー実行前
SQL> select * from test;

レコードが選択されませんでした。

SQL> select * from dummy_test;

レコードが選択されませんでした。

・トリガー実行。
testテーブルにデータが入れる前に、ダミーテーブルにデータが入る
SQL> insert into test values(1);

1行が作成されました。

・トリガー実行後
SQL> select * from test;

         A
----------
         1

SQL> select * from dummy_test;

         A
----------
         1


■異常系
・トリガー実行前
SQL>  select * from dummy_test;
 select * from dummy_test

・わざとダミーテーブルを削除
SQL> drop table dummy_test purge;

表が削除されました。

・ダミーテーブルが無いので、トリガー失敗
SQL> insert into test values(1);
insert into test values(1)
            *
行1でエラーが発生しました。:
ORA-04098: トリガー'SYSTEM.T_INS_DUMMY_TEST'が無効で再検証に失敗しました

・トリガー実行後
SQL>  select * from dummy_test;
 select * from dummy_test

トリガーを使う上で注意しないといけないのが、
元テーブルと、ダミーテーブルにデータ入れる動作が、1トランザクションであるということです。
要するに、トリガーとなる動作と、トリガー自体の動作は1トランザクションであり、どちらかが
失敗するとトランザクションの処理自体がロールバックされます。
この場合は、ダミーテーブルを削除することで、わざとエラーを発生させましたが、それ以外の
エラーでダミーテーブルへの処理が失敗したとしても同じように、トランザクション自体が失敗します。

ということは、トリガーの仕組みを入れることで弱点を一つ作ってしまうことにもなるのです。
トリガー自体は便利な機能ですが、そういった仕組みを把握しておかないと、思わぬところでエラーを引き起こしてしまうことになるのです。


■トリガーが無い状態で元テーブルにデータを入れると?
・トリガー実行前
SQL> select * from test;

レコードが選択されませんでした。

SQL> select * from dummy_test;

レコードが選択されませんでした。

・トリガー無い状態で、元テーブルにデータを入れる
SQL> insert into test values(1);

1行が作成されました。

・トランザクション中にトリガー作成
SQL> create or replace trigger t_ins_dummy_test
  2  before insert on test
  3  for each row
  4  begin
  5  insert into dummy_test values(:new.a);
  6  end;
  7  /

トリガーが作成されました。

・トリガー実行後
SQL> select * from test;

         A
----------
         1

SQL> select * from dummy_test;

レコードが選択されませんでした。


元テーブルにデータを入れた後、ダミーテーブルにデータを入れるトリガーを作っても、
トリガーは動作しません。
トリガーを動作させたければ、元テーブルにトリガーとなる動作をさせる前に、トリガーを作っておく必要があります。

0 件のコメント:

コメントを投稿