Forum Stats

  • 3,852,443 Users
  • 2,264,104 Discussions
  • 7,905,065 Comments

Discussions

PL/SQLのループでとにかくnot foundを無視してループさせたい。

859671
859671 Member Posts: 24
edited May 10, 2011 9:18PM in SQLとPL/SQL
お世話になっております。
データが5000件程度あるマスタテーブルをループさせながら一時表に書き込むプログラムを書いています。
こんな感じです。

begin
for i in ( select code, trdate from test1 where trdate=sysdate) loop

select bb into var_bb from test2 where code = i.code ; -- ①

insert into test3 ( code, bb) values ( i.code , var_bb ) ;

end loop

comit;
end ;
/

test2にtest1と同じコードが張っていない場合、no_date_found例外
でとまってしまいます。余り重要でないtest3テーブルなので、なくてもとりあえず全件まわしたいと考えています

この場合、さらっとした書き方は出来ないでしょうか?
① をカーソル宣言して、open , fetch , %notfoud属性を調べれば掛けますが、
もっとサラッと簡単に書ける方法がないか調べています。

よろしくお願いします。

Answers

  • 145973
    145973 Member Posts: 40
    edited May 10, 2011 1:04AM
    select bb into var_bb from test2 where code = i.code ; -- ①
    insert into test3 ( code, bb) values ( i.code , var_bb ) ;

    の代わりに、

    for j in (select bb from test2 where code = i.code) loop
    insert into test3 (code, bb) values ( i.code , j.bb ) ;
    end loop;

    で、いかがですか。
  • tmtsmic
    tmtsmic Member Posts: 120
    こんにちは。

    こんな感じでbegin と end;で括る手は使えませんか?
    ※動作確認はしていません

    begin

     for i in ( select code, trdate from test1 where trdate=sysdate) loop

      begin

       select bb into var_bb from test2 where code = i.code; --取得できない時は「exception1つ目」へ
       insert into test3 ( code, bb) values ( i.code , var_bb ); --insertに失敗したら「exception1つ目」へ

      exception

       --exception1つ目
       when NO_DATA_FOUND then
        --データがない時はスルー。

       when others then
        --エラーログを出力したりするとか
        --raise文なんか使う時もあったり。
        --ちなみにraise文で再度エラーを起こせば「exception2つ目」へ
        --処理を飛ばすことができる。

      end;

     end loop;

     commit;

    exception

     --exception2つ目
     when others then
      --ロールバックしたりとかいろいろ。

    end;
  • 859671
    859671 Member Posts: 24
    ありがとうございます。

    確かにこっちのほうが、スマートに書けそうですね。
    後はno_data_found対策にループを使うのが心理的にちょっと?
    という感じです。
  • 859671
    859671 Member Posts: 24
    ありがとうございます。

    begin - endをネストさせるやり方は全く知りませんでした。
    もう少し様子を見てどちらを使うか決めます。
  • 859671
    859671 Member Posts: 24
    結局select 部分はfor loop, insert部分はbegin-end;を作りました。
    これですっきりシンプルに記述できました。
  • 145973
    145973 Member Posts: 40
    心理的に抵抗があるとのことですが、

    暗黙カーソルを利用したカーソルFORループで、
    SELECT文の実行結果が0行の場合に、
    カーソルFORループ自体がスキップされるのは、
    想定通りの動作です。

    何もトリッキーなことをしているわけではありません
    ので、ご安心ください。
    結局select 部分はfor loop, insert部分はbegin-end;を作りました。
    これですっきりシンプルに記述できました。
    これは、2つの折衷案を取ったということでしょうか。

    そうだとしたら、私の提示した暗黙カーソルの方法では、
    INSERT文を実行する時点では、常に1つのレコードのみフェッチされています。
    このため、今回問題となっている例外は発生しません。
    例外処理のソースコード自体が不要である点を、念のため付記しておきます。
This discussion has been closed.