カーソルってなに?
はじめまして。
「Zenn初めて使ってみた」さんまです。
黄金週間も近づいてきたのに、まだコタツもパッチも脱却できません!!
(とある若い社員の方にはパッチが通じなかった 悲)
まだまだ寒い日が続きますが、みなさんもお体には気を付けてください。
今回(初めてやけど)は、昔になんかで色々イジったような記憶があるものを呼び起こし、筆を執ってみました。(「そんなもん知っとるわ」って方はスルーでお願いします)
ではでは、タイトルの通り「カーソルってなに?」とは
かーそる1 | かーそる2 | かーそる3 |
---|---|---|
です。
いやいやいやいや、これじゃ話し終わってまうやん・・・
そうです。今回紹介するカーソルは「データベースにおけるカーソル」のことです。
それでは説明していきます。
カーソル(CURSOR)
普通はデータを更新する場合、UPDATE文を利用してWHERE句に条件を設定し、その条件に該当するデータを一括で更新します。
カーソルを利用した処理では、まずカーソル(最初に取り出すSELECT文)を定義し、抽出したデータに対してループ処理で1行ずつ条件を判定し、条件に応じてデータを更新することができます。
抽出されたレコードを1行ずつフェッチ(取得)して、複雑な処理をしたい場合に有効です。
カーソルを利用した処理の全体像は以下の通りです
- カーソルの宣言
- カーソルを開く
- データの取得
- ループ処理の実行
- カーソルを閉じる
フローチャート
カーソルを利用したフローチャートを描いてみました。
なんかあんま美しくないなー(普通に画像でよかったんじゃね)
⇒ 画像も用意してみたよ(後付けです)
カーソルを利用したフローチャートです(Zennで描いてみたよ)
頑張って描いたけど、なんか美しくないわー
画像はこちら
やっぱこっちの方がしっくりくるなー
カーソル(CURSOR)処理の実装
カーソル処理のコードはSQL Serverやoracle、PostgreSQL等で若干違うと思います(知らんけど)ので、ここでは詳しく記載しませんが、実際に実装する場合の手順は変わらないはずです。
カーソル処理の実装です
- カーソルの宣言
最初に、処理対象のデータ抽出するSELECT文を指定します。
ここではカーソル“csr”を定義すると同時にSELECT文を割り当てています。
DECLARE csr CURSOR FOR
SELECT col1, col2
FROM tbl1
まあ大体こんな感じです。
- カーソルを開く
次にカーソルを開きます。割り当てたSELECT文が実行されます。
OPEN csr
開けんと始まらんよ
- データの取得
データベースの分野では以下のような表現をします
- データを1行ずつ取得すること ⇒ FETCHする
- 「FETCH NEXT FROM カーソル名 INTO 変数リスト」 ⇒ 次の行のデータを取得し、変数へ
- 最初の1回目に限り ⇒ 1行目のデータを取得する
SELECT文が実行した結果セットからデータを1行取得し、
変数リスト(ここではcol1, col2という2つの変数)にデータを代入します。
変数リストに代入することで、条件分岐の判定などに利用できるようになります。
FETCH NEXT FROM csr INTO :col1, :col2
- ループ処理の実行
実際にやりたかった処理を記述します。
FETCH_STATUSはグローバル変数(明示的に定義しなくても自動的に定義されている変数)
結果
0:データが取り出せた
1:失敗した
2:取り出すデータがなかった
最後に実行したFETCH文の結果、ループ条件「:FETCH_STATUS = 0」は、
「データが取り出せた場合」となります。
ここにやりたかった処理をゴリゴリ書いていきましょう。
WHILE :FETCH_STATUS = 0
BEGIN
SET :col1 = :col1 + :col2
WHERE CURRENT OF csr
FETCH NEXT FROM csr
INTO :col1, :col2
END
今回はループをWHILEで記載してますが、FOR文とか回れば何でもOKっす。
- カーソルを閉じる
最後にカーソルを閉じます。
ループ処理が終了した後、カーソルを閉じて処理は終了します。
これをやらないと、例えば毎日定刻にこの処理を実行する際にカーソルがクローズされずオープンのままの場合、最初に書いた「OPEN csr」で「カーソルはすでに開かれています。」というような旨のエラー分が発生してしまいます。
そのため、処理が一旦終わったカーソルは必ずCLOSEする必要があります。
CLOSE csr
「開けたら、閉めんかい!!」 世の常ですよね。
カーソル利用時に注意すべきこと
なんか良いことずくめのように記載していますが、注意すべき点はあります。
以下は注意すべき点の例です
- 先述の通り、パフォーマンスが落ちる可能性がある。
- カーソルで取得したレコード毎に処理をしている間に、意図しない更新が入る可能性がある
(取得したレコードを処理をしている最中に、別の全く関係ない処理が平行に実行される) - 上述で排他の関係が理解できていないとデッドロックを引き起こす可能性がある
まとめ
いかがだったでしょうか。
カーソルについて説明してきましたが、実際あんまり使う機会は少ないと思います。
「おー、こんなこともできたんや!」的な感じで覚えていただければ幸いです。
ありがとうございました。(*◕ฺω◕ฺ)ノ
Discussion