【SQL】SELECTしたデータを1行ずつ読み込む方法について【カーソル】

たけのこ

こんにちは、たけのこです!

システム開発では、データベース操作は必須級の技術ですが、

その中でも今回は、カーソルという機能に絞って解説します。

こんな人にオススメ!
  • SELECT文で抽出したデータを1行ずつ読み取る方法を知りたい方
  • ストアドプロシージャでカーソルを利用したい方

カーソルはストアドプロシージャの花形とも言われています。

複雑なデータを扱う際にとても便利なので、使い方をマスターしておきましょう!

スポンサーリンク

カーソルとは?

カーソルとは、SELECT文などで抽出した結果を1行ずつ読み取ることのできる機能です。

基本的にストアドプロシージャで利用され、

  • 1行ずつ条件分けしてinsertしたい時
  • 複雑な条件でupdateしたい時

などに使われます。

カーソルを使用する流れについて

カーソルは他のSQL構文と違い、手順が多いので戸惑ってしまいそうですが、流れに沿って実装していけば案外簡単です。

カーソル利用の流れ
  1. カーソルを宣言
  2. カーソルオープン
  3. ループ文でカーソルのデータを1行ずつ読み取る
  4. データがなくなったら、カーソルをクローズ
  5. 宣言したカーソルを削除

実際にカーソルを利用したストアドプロシージャのスクリプトを見ながら、使い方を解説します!

ストアドプロシージャでのカーソルの利用

今回、以下3つのテーブルを用意して、MST_Usersにいくつかデータを登録しています。

また、実装していくストアドプロシージャの条件は以下の通りです。

  • MST_Usersのageが18以上の場合、adult_Usersに登録
  • MST_Usersのageが18未満の場合、kids_Usersに登録

カーソルの宣言

最初にカーソルを宣言します。カーソルはSELECTクエリを用いて、処理したいデータを指定します。

1DECLARE user_cursor CURSOR FOR
2SELECT
3    user_id,
4    name,
5    age,
6    remarks
7FROM
8    MST_Users;

継続ハンドラの設定

カーソルがすべての行を読み終えたときに、自動的に処理を終了するように継続ハンドラを設定します。

1DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;

「DECLARE」句でCONTINUE HANDLERハンドラを定義。

「NOT FOUND SET finished = 1;」でデータが見つからなくなったら、ループが終わるように設定しています!

カーソルの開始とデータの読み取り

1OPEN user_cursor;
2read_loop: LOOP
3    FETCH user_cursor INTO u_id, u_name, u_age, u_remarks;
4    IF finished = 1 THEN 
5        LEAVE read_loop;
6    END IF;
7    
8    IF u_age >= 18 THEN
9        INSERT INTO adult_Users (user_id, name, age, remarks) VALUES (u_id, u_name, u_age, u_remarks);
10    ELSE
11        INSERT INTO kids_Users (user_id, name, age, remarks) VALUES (u_id, u_name, u_age, u_remarks);
12    END IF;
13END LOOP;
14CLOSE user_cursor;

OPEN句で宣言したカーソルをオープンし、利用できる状態にします。

次に、「read_loop: LOOP」でループを開始し、「FETCH user_cursor INTO u_id, u_name, u_age, u_remarks;」で1行ずつ読み取ったデータを

  • u_id
  • u_name
  • u_age
  • u_remarks

の変数の中にそれぞれ代入します。

代入したら、後はIF文で条件分けして各テーブルにデータ登録を行なっています。

最後に、「CLOSE user_cursor;」でカーソルを閉じて終わりです!

ここまで解説したカーソルを利用したストアドプロシージャの全コードは以下の通りです。

1DELIMITER $$
2
3CREATE PROCEDURE InsertUsers()
4BEGIN
5  DECLARE finished INTEGER DEFAULT 0;
6  DECLARE u_id INT;
7  DECLARE u_name VARCHAR(100);
8  DECLARE u_age INT;
9  DECLARE u_remarks TEXT;
10  DECLARE user_cursor CURSOR FOR SELECT user_id, name, age, remarks FROM MST_Users;
11  DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
12
13  OPEN user_cursor;
14  
15  read_loop: LOOP
16    FETCH user_cursor INTO u_id, u_name, u_age, u_remarks;
17    IF finished = 1 THEN 
18      LEAVE read_loop;
19    END IF;
20    
21    IF u_age >= 18 THEN
22      INSERT INTO adult_Users (user_id, name, age, remarks) VALUES (u_id, u_name, u_age, u_remarks);
23    ELSE
24      INSERT INTO kids_Users (user_id, name, age, remarks) VALUES (u_id, u_name, u_age, u_remarks);
25    END IF;
26  END LOOP;
27  
28  CLOSE user_cursor;
29END$$
30
31DELIMITER ;
32

まとめ

ということで、今回はSQLのカーソル機能について紹介しました。

コードは長いですが、使いこなせるようになればデータ操作の幅が大きく広がります。

これからデータ操作のプロジェクトに参画する予定の人や、データ操作をすることの多い人はぜひ覚えていってください。

というわけで、今回はこの辺りで!

ありがとうございました!

スポンサーリンク
ABOUT ME
たけのこ
たけのこ
自由奔放エンジニア
現役でエンジニアをやっています! 開発現場で経験したコーディング実装例、実装アーキテクチャの解説などを記事に書き起こしています!
記事URLをコピーしました