MySQL上で大量のデータコンバートをしたいので、以前Microsoft SQL Serverを使っていた時のようにカーソルを使った処理ができないのか調べていました。そしたらば問題なくカーソルが使えるんですね。insertやupdateの一括処理でできれば一番速いのですが、1レコードずつループで処理しなければならない場面では、カーソルが便利です。
ストアドプロシージャとカーソルの使い方は、サイト『MySQLストアドプロシージャ入門』を参考にしたのですが、デリミタ(delimter)の宣言をしないと上手くいかなかったのでその部分の変更と、カーソルのfetchを以前MSSQLServerでやっていた書き方に近いように変更してみました。デリミタについては、書籍『現場で使える MySQL (DB Magazine SELECTION)』の解説で理解しました。
下記が、addressテーブルからidとnameを取り出して1行ずつ表示するストアドプロシージャのサンプルです。
delimiter // CREATE PROCEDURE sp_looptest() BEGIN -- ハンドラで利用する変数 v_done を宣言 DECLARE v_done INT DEFAULT 0; -- フェッチした値を格納する変数 DECLARE v_id INT; DECLARE v_name VARCHAR(255); -- カーソル宣言 DECLARE v_cur cursor FOR SELECT id,name FROM address LIMIT 10; -- SQLステートが02000の場合にv_doneを1にするハンドラを宣言 DECLARE continue handler FOR sqlstate '02000' SET v_done = 1; -- カーソルを開く OPEN v_cur; --最初のカーソルをfetch fetch v_cur INTO v_id,v_name; -- while関数で繰り返えさせる while v_done != 1 do -- メイン処理 SELECT v_id,v_name FROM dual; -- 次のカーソルをfetch fetch v_cur INTO v_id,v_name; END while; -- 最後にカーソルを閉じる close v_cur; END; // delimiter ;
MSSQLServerと大きく違うのは、continue handlerという変数が使えるということですね。イベントハンドラ的に、この条件の時はこうなる、という記述をすることができます。
これで大量データの処理が進みそうです。
コメント
[…] 先週に引き続き、MySQLでストアドプロシージャを作っていた訳ですが、ながーいinsert〜select文を追加したところ、文法エラーで動かなくなってしまいました。なぜだろうと思ってselect文 […]