2020年6月8日月曜日

mysql(5.1) + カーソルloop使ったプログラムのテンプレ

たまに、ツールとしてデータベースプログラムを書くのですが、1から書くのではなく、いつもどこかの作成済みプログラムを流用しているので、流用も面倒くさくなり、テンプレ化することにしました。
他の人にも使ってもらえるよう、コメント多めです。

【概略】
データを取得して、繰り返しする処理のテンプレです。
データベースへの書き込み処理も考慮してトランザクションも記載してあります。

【コード】


-- プロシージャ入れ替え用のDROP
DROP PROCEDURE IF EXISTS PROCEDURENAME;
delimiter ///
CREATE DEFINER = `root`@`localhost` PROCEDURE `PROCEDURENAME`
 (IN param1 VARCHAR(10)
 ,IN param2 VARCHAR(10))
BEGIN
    -- Loop検知・保持する変数
    DECLARE done INT DEFAULT 0;
    -- 通常変数を記載する際にはカーソルの前に書く
    DECLARE local_aa VARCHAR(10);
    DECLARE local_bb VARCHAR(10);
    -- カーソル定義
    DECLARE l_cur CURSOR FOR select a ,b from xx; -- カーソル定義

-- データなしを検知するハンドラ
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
-- 例外を検知するハンドラ
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
    ROLLBACK;
    SET autocommit=1;
    SELECT 0 AS RESULT;
END;

-- メイン処理
-- オートコミットを切って、自立トランザクションにしています
    SET autocommit=0;
    START TRANSACTION;

-- カーソルを開く
    open l_cur;
-- 繰り返し処理
    REPEAT
-- 1件データ取得
        FETCH l_cur into local_aa , local_bb;
-- EOF判定
        IF NOT done THEN
            -- データ処理
            -- これを書いておくとコンソールにデバッグのように出力される
            SELECT now() AS CURRENT_DATETIME local_aa AS aa , local_bb AS bb;

            -- この例では別ストアドを呼ぶ
            call sub_procedure(param1,param2,local_aa,local_bb);
        END IF;

    UNTIL done END REPEAT;

-- 後片づけ
    close l_cur;

    COMMIT;
    SET autocommit=1;

-- 呼び出し元用に正常終了を返す    
    SELECT 1 AS RESULT;

end;
///
delimiter ;

0 件のコメント: