SQLServerのカーソル利用について
SQLServerとかでストアド使った処理でよくあるカーソル使った処理。
<よくあるカーソル利用時の処理パターン>
-- 0.カーソル取得用変数定義
DECLARE @c_key INT;
DECLARE @c_col1 NVARCHAR(50);
DECLARE @c_col2 INT;
DECLARE @c_col3 DATETIME2;
-- 1.カーソル定義
DECLARE cur1 CURSOR FOR SELECT key,col1,col2,col3 FROM tab1;
-- 2.カーソルOPEN
OPEN cur1;
-- 3.初回カーソルFETCH
FETCH NEXT FROM cur1 INTO @c_key,@c_col1,@c_col2,@c_col3;
-- 4.カーソルループ処理(取得結果なしで終了)
WHILE @@FETCH_STATUS = 0
BEGIN
-- @c_key,@c_col1,@c_col2,@c_col3とか使ってやりたい処理
-- 5.次の結果をフェッチする(内容は3と同じ)
FETCH NEXT FROM cur1 INTO @c_key,@c_col1,@c_col2,@c_col3;
END
-- 6.カーソルを閉じる
CLOSE cur1;
-- 7.解放
DEALLOCATE cur1;
だいたいこんな感じですが
いざ書こうと思ってももすぐ忘れる、書くのめんどくさい、特にフェッチする項目が多いときは超めんどくさい。
変更なんか入った日には。。
さらに今時のO/Rマッパとか糖衣構文とかに慣れ切った体ではほんとにつらい。
個人的に拒否反応が起こるところとしては
「0.カーソル取得用変数定義」
Oracleみたいに%ROWTYPEが使えればいいが、自分で定義しないといけない。
→いやいやレベル20%
「2.カーソルOPEN、3.初回カーソルFETCH」
読み込むのに手続きが多くてめんどくさい。
→いやいやレベル30%
「4.カーソルループ処理」
ここの「@FETCH_STATUS=0」っていうの毎回忘れるので調べるのめんどくさい。
→いやいやレベル35%
「5.次の結果をフェッチする」
3の初回カーソルと同じ内容をまた書かなければならない。いやすぎる。
→いやいやレベル55%
「6.カーソルを閉じる、7.解放」
まあ開いたら閉じるのが世の常なのでしょうがないケド。。開かなきゃ閉じなくてもいいのに。。
→いやいやレベル60%
ここまでは我慢の限界だとして、いざ変更が入ってカーソル取得項目が増えようもんなら
0の定義追加
1のカーソル定義変更
3のフェッチ項目追加
5のフェッチ項目追加
をやらなければならない
→いやいやレベル80%
自分がよく使うパターン
無限ループしないように気を付けるくらい。
(速度がどうのとか、リソースがこうのとか全く考えてません)
-- 1.処理用テーブル定義(カーソル定義に相当)
SELECT col1,col2,col3 INTO #w_tab1 FROM tab1;
-- 2.ワークテーブルなくなるまで順番に処理
WHILE EXISTS(SELECT * FROM #w_tab1)
BEGIN
DECLARE @c_key INT;
SET @c_key=select TOP 1 key from #w_tab1;
--処理で使いたい項目は上記と同様に#w_tab1から取得
-- 3.処理済データは削除(ここはWHILEの条件と合わせて更新でもなんでもよい)
DELETE FROM #w_tab1 WHERE key=@c_key;
END
ああ、すっきり。(自己満足)