• ベストアンサー

トリガーにて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文で更新対象行がとれるものなのでしょうか? また、ちょっと別問題ですが、挿入時のコードが思いつきませんが、何か良い方法はありますでしょうか? 申し訳ありませんがどなたかご教授いただけませんでしょうか? 宜しくお願い致します。

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

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

  • ベストアンサー
回答No.2

ログへの出力は、トランザクション不成立の場合でも記録して良いんですか? 当初、自律型トランザクションを書いているくらいなので、トランザクションの成否にかかわらず、 挿入/更新の行為があった場合、記録するのが目的のような気がしますけど、AFTERトリガだし・・ 極端なケースですが、トランザクションがなんらかのエラーでロールバックの場合でもUTL_FILEで出力した分はそのまま、 但し、エラーを引き起こす場所が、AFTERトリガの前だと、エラー該当レコードに関する記録はされずに終わる。 という微妙なログのような気がします。

ryozyryozy
質問者

お礼

コメントありがとうございます! >トランザクション不成立の場合でも記録して良いんですか? 不成立の場合は記録したくないです。。 >当初、自律型トランザクションを書いているくらいなので、トランザク ションの成否にかかわらず、 挿入/更新の行為があった場合、記録するのが目的のような気がしますけど、AFTERトリガだし・・ 自律型トランザクションは正直よくわからず書きました。以前の本サイトの質問にて、同様にトリガーを作成してテーブル更新時ビュー作成しようとして上手くいかず、自律型トランザクションを教えていただきました。 どのようにすればトランザクション成立の場合のみ記録できるのでしょうか? よろしければご教授いただけませんでしょうか?宜しくお願いします。

その他の回答 (2)

回答No.3

SQL単文でなくトランザクションの成否を要素とするなら、ROWレベルトリガでファイル出力は無理があります。 ログの出力先をオラクル上のテーブルとし、事後にファイル出力する形態にした方が無難かと思いますよ。 なお、自律型トランザクションは、トランザクションが独立してしまい、本体トランザクションの成否に関わらず、 動作してしまいます、今回の場合は、使ってはなりません。

ryozyryozy
質問者

お礼

ありがとうございます。 もしよろしければ、サンプルコードなどご提示いただけませんでしょうか?

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.1

・:NEW.ColAに更新後の値が入っていると分かっているのに、なぜ改めてテーブルを検索しているのですか? ・inserting/updatingともに更新後の値しか記録する必要がないなら、insertingとupdatingで場合わけをする必要がありません。 ・'w'では、毎回上書きされて、結局1行しか記録されません。

ryozyryozy
質問者

お礼

ご回答ありがとうございます! すいません。なんか完全に勘違いしてました。 create or replace trigger kan_trg after update or insert on t_kan each row aaa number file UTL_FILE.FILE_TYPE; filename varchar2(10); BEGIN filename := 'aaa.csv'; file := UTL_FILE.FOPEN('FILE_PATH', filename, 'a'); UTL_FILE.PUT_LINE(file, :new.colA); ・ ・ end; / てな感じでよろしいんでしょうか? 明日動作確認してみます。 ありがとうございました。

関連するQ&A

  • UTL_FILEパッケージについて

    UTL_FILEパッケージを使用してPL/SQLよりテキスト出力したいのですが上手くいきません。 まずsysdbaにて「create directory aaa as 'd:\'」にてディレクトリを作成しました。 次に以下のようにプロシージャを作成しました。 create procedure kan_exp( fir IN varchar2, filename IN varchar2) is file UTL_FILE.FILE_TYPE; CURSOR tk01_kan_c IS select aaa,bbb from tableCCC begin file := UTL_FILE.FOPEN(dir, filename, 'w'); UTL_FILE.PUT_LINE(file, 'TEST'); UTL_FILE.NEW_LINE(file); for kanrec in tk01_kan_c loop UTL_FILE.PUT_LINE(file, 'TEST'); end loop; END kan_exp; / それを以下のように呼び出しましたが、 execute kan_exp('UTL_FILE_DIR', 'aaa.csv'); 「ORA-29280:無効なディレクトリパスです。」エラーが発生します。 色々と調べてユーザに権限が必要かと思い、「grant read on directory to User」としましたが、ユーザーまたはロール'User'は存在しませんと出てきます。※もちろんUserは存在します。 なにか足りないものがあるのでしょうか? ご教示いただけますでしょうか?宜しくお願いします。

  • UTL_FILEエラー?

    Oracle10g(リンクをはっています) Winxp http://oshiete1.goo.ne.jp/kotaeru.php3?q=995849 を参考にして以下のようなプロシージャを作成しました。 CREATE OR REPLACE PROCEDURE test.Test_Convrt IS BEGIN DECLARE c1 number; c2 number; data1 varchar2(100) := null; data2 varchar2(100) := null; File_Handle UTL_FILE.FILE_TYPE; Read_Line VARCHAR2(1023); BEGIN File_Handle := utl_file.fopen('C:\temp', 'test.csv', 'r'); LOOP BEGIN UTL_FILE.GET_LINE(File_Handle, Read_line); -- カンマ位置 c1 := instr(Read_line,',',1,1); c2 := instr(Read_line,',',1,2); -- 列データ data1 := ltrim(substr(Read_line,1 ,c1-1)); data2 := ltrim(substr(Read_line,c1+1,c2-c1-1)); -- update update test.tbl1 set col1= data2 where col1= data1; commit; exception when no_data_found then exit; END; END LOOP; UTL_FILE.FCLOSE(File_Handle); END; END ; コンパイルは通るのですが、いざ実行しようとすると、 行1でエラーが発生しました。 : ORA-29280:invalid directory path ORA-06512 at "SYS.UTL_FILE", line 33 ORA-06512 at "SYS.UTL_FILE", line 436 ORA-06512 at "test.TEST_CONVRT", line 11 ORA-06512 at line 1 と表示されました。 http://oshiete1.goo.ne.jp/kotaeru.php3?q=1338675 も見てみたのですが、初心者なので、いまひとつ理解できません。 SYS.UTL_FILEを参照できていないということはなんとなく、わかりました。 どのようにすれば解決できるでしょうか? また、開発初心者なので、参考になるサイトが知りたいです。 どなたか、よろしくお願いします。

  • UTL_FILE_DIRについて

    お世話になっております。 PL/SQLのファイル出力を行おうとUTL_FILE_DIRを組んだのですがファイルが更新されません。 エラーも検出されないのでどうしたものかと悩んでおります。 ソースは一番最後に記載します。 現状のやった作業に関しては ・初期化パラメータにUTL_FILE_DIR = * selectで確認済み ・テキストファイルの確認  ソースに記載してる通りの所に存在している。(権限もフルコン) oracleのバージョンは9iです。 よろしくお願いします。 set serveroutput on; DECLARE -- ファイルハンドラ vHandle UTL_FILE.FILE_TYPE;   vDirname      VARCHAR2(250);   vFilename      VARCHAR2(250); vOutput VARCHAR2(32767); error_code       NUMBER(5); error_message VARCHAR2(2048); BEGIN vDirname := 'c:'; vFilename := 'test.txt'; vHandle := UTL_FILE.FOPEN(vDirname, vFilename, 'w'); vOutput := ファイル出力です'; UTL_FILE.PUT_LINE(vHandle, vOutput); UTL_FILE.FCLOSE(vHandle); EXCEPTION WHEN OTHERS THEN error_code := sqlcode; error_message := sqlerrm; dbms_output.put_line('エラーコード:' || error_code); dbms_output.put_line('エラーメッセージ:' || error_message); END; / 上記実行するとエラー無しで正常終了しますがテキストファイルは更新されていません。

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

    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文を入れることはできないようです。どのようにすれば解決するか、ご教示いただけませんでしょうか? 宜しくお願い致します。

  • PLSQLでファイルに書き込みをしたいけど出来ない。。

    ☆ とっても、初心者です。 本日、初めてのPLSQLプルグラムを書いてみました。 下記のプログラムがそうなのですが、SQL*Plusを起動し、 START XXXXXX (←作成したSQL文の名前) と書いて実行して見ましたが、エラーは出ないのですが、私の希望では、[test.ddl]ファイルにsakurakoっと出力されていて欲しいのですが、なんにも更新されていません。。。 LOG:プロシージャが作成されました。 LOG:エラーはありません。 何か方法がまずいのでしょうか? あぁぁ、、何方かよきアドバイスをお願い致します。 ===================================== CREATE OR REPLACE PROCEDURE Create_US_Company IS CURSOR WORK_LINE IS SELECT * FROM TEST.US_COMPANY; TYPE FILE_TYPE IS RECORD (ID BINARY_INTEGER); FILE_HANDLE UTL_FILE.FILE_TYPE := UTL_FILE.FOPEN('D:\tmp,'test.ddl','w'); STR VARCHAR2(200); BEGIN STR := 'SAKURAKO'; UTL_FILE.PUT_LINE ( FILE_HANDLE, STR); UTL_FILE.FCLOSE (FILE_HANDLE); END Create_US_Company; ===================================== ☆

  • CSVファイルを読み込んでテーブルの更新

    こんばんは。 oracle9iでPL/SQLを使用して、CSVファイルを 読み込んで、テーブルの更新を行いたいと 思っています。 CSVファイル、テーブル共に最初の2つがキー項目です。 ■CSVファイル 001, 111, 10000, 20000 002, 222, 30000, 40000 ・・・・・ ・・・・・ 009, 999, 55555, 55555 ■テーブル 001, 111, 99999, 99999 002, 222, 99999, 99999 ・・・・・ ・・・・・ 009, 999, 99999, 99999 ■テーブル(処理後) 001, 111, 10000, 20000 002, 222, 30000, 40000 ・・・・・ ・・・・・ 009, 999, 55555, 55555 わかったのは、CSVファイルを行単位で読み込む所までです。 DECLARE   File_Handle UTL_FILE.FILETYPE; Read_Line VARCHAR2(1023); BEGIN File_Handle := UTL.FILE.FOPEN('dir', 'file', 'r'); BEGIN LOOP UTL.FILE.GETLINE(File_Handle, Read_line); END LOOP; END; UTL.FILE.FCLOSE(File_Handle); END; 1行を読み込んだのはいいけど、この後がよくわかりません。テーブルを更新する所とあわせて、ご教示ください。

  • 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サーバー 以上、誰か教えて~

  • プロシージャの実行方法

    テキストファイル(test.txt)から文字列を一行ずつ読み込んでDBMS_OUTPUTで表示を最後の行まで繰り返すプロシージャを作りたいのですが、プロシージャ制作までは出来るのですがプロシージャの実行が出来ません。 原因が理解できないのですが返答をお願いします。 create or replace procedure TXT_R as FH UTL_FILE.FILE_TYPE; V_LINE VARCHAR2(32767); BEGIN FH := UTL_FILE.FOPEN('DATA_PUMP_DIR','test.txt','R'); LOOP UTL_FILE.GET_LINE(FH,V_LINE); DBMS_OUTPUT.PUT_LINE(V_LINE); END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN UTL_FILE.FCLOSE(FH); END TXT_R; ここまでプロシージャです。 そしてネットで調べた結果引数が無い時は書かなくていいと書かれていたのですが、 exec TXT_R; で実行すると ORA-00900: SQL文が無効です。 となってしまいます。

  • PL/SQLのプロシージャが動かない

    テキストファイル(test.txt)から文字列を一行ずつ読み込んでDBMS_OUTPUTで表示を最後の行まで繰り返すプロシージャを作りたいのですが、declareで実行する時は何の問題も出ないのにプロシージャを作ろうとするとエラーが発生します。 原因が理解できないのですが返答をお願いします。 create or replase procedure TXT_R as FH UTL_FILE.FILE_TYPE; V_LINE VARCHAR2(32767); BEGIN FH := UTL_FILE.FOPEN('DATA_PUMP_DIR','test.txt','R'); LOOP UTL_FILE.GET_LINE(FH,V_LINE); DBMS_OUTPUT.PUT_LINE(V_LINE); END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN UTL_FILE.FCLOSE(FH); END; 実行すると ORA-00905: キーワードがありません。 のエラ-が出ます

  • ファイルへの書き込みができない

    ファイルへの書き込みができない 実行時エラーは表示されないのですが、ファイルへ出力されません。 コードは以下のようにしています。 よろしくお願いします。 declare FILE_HANDLE utl_file.file_type; STR varchar2(1023); begin -- 書き込みモードでファイルオープン FILE_HANDLE := UTL_FILE.FOPEN('c:\tmp','test.txt','W'); STR := 'test'; -- ファイルへ出力 UTL_FILE.PUT(FILE_HANDLE,STR); -- ファイルのクローズ -- UTL_FILE.FCLOSE(FILE_HANDLE); exception when others then dbms_output.put_line('その他エラー'); end; /