QA@IT

[MySQL]カーソル内でレコードがスキップされる

5765 PV

現在、MySQL上でストアドプロシージャーを作成しています。
その中で、以下の様な処理を記述しています。

    -- カーソル変数宣言
    declare cursor1 cursor for
    select
        C_MST_SMP_SITE_ID,
        REGISTED_MONTH,
        PASS_MONTH
    from 
        `member_num`
    order by
        C_MST_SMP_SITE_ID,
        REGISTED_MONTH desc,
        PASS_MONTH asc;

    declare continue handler for not found set done = 1;

    -- カーソルオープン    
    open cursor1;
    cursor_loop: loop

        fetch registed_month_cursor
        into
            cursor_site_id,
            cursor_stard_month,
            cursor_path_month;

        -- 処理終了条件判断
        if done = 1 then
            leave cursor_loop;
        end if;

    -- 以下に処理を記述
    end loop cursor_loop;
    close cursor1;

上記のカーソルで利用しているSelect結果が150レコード程度存在するのですが、実際に処理されるのは120程度になってしまっています。
「not found」になるタイミングをデバッグし確認したところ、毎回同じレコード数で処理が終了してしまっている様です。
試しに、カーソルのループ処理から抜けられないのを理解した上で「if done = 1 then」の条件文を削除して実行したところ、ループから抜けることはできませんでしたが、150レコード全てに処理を行うことができました。
continue handlerの箇所を「SQLSTATE '02000'」に変更して試してみても同じでした。
単純にSelectした場合に取得できるにもかかわらず、カーソルに設定したところnot foundとなってしまう原因はなんでしょうか。
どなたかご教授いただけますでしょうか。

回答

処理の部分がどうなっているかも気にはなりますが、
現在の情報から言えることとしては、

not foundまでにループは何回まわっているのか確認する

実際に150件処理しているか計測してみてはどうか。
150回まわっているのにそうなのか(この場合は最後の更新情報がcommitされていないとか)、
本当に120回しか回っていないのか。

変数名の衝突が起きている可能性がある

fetchにつかっている cursor_site_id, cursor_stard_month, cursor_path_month
は宣言部分は省略されていますが、ローカル変数だと思いますが、
テーブルの列名と衝突することがあるそうです。

今回このケースに当てはまるかわかりませんが、selectで別名を定義するか、変数名をかえるかしてみてどうなるか確認してみてはどうでしょう。

参考: http://stackoverflow.com/questions/20814563/mysql-cursor-not-sorting-result-in-correct-order

編集 履歴 (0)
  • ご回答いただきありがとうございます。
    まず、処理件数のカウントですが、すでに実施しておりまして、正確に言うと112件処理したところで処理を抜けています。
    また、変数名についても、プロシージャーの先頭で宣言しており、テーブル内の列名とは重複しない様に先頭にcursor_と付けるようにしています。
    処理は前年同月比を取得する様な簡単なselect文とその結果計算した値を更新しています。
    -
  • そうですか。さすがにソートは関係ないと思いたいので、処理中のselectによってなにかロックされてしまっているんですかね(当て推量ですが)。もし処理中に更新対象のテーブルを参照しているのであれば、対象テーブルのコピーを作成してそのテーブルで 前年同月比を計算するようにしてみてはどうでしょう?。 -
  • ちなみに、処理が無い場合(質問に載せてくれたようなコード)では150回ループするんですよね?ちょっとすぐには思い当たらなさそうです。
    テーブルの定義(列の型)と変数の型が掲載可能なら掲載しておくと良いと思います。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。