カーソルの完全な実行プロセスには、カーソルの宣言(DECLARE)、カーソルの開放(OPEN)、次の行の取得(FETCH)、およびカーソルの閉鎖(CLOSE)が含まれます。
カーソルの宣言(DECLARE)
カーソルを宣言する構文は以下のとおりです:
DECLARE cursor_name CURSOR FOR select_statement
この構文は、カーソルをSELECTステートメントに関連付けます(SELECTステートメントにはINTO句を含めることはできません)。SELECTステートメントは、カーソルがイテレーションする行を取得します。後で行を抽出する場合はFETCHステートメントを使用してください。その際、SELECTステートメントで取得する列数は、FETCHステートメントで指定する出力変数の数と一致している必要があります。
カーソルの宣言は、ハンドラーの宣言より前、変数や条件の宣言より後に記述する必要があります。1つのストアドプログラム内で複数のカーソルを宣言できますが、同一ブロック内で宣言されたカーソルは、それぞれ一意の名前を持たなければなりません。
ほとんどの場合、INFORMATION_SCHEMAテーブルを使用したカーソルを利用することで、SHOWステートメントなどと同等の情報を取得できます。
カーソルの開放(OPEN)
宣言済みのカーソルを開放する構文は以下のとおりです:
OPEN cursor_name
次の行の取得(FETCH)
指定したカーソル(必ず開放済みである必要があります)に関連付けられたSELECTステートメントの次の行を取得し、カーソルポインタを進める構文は以下のとおりです:
FETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...
行が存在する場合、取得した列は名前付けられた変数var_nameに格納されます。SELECTステートメントで取得する列数は、FETCHステートメントで指定する出力変数の数と一致している必要があります。
利用可能な行がなくなると、データなし状態が発生し、SQLSTATE値は"02000"になります。この状態を検出するには、例外ハンドラーを設定するか(NOT FOUND条件を設定する)必要があります。ただし、SELECTやその他のFETCHステートメントでも同様の状況が発生し、ハンドラーが実行される可能性があるため注意が必要です。どの操作がこの状況を引き起こしたかを区別する必要がある場合は、その操作を独自のBEGIN ENDブロック内に配置し、自身のハンドラーにのみ関連付けるようにしてください。
カーソルの閉鎖(CLOSE)
以前に開放したカーソルを閉鎖する構文は以下のとおりです:
CLOSE cursor_name
カーソルが開放されていない状態でこのステートメントを実行すると、エラーが発生します。明示的に閉鎖しない限り、カーソルは宣言されたBEGIN ENDブロックの実行終了時に自動的に閉鎖されます。
例
obclient> DELIMITER //
obclient> CREATE PROCEDURE hr_curdemo()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE x, y, z INT;
DECLARE cur1 CURSOR FOR SELECT id,salary FROM hr.emp;
DECLARE cur2 CURSOR FOR SELECT avg_sal FROM hr.avg;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
OPEN cur2;
read_loop: LOOP
FETCH cur1 INTO x, y;
FETCH cur2 INTO z;
IF done THEN
LEAVE read_loop;
END IF;
IF y < z THEN
INSERT INTO hr.low_sal VALUES (x,y);
ELSE
INSERT INTO hr.high_sal VALUES (x,z);
END IF;
END LOOP;
CLOSE cur1;
CLOSE cur2;
END //
Query OK, 0 rows affected