こんにちは!データベースエンジニアとして日々PostgreSQLと格闘している私ですが、今日は「PL/pgSQLのカーソル」という、ちょっと玄人っぽく聞こえるテーマについてお話ししたいと思います。
「カーソル」って聞くと難しそうですよね。でも、大丈夫。実は私たちの日常にある「ある行動」と全く同じ考え方なんです。
そもそも「カーソル」って何?
データベースからデータを取り出すとき、通常は `SELECT FROM …` のように一気に結果を受け取りますよね。でも、もしその結果が100万行もあったらどうでしょう? メモリがパンクしてしまいますし、何より人間が一度に処理するのは不可能です。
ここで登場するのが「カーソル」です。
これを「レストランの注文伝票」に例えてみましょう。
キッチン(データベース)から料理(データ)が出てくるとき、ホールスタッフ(カーソル)が伝票を片手に、「次は1番テーブルのハンバーグ、次は2番テーブルのパスタ…」と、一品ずつ丁寧にお客さんに運んでいく様子をイメージしてください。
全部一気にテーブルに叩きつけるのではなく、状況を見ながら「次の一皿」を運ぶ。これがカーソルの本質です。
—
カーソルの基本的な使い方
PL/pgSQLでカーソルを使うには、大きく分けて4つのステップがあります。おまじないだと思って見てみてください。
1. 宣言(準備をする)
まずは、「どのデータを扱うか」という伝票を準備します。
DECLARE
my_cursor CURSOR FOR SELECT name FROM users;
「これからユーザーの名前リストを取り扱うよ」という宣言です。まだ何も動いていません。
2. OPEN(伝票を開く)
さあ、いよいよ仕事開始です。
OPEN my_cursor;
これでデータベースに対して「さっきのリスト、準備して!」と合図を送ります。
3. FETCH(一品ずつ運ぶ)
ここが一番のポイント。`FETCH`を使って、データを一行ずつ取り出します。
FETCH my_cursor INTO user_name;
これで「次の一行」を`user_name`という変数に詰め込むことができます。
4. CLOSE(伝票を閉じる)
仕事が終わったら、忘れずに片付けましょう。
CLOSE my_cursor;
これでメモリも解放されてスッキリです。
—
ループで回すのが「実戦」のコツ
実際には、一行ずつFETCHしては処理する…という動作を、データがなくなるまで繰り返すことが多いです。そんな時は `LOOP` 文と組み合わせるのが定石です。
OPEN my_cursor;
LOOP
FETCH my_cursor INTO user_name;
— データがなくなったらループを抜ける(EXIT WHEN NOT FOUND)
EXIT WHEN NOT FOUND;
— ここで何かしらの処理をする
RAISE NOTICE ‘処理中のユーザー: %’, user_name;
END LOOP;
CLOSE my_cursor;
こうすることで、「100万行あっても、一気に読み込まずに安全に処理する」という、プロの現場でもよく使われる堅実なコードが書けるようになります。
—
最後のアドバイス
カーソルは便利ですが、「なんでもかんでもカーソルで回せばいい」というわけではありません。実は、SQLは「集合」で処理するのが一番速いように設計されています。
「どうしても一行ずつ順番に複雑な処理をしないといけない!」という時にこそ、このカーソルという秘密兵器を思い出してください。
最初は難しく感じるかもしれませんが、まずは小さなテーブルで試してみてくださいね。「おっ、一行ずつ取れてる!」という実感が湧いてくれば、もうあなたはPostgreSQLの扱いを一つマスターしたも同然です。
また次回の記事でも、現場の小ネタをシェアしていきますね。データベースライフを一緒に楽しみましょう!
コメント