トリガー生成時に発生するエラーの解決方法

このQ&Aのポイント
  • WindowsXPのOracle9i環境でビューを作成するためのトリガーを作成しました。しかし、トリガーを実行すると「ORA-04092:トリガーはCOMMITできません」というエラーが発生します。
  • トリガーの中にはCOMMIT文を含めることができないため、このエラーが発生します。トリガーの中にCOMMIT文を入れる必要がある場合は、別の方法を探す必要があります。
  • 解決方法としては、トリガーの中にCOMMIT文を入れる代わりに、トリガーの外側でCOMMIT文を実行することが挙げられます。トリガーの中では必要な処理を行った後に、トランザクションを保持したままトリガーを終了し、トリガーの外側でCOMMIT文を実行することでエラーを回避することができます。
回答を見る
  • ベストアンサー

トリガーにてビューを作成しようとすると・・

WindowsXPのOracle9i環境です。 以下のようなトリガーを作成しました。 create or replace trigger kan_trg after update or insert on t_kan declare begin execute immediate 'create or replace view V_test as select ・・ from t_kan with read only'; end; / その後、試しに「insert into t_kan ・・・」 と実行してみましたが、「ORA-04092:トリガーはCOMMITできません」が発生します。 色々調べましたがトリガーの中にCOMMIT文を入れることはできないようです。どのようにすれば解決するか、ご教示いただけませんでしょうか? 宜しくお願い致します。

  • Oracle
  • 回答数3
  • ありがとう数5

質問者が選んだベストアンサー

  • ベストアンサー
  • nora1962
  • ベストアンサー率60% (431/717)
回答No.3

うーん、あまり考えられませんね。 9iの環境で簡略して環境でやってみましたが、正常にSELECTできましたよ。

ryozyryozy
質問者

お礼

ご連絡遅くなりました。私の勘違いで上手くいけてました。 ありがとうございました。

その他の回答 (2)

  • nora1962
  • ベストアンサー率60% (431/717)
回答No.2

insert into したセッションとは別のセッションで検索しようとしていませんか。 AFTERトリガでもCOMMITしていないデータは別セッションからは検索できませんよ。

ryozyryozy
質問者

お礼

ご回答ありがとうございます! 同一セッションで検索してますし、commitもしております。 他に何か考えられることありますでしょうか?

  • nora1962
  • ベストアンサー率60% (431/717)
回答No.1

「create any view」権限を持ったユーザーで create or replace procedure kan_proc(str in varchar2) is PRAGMA AUTONOMOUS_TRANSACTION; -- ↑ 自律型トランザクション プラグマ begin execute immediate str; end; / create or replace trigger kan_trg after update or insert on t_kan begin kan_proc('create or replace view V_test as select * from t_kan with read only'); end; / 「create any view」権限はロール経由では無効になるので、DBA権限を 持ったユーザーでプロシージャを作っても実行時「権限不足」になるので 注意。

ryozyryozy
質問者

お礼

ご回答ありがとうございます! 「自律型トランザクション プラグマ」というのが調べても高度でよく理解できませんでしたが、とりあえずビューは作成できたようです。 ところが、t_kanテーブルにinsert文にてテストしてみましたが、トリガーにて「after」指定にもかかわらず、作成されたビューの中にはinsertしたレコードが入ってきませんでした。 それでは意味がないのですが、なぜなのでしょうか??

関連するQ&A

  • DDLトリガーの作成にて

    お世話になります。 oracleにDDLトリガーを作成したいのですが、エラーが出て作成出来ません。 AFTER DDL on DATABASEのAFTERのところで エラー内容:「ORA-04072: トリガー型が無効です」 が発生します。 試しに、AFTER insert にするとここの部分は通るのですが、作成したいのはCREATEやDROPの時に起動するDDLトリガーなのです。 ちなみに、AFTER create or drop としても同じエラーが発生します。 ネットやoracleのリファレンスも見ましたが今だ解決出来ないでおりますので、ぶしつけな質問なのですが、どこが悪いのか教えて戴きたいです。 -- 作成するトリガーは下記となります ------------------------------------- CREATE OR REPLACE TRIGGER SYS.AFTER_DDL_EVENT AFTER DDL on DATABASE WHEN (ora_sysevent not in ('AUDIT','TRUNCATE')) DECLARE VCW_MODULE varchar2(48) := null; NW_CNT number := 0; BEGIN insert into ログ格納テーブル ・・・ if ( ora_sysevent = 'CREATE' ) then ・・・ elsif ( ora_sysevent = 'DROP' ) then ・・・ end if; END; / です。CREATEやDROPが発生した時にログを残したいのです。 oracle8ではDDLトリガーは作成出来ないってことは無いですよねぇ・・・。 環境は、oracle8、windowsNTサーバー 以上、誰か教えて~

  • トリガーのエラー

    ORA-04098: トリガー'sss.ssss'が無効で妥当性再チェックに失敗しました。というようなエラーが出ます。 トリガー自体は下のような単純なものです。 このエラーは単純にトリガーの文法などのエラーでしょうか?それとも、ORACLE環境など他の原因なんでしょうか? よろしくお願いします。 ------------------------------------- CREATE or replace Trigger XInsert AFTER INSERT ON sTable FOR EACH ROW BEGIN INSERT INTO xxxxxx (s,a,b,c,d) values(seq_a.NEXTVAL ,:new.a ,:new.b ,:new.c ,:new.d ); END;

  • ORACLEのトリガーについて勉強しているのですが現在詰っています。

    ORACLEのトリガーについて勉強しているのですが現在詰っています。 トリガーの内容ですが、table1のレコードがUPDATEかINSERTかDELETEが 実行された時にtable2にそのレコードすべてをINSERTしたいのですが CREATE OR REPLACE TRIGGER test_trg After INSERT or UPDATE or DELETE on table1 for each row  BEGIN   if inserting then    insert into (?);   elsif updating then    insert into (?);   else    insert into (?);   end if;  END; tableを使ってログを残せるようにするためこのトリガーを作ろうとしています。 この様な感じになると思っているのですが、(?)の部分をどう書けばいいのか がよくわかりません。どうしても解らないので教えていただければ幸いです。 何卒よろしくお願いします。

  • トリガーにてUTL_FILEパッケージを使用しログ作成を行いたい

    いつもお世話になっております。 Oracle9i+WindowsXPの環境で、以下のようなトリガーをテーブル更新or挿入タイミングで起動させ、更新対象行をログのような形でUTL_FILEパッケージを使用してCSVファイルを作成しようとしておりますが、テーブルを更新してもエラーが発生します。 create or replace procedure kan_proc(aaa in number) is PRAGMA AUTONOMOUS_TRANSACTION; file UTL_FILE.FILE_TYPE; filename varchar2(10); BEGIN filename := 'aaa.csv'; file := UTL_FILE.FOPEN('FILE_PATH', filename, 'w'); UTL_FILE.PUT_LINE(file, aaa); ・ ・ END kan_exp; / create or replace trigger kan_trg after update or insert on t_kan each row aaa number begin if updating then select colA into aaa from t_kan where :new.colA = colA; kan_proc(aaa); else if inserting then ??? end; / エラーNo.はちょっと今はわかりませんが、必要であれば提示させていただきます。 全く自信がないのですが更新時上記のようなSQL文で更新対象行がとれるものなのでしょうか? また、ちょっと別問題ですが、挿入時のコードが思いつきませんが、何か良い方法はありますでしょうか? 申し訳ありませんがどなたかご教授いただけませんでしょうか? 宜しくお願い致します。

  • 続・トリガーの起動条件について質問です。

    先ほど書き込みしたものの回答が得られないので、 質問内容を少し変えます。 トリガーを作成する際に WHEN句に書き込める制限などはあるのでしょうか? 試しに CREATE OR REPLACE TRIGGER INS_01 AFTER INSERT ON A_TBL FOR EACH ROW WHEN(NEW.ID = (SELECT ・・・)) BEGIN ・・・・ END; / と書いたところ ORA-02251: ここでは副問合せは使用できません。 と怒られました。 また:NEWや:OLDの使えるはどの値を持ってくるのでしょうか? 自分はINSERT時には:NEWはVALUESの値、:OLDはNULL。 UPDATE時は:NEWはSETした値、:OLDはWHERE句で指定したレコードの値だと思っています。 間違いや補足ありましたら教えていただけると幸いです。 宜しくお願いします。

  • OracleのTrigger(トリガー)について

    いつもご親切にありがとうございます。 Oracleのトリガーについて教えてください。 テーブルA ----------------- 日付 date型 品名 char(15) 営業所 cahr(5) フラグ char(1) データをINSERTする際に、下記のように変更したいです。 (1)日付が2月且つ、営業所が00001の場合は99999に変更、 (2)日付が2月且つ、品名の後ろ5桁が00001の場合後ろ5桁だけを99999に変更 下記のようにトリガーを作成しているんですけど、 (2)をどのように入れたらよいでしょうか? CREATE OR REPLACE TRIGGER TRG_テーブルA BEFORE INSERT ON テーブルA REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW BEGIN IF ( to_char(:NEW.日付,'YYYYMM') = '201502' ) AND ( :NEW.営業所 = '00001' ) THEN :NEW.営業所 := '99999'; END IF; END; / よろしくお願いします。

  • トリガーの起動条件で悩んでいます。

    超初心者です。 うまく説明できないかも知れませんが助けて下さい。 うまく動作しない処理は、 [A_TBL]が更新時に履歴あり・なしにそれぞれトリガーを用意しているのですが、 履歴なしの場合は[A_TBL]がUPDATEされるだけなので、 『[A_TBL]がUPDATEされたタイミングで[B_TBL]もUPDATEする』 という起動条件にしています。 履歴ありの場合は[A_TBL]のデータをUPDATEで無効化(FLGを立てます)し、 その後、更新データをINSERTで登録しようと思っています。 そのためトリガーの起動条件を、 『[A_TBL]がINSERTされたタイミングで[B_TBL]のデータをUPDATEする』 としていますが、 [A_TBL]に新規登録時のトリガーの起動条件が、 『[A_TBL]にINSERTされたタイミングで[B_TBL]にもINSERTする』 としているので、 [A_TBL]にINSERTされると両方のトリガーが起動してしまい、 怒られました。 自分の作ったトリガーを書いておくので どのようにしたらよいのか教えていただけませんでしょうか? トリガーの書き方におかしな点があったらご指摘もお願い致します。 よろしくお願いしますm(_ _)m 新規登録のトリガー CREATE OR REPLACE TRIGGER INS_01 AFTER INSERT ON A_TBL FOR EACH ROW BEGIN INSERT INTO B_TBL( ID, 姓, 名, 住所, 本籍, 電話番号, 郵便番号 )VALUES( :NEW.ID, :NEW.姓, :NEW.名, :NEW.住所, :NEW.本籍, :NEW.電話番号, :NEW.郵便番号 ); END; / 更新のトリガー CREATE OR REPLACE TRIGGER UP_01 AFTER INSERT ON A_TBL FOR EACH ROW BEGIN UPDATE B_TBL SET 姓 = :NEW.姓, 名 = :NEW.名, 住所 = :NEW.住所, 本籍 = :NEW.本籍, 電話番号 = :NEW.電話番号, 郵便番号 = :NEW.郵便番号 WHERE ID = :NEW.ID ; END; /

  • トリガーについて

    このジャンルでお願いします。 次のようなテーブルで DROP TABLE IF EXISTS item; CREATE TABLE IF NOT EXISTS item ( id int(11) NOT NULL AUTO_INCREMENT, parent_id INT, name varchar(32) NOT NULL, level int NOT NULL, FOREIGN KEY (parent_id) REFERENCES item(id) ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO item (parent_id, name) VALUES (null, 'item1'); INSERT INTO item (parent_id, name) VALUES (1, 'item2'); INSERT INTO item (parent_id, name) VALUES (2, 'item3'); INSERT INTO item (parent_id, name) VALUES (3, 'item4'); INSERT INTO item (parent_id, name) VALUES (2, 'item5'); INSERT INTO item (parent_id, name) VALUES (null, 'item6'); INSERT INTO item (parent_id, name) VALUES (6, 'item7'); INSERT INTO item (parent_id, name) VALUES (null, 'item8'); DROP PROCEDURE IF EXISTS UPDATE_LEVEL; DELIMITER // CREATE PROCEDURE UPDATE_LEVEL() BEGIN DECLARE CNT INT; DECLARE LVL INT; SET LVL=1; UPDATE item SET level=0; UPDATE item SET level=LVL WHERE parent_id IS NULL; SELECT COUNT(*) INTO CNT FROM item WHERE level=LVL; WHILE CNT>0 DO UPDATE item INNER JOIN (SELECT id FROM item WHERE level=LVL) as temp ON parent_id=temp.id SET item.level=LVL+1; SET LVL=LVL+1; SELECT COUNT(*) INTO CNT FROM item WHERE level=LVL; END WHILE; END // DELIMITER ; DROP TRIGGER IF EXISTS TRG_INSERT_ITEM; DELIMITER // CREATE TRIGGER TRG_INSERT_ITEM AFTER INSERT ON item FOR EACH ROW BEGIN CALL UPDATE_LEVEL(); END; // DELIMITER ; itemテーブルにinsertした場合にトリガーでUPDATE_LEVEL()を実行するようにしているのですが、 実際に挿入すると、 >Can't update table 'item' in stored function/trigger because it is already used by statment which invoked this stored function/trigger . このようなエラーが出てしまいます・・・ UPDATE_LEVEL()にinsertらしき記述はないと思うのですが、 これはなぜこのようなエラーが出るのでしょうか?

    • ベストアンサー
    • MySQL
  • プロシージャとトリガー

    Aというテーブルのaカラムが更新されれば、Bテーブルの列の中でAテーブルの列id含む列(複数)のbカラムをFalseからTrueに変更されるような、トリガー と プロシージャを作りたいのです。 考えていたのは、プロシージャは、 CREATE FUNCTION update_edit_b() RETURNS OPAQUE AS ' BEGIN (複数列指定?) NEW.b := 't'; RETURN NEW; END; ' LANGUAGE 'plpgsql'; プロシージャで、Bテーブルの複数列を指定するにはどうしたら良いでしょうか? トリガーは CREATE TRIGGER trgger_a AFTER UPDATE OF a ON Table_a FOR EACH STATEMENT EXECUTE PROCEDURE update_edit_b ; こんな感じでしょうか?

  • ORACLE ログオントリガーで接続制限

    初心者です。失礼のないように努力いたしますのでご協力お願いいたします。 ログオントリガーを使用して接続者の制限をしたいのですが正常に動作しません。 CREATE OR REPLACE TRIGGER LOGON_TRG AFTER LOGON ON DATABASE DECLARE STR_SCHEMANAME VARCHAR2(20); STR_OSUSER VARCHAR2(20); STR_PROGRAM VARCHAR2(20); BEGIN SELECT USERNAME,OSUSER,PROGRAM INTO STR_SCHEMANAME,STR_OSUSER,STR_PROGRAM FROM V$SESSION WHERE audsid = USERENV('SESSIONID'); IF STR_SCHEMANAME = 'SCH1' AND STR_OSUSER = 'USER1' THEN INSERT INTO ALOG (SCHEMANAME,OSUSER,LOGIN_DAT,PROGRAM)VALUES(STR_SCHEMANAME,STR_OSUSER,TO_DATE(TO_CHAR(SYSDATE,'YYYY/MM/DD HH24:MI:SS'),'YYYY/MM/DD HH24:MI:SS'),STR_PROGRAM); COMMIT; RAISE_APPLICATION_ERROR(-20000, 'Can not login'); END IF; END LOGON_TRG; <説明> スキーマ='SCH1'にOSユーザー=’USER1’が接続してきたらALOGに情報を記録して接続しない。 このトリガーはSYSで登録しています。 <結果> スキーマ='SCH1'にOSユーザー=’USER1’で接続するとALOGに記録はするのですが、 エラーメッセージが表示されず正常に接続できてしまいます。 <質問> ○RAISE_APPLICATION_ERRORがなぜ正常に動作しないのかがわかりません。 ○RAISE_APPLICATION_ERRORに権限的なものが必要なのでしょうか? (いろいろと調べてみましたが特に権限での制限は見当たりませんでした) 何か要因に思い当たる方がいらっしゃいましたらご協力いただければと思います。 よろしくお願いいたします。