ITスキル

Oracleエラー「ORA-04091」を解説。トリガー内で自テーブル向けDMLを書かない

Oracleエラー「ORA-04091」について、わかりやすく解説します。

ORA-04091とは

ORA-04091は、Oracleトリガーの実行時に発生するエラーです。
トリガーはテーブルへの各種操作(INSERT、UPDATE、DELETE)に連動して動くのが基本だと思います。

このような場合、トリガーエラーが発生するとテーブルに対するトランザクションが異常終了します。

「テーブルにデータがINSERTできない、なんでだろう…」と色々調べていたら、実はINSERT文自体に問題はなく、トリガーがエラーを吐いていたり ということがあり得ます。

エラーメッセージは「表XXXXXは変更しています。トリガー/関数は見ることができません」です。XXXXX部分にはテーブル名が入ります。
例によってちょっとわかりづらいですね。
「トリガー内で自分のテーブルを使っちゃだめよ」ということです。

エラーの原因

エラーの原因は、トリガーの処理内で自テーブルに対するDMLを実行しているからです。

トリガーの構文を確認してみてください。CREATE TRIGGER ~ON XXXXXのXXXXX文と同じテーブル名が、トリガー構文内のSELECT、INSERT、UPDATE、DELETE文に含まれていたら、ほぼそれが原因です。

このエラーは、BEFOREトリガーでもAFTERトリガーでも関係なく発生します。
AFTER~なら良い気もしますが、幻想です。

厄介なのは、トリガーコンパイル時にエラー検知できず、実行して初めて見つかること。加えて、トランザクションが完了できないことにより他のエラーを招く可能性もあり、肝心のエラー原因(ORA-04091)を見落としがちなことです。

解決方法

エラー原因にある通り、トリガー内で自分のテーブルに対する操作をしないようにすることです。

トリガーが実行中ということは、すなわちそのテーブルのトランザクションがまだ確定していない状態。テーブルデータの実体が確定していないということ。審議中です。

で、審議中のテーブルをDMLに使っちゃいけませんぜ という話。

代用手段は、他のテーブルを使ったり、トリガー対象データの新・旧の値を使うなどです。

それでもできないような場合は、トリガーではなくバッチプロシージャなどを使うべきと思います。

Commit完了後のしっかりしたデータをもとに料理した方が、処理も追いやすいです。

総評

コンパイル時点ではエラー扱いとならない というのがこのエラーの怖いところです。
気軽に作ったトリガーが、システムの中核処理を止めてしまったりということが容易に想像できます。

そもそも個人的にはトリガーの乱用は反対です。
せめてトリガー内でEXCEPTIONを拾ってくれるとありがたい。

お読みいただきありがとうございました。
記事内容はあくまで個人の経験、主観で書いていますので、細かい誤りなどありましたら教えていただけますと幸いです。

 

COMMENT

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください