• ベストアンサー

PLSQlでのロールバック

以下の様な処理をしたいのですがうまくいきません。 ・カーソルc_infoで取得した人数分、処理を行いたい。 ・ある1人が異常終了した場合は、その人の処理を全てロールバック  した後、次の人に進む。 begin for r_info in c_info loop begin 処理A  処理B  処理C exception  rollback; end; end loop exception end; こういう風に組んだのですが、 ある一人が処理Cで異常終了した時、その人の処理A,処理B がコミットされてしまっています。 どのようにすればよいでしょうか? ご教授ください。

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

  • ベストアンサー
  • lv4u
  • ベストアンサー率27% (1862/6715)
回答No.4

>>セーブポイントを設けてこのように既にやってみましたが 結果は同じでした。 何でしょうね?トランザクション処理対象外のDDL文が処理A-Cに含まれてはいないですよね? あとは、消去法ってことで、処理AーCの処理をすこしずつ減らし、raiseで例外を発生させて、どこまでだとrollbackされて、どこを過ぎるとcommitされてしまうか?って絞り込んでゆくのがいいかもしれません。 declare USER_ERR_TEST exception; begin ... if (エラー発生させたいデータ?) then raise USER_ERR_TEST;

-Rena-
質問者

お礼

有難うございます。 そのようにやってみます。 後、exception の中なのですが when e_user_exxecption then しかなく、 when others then がありませんでした。 これも影響しているのでしょうか? 下であります とかいてしまいすいません

その他の回答 (3)

  • PED02744
  • ベストアンサー率40% (157/390)
回答No.3

処理A/B/Cの各々の中でcommit; が書かれていない限り、 そんな事は起こらないとおもうんですけど。。。 処理A/処理Bの各々がもしプロシージャになっているのなら、 最後でcommit;が入っていないか確認してみてください。

-Rena-
質問者

補足

有難うございます。 処理A,B,Cはプロシージャです。 それぞれの中で、APIをコールしているのですが、コミット文は ありませんでした。

  • lv4u
  • ベストアンサー率27% (1862/6715)
回答No.2

以下のように、SAVEPOINTを使ってみたらどうでしょう? begin for r_info in c_info loop begin SAVEPOINT my_point; -- この時点に戻れるように保存 処理A  処理B  処理C exception ROLLBACK TO my_point; -- 直前のSAVEPOINTに戻る end; end loop exception end;

-Rena-
質問者

お礼

有難うございます。 セーブポイントを設けてこのように既にやってみましたが 結果は同じでした。

  • olsen_w
  • ベストアンサー率50% (2/4)
回答No.1

PL/SQLは長いことやってないのでうろ覚えですが WHEN OTHERS THENっていらないんでしたっけ? これがないと例外に飛ばないような気がするのですが… exception WHEN OTHERS THEN   rollback; end;

-Rena-
質問者

お礼

有難うございます。 WHEN OTHERS THEN は書いています。 例で漏れてしまいました。すいません。

関連するQ&A

  • PLSQLで

    PLSQL(Oracle9.i)で以下のことをしようとしています。 しかし、コンパイルは通るがステップ実行すると固まります。 -- 宣言部 TYPE REC_A IS RECORD( a NUMBER, b NUMBER, c NUMBER, d NUMBER, e NUMBER, f NUMBER, g NUMBER, ); TYPE B_TBL IS TABLE OF REC_A INDEX BY BINARY_INTEGER; TYPE C_TBL IS TABLE OF B_TBL INDEX BY BINARY_INTEGER; D_TBL C_TBL; -- 関数部 FOR i IN 1..3 LOOP  FOR J IN 1..3 LOOP   D_TBL(I)(J).a := 1;   D_TBL(I)(J).b := 2;   D_TBL(I)(J).c := 3;   D_TBL(I)(J).d := 4;   D_TBL(I)(J).e := 5;   D_TBL(I)(J).f := 6;   D_TBL(I)(J).g := 7;  END LOOP; END LOOP; なにぶんまだPLSQLの勉強始めて1ヶ月満たないもので、分からないことをどう伝えればいいのかも分からない状況です。 処理的には、D_TBL(I)(J)に値をいろいろセットし集計をとりCSVにはきだす処理です。 これだけでは分からないかもしれませんが、よろしくお願いします。

  • PLSQLについて

    いつもお世話になります。 オラクル初心者です。 宜しくお願い致します。 下記の様な、for~loopで、 tmpM商品単価(主キーなし)と言う一時表テーブルから M商品単価(主キーは「品番」)へインサートをする際、 tmpM商品単価には、「品番」フィールドにダブった品番 がある為、単価実行日を降順に並べ替え古い行は、 where not exists(~)で、インサートされない様に考えました。 しかし、下記構文では、コミットされる前だからなのか、 ダブった品番の行もインサートされようとされ、エラー となってしまいます。 どなたかご親切な方、ご教授下さいます様、 宜しくお願い致します。      記 create or replace procedure dbInsSyouhinmaster ( out_val out pls_integer ) as cursor c_1 is select 品番,商品分類,売上単価,単価実行日,登録日時,登録者 from tmpM商品単価 a where not exists(select * from M商品単価 b where trim(a.品番) = trim(b.品番)) order by 単価実行日 DESC; begin out_val:=0; for r_emp in c_1 loop if c_1%FOUND then INSERT INTO M商品単価 (品番,商品分類,売上単価,単価実行日,登録日時,登録者) VALUES(r_emp.品番,r_emp.商品分類,r_emp.売上単価,r_emp.単価実行日, r_emp.登録日時,r_emp.登録者) ; end if; out_val := out_val + 1; end loop; end;

  • 障害回復(ロールバックとロールフォワード)について

      t0  t1  t2   t3   t4   t5        |           | A s---e   |           |         |           | B s-------------e        |         |           | C  s------------------------|         |           | D       |   s----e    |         |           | E       |    s---------| ※t2はチェックポイント、t5は障害発生 ロールバックとロールフォワードについて教えてください。 (1)BとEについてロールフォワードによる回復が必要とのことですが、障害発生前にトランザクションが終了しており、コミットされているはずなのに、なぜロールフォワードが必要なのでしょうか? (2)Aはチェックポイント前に処理が完了しているため、回復処理は不要とのことですが、BとEが必要でAが不要の違いわかりません。 よろしくお願いします。

  • PLSQLの識別子エラー

    下記PLSQLを実行した時に(sqlplus上で、@XXXX.SQLと実行) WCOUNT :=WCOUNT + 1; エラー PLS-00201: 識別子WCOUNTを宣言してください のエラーがでます 宣言をしているのですがわからず、お助けください また、他にもこのエラーを処置したあとに問題と なりそうな箇所があれば指摘お願いします -やろうとしてること (1)テーブルA を、男子を出席順に読み込んでその読み込んだ順番に 1から番号をふり、テーブルBへ新規追加する (2)テーブルAからテーブルBに新規追加していない女子を、出席順に読み込んで 1から番号をふり、テーブルBへ新規追加する (3)テーブルBのKEYは順番のみ (4)テーブルBのINSERT分は、今後機能追加する予定なのでNOT IN使用する -組んだPL/SQL(2つのINSETを1つのファイルに記述しています) DECLARE WCOUNT number; CURSOR カーソル IS SELECT 出席番号,名前,成績 FROM テーブルA  ORDER BY 出席番号; BEGIN FOR r IN カーソル LOOP INSERT INTO テーブルB (r.順番, r.名前,r.出席番号) VALUES (WCOUNT,r.名前); COMMIT; WCOUNT :=WCOUNT + 1; END LOO; / END; DECLARE CURSOR カーソル IS SELECT 出席番号,名前,成績 FROM テーブルA A WHERE A.出席番号 NOT IN (SELECT B.出席番号 FROM テーブルB B) ORDER BY 出席番号; BEGIN FOR r IN カーソル LOOP INSERT INTO テーブルB (順番, 名前) VALUES (WCOUNT,r.名前); COMMIT; WCOUNT :=WCOUNT + 1; END LOOP; / END;

  • LOOP処理について

    条件に当てはまる値を10件SELECTし、 INSERTしたいのですが試せる環境がなく確認できない状態です。 もしテーブルを全件みて該当データがない場合も処理終了と したいのですが下記のような書き方でよいのでしょうか? どなたかご助言いただけないでしょうか?お願いします。 BEGIN WHILE (10=i) LOOP SELECT A INTO AA FROM TBL_A WHERE A = "xxx" INSERT INTO TBL_B (A_ID)VALUES(AA) EXIT WHEN (10=i) ; END LOOP; DBMS_OUTPUT.PUT_LINE('呼び出されます'); END;

  • Verilogで動的なモジュールを作る方法

    Verilogで動的なモジュールを作る方法 たとえば、どのような周波数であっても 1秒のウェイトをする回路を作りたいと思っています。 試験的に、 `define time (1) //1S `define tCK (20) //周期20nS module wait( input iCLOCK, input inRESET, output reg oWAITEND); localparam = loop_end (1/(`time * 1000000000))/`tCK; reg [31 : 0] loop; always@(posedge iCLOCK or negedge inRESET)begin if(inRESET == 1'b0)begin loop <= 32'h00000000; end else begin if(loop < loop_end)begin loop <= loop + 32'h00000001; oWAITEND <= 1'b0; end else begin oWAITEND <= 1'b0; loop <= loop; end end end //always endmodule というものを作って、defineの値(このdefineは別ヘッダファイルからincludeしてやりました)を変えてやれば目的の周波数で動き、目的のウェイト作るモジュールををソース自体を変えずに得られると思いましたが、 シミュレーションではうまくいったものの、QuartusIIではうまく論理合成されませんでした。 もし、他に方法がありましたら教えていただけないでしょうか? よろしくおねがいします。

  • pascalにおけるwhile文の条件について

    「cがA,B,Cのどれかの場合はwhile文の内容を繰り返す」というプログラムは while c in ['A','B','C'] do begin ~ end; と書けますが、「cがA,B,Cのどれかで無い場合はwhile文の内容を繰り返す」というプログラムはどのように書けばよいのでしょうか。私は while not c in ['A','B','C'] do begin ~ end; だと思ったのですが、エラーが発生したのでどうやら違うようです。 わかる人がいれば教えてください。よろしくお願いします。

  • トランザクション

    データベースのトランザクションで Aというデータがあるとき begin から始まって end で終了ですが その間に read(A) write(A:A*100) という処理を行ったとき 実際にA*100が書き込まれるのは end したときなのか write したときなのか どちらですか?

  • select into句のトランザクションについて

    お世話になってます。 sqlについて質問です。 ddlを発行するとトランザクションは暗黙的にコミットされると思いますが、 select into #temptable ・・・ のように、select into 句で一時テーブルを作成した場合、トランザクションはどうなるのでしょうか? また、以下のように一時テーブルと普通のテーブルで挙動は変わりますか? begin transaction select into #temptable from A ← ここでコミットされてしまう? …(1) select into temptable from A ← ここでコミットされてしまう? …(2) rollback transaction 以上、よろしくお願いいたします。

  • ORACLE PRO*CからPLSQL(パッケージ)を使用した場合のトランザクション処理について

    ORACLE PRO*CからPLSQL(パッケージ)を使用した場合のトランザクション処理について教えて下さい。 ORACLE PRO*CからPLSQL(パッケージ)を呼び出して います。PLSQLの中でコミット・ロールバックせずにPRO*C側で制御したいのですが。PLSQL(パッケージ) 内で別のPLSQLを呼出したり、BEGIN-ENDを多様すると PLSQL内で自動的にコミットが発生している様に思わ れます。何か方法はないものでしょうか。 御存知の方、御教示をお願いします。

専門家に質問してみよう