カーソルを使用するには、カーソルを囲むための標準的なボイラープレートコードが必要です。
カーソルを使用してテーブルの値のセットごとにストアドプロシージャを呼び出すには、基本的に同じボイラープレートが必要です。 SELECT
渡したい値(一時テーブル、ベーステーブル、ビューなど、保存された関数の呼び出しを含めることができます)から取得し、それらの値を使用してプロシージャを呼び出します。
以下に、そのボイラープレートコードの構文的に有効な例を、各コンポーネントが実行していることを説明するコメントとともに記述しました。 「理由だけで」何かをするように頼まれるよりも嫌いなことはほとんどないので、すべてが(うまくいけば)説明されます。
複数の値を使用してプロシージャを呼び出すと述べたため、この例では2を使用します。
彼女が発生するイベントには、理由のために特定の順序があることに注意してください。変数を最初に宣言する必要があり、カーソルは継続ハンドラーの前に宣言する必要があり、ループはこれらすべてに続く必要があります。これは、ここではかなり極端な柔軟性がないという印象を与えますが、実際にはそうではありません。 BEGIN
内に追加のコードをネストすることで、順序をリセットできます。 ... END
プロシージャ本体内のブロック。たとえば、ループ内に2番目のカーソルが必要な場合は、ループ内、別のBEGIN
内で宣言するだけです。 ... END
。
DELIMITER $$
DROP PROCEDURE IF EXISTS `my_proc` $$
CREATE PROCEDURE `my_proc`(arg1 INT) -- 1 input argument; you might not need one
BEGIN
-- from http://stackoverflow.com/questions/35858541/call-a-stored-procedure-from-the-declare-statement-when-using-cursors-in-mysql
-- declare the program variables where we'll hold the values we're sending into the procedure;
-- declare as many of them as there are input arguments to the second procedure,
-- with appropriate data types.
DECLARE val1 INT DEFAULT NULL;
DECLARE val2 INT DEFAULT NULL;
-- we need a boolean variable to tell us when the cursor is out of data
DECLARE done TINYINT DEFAULT FALSE;
-- declare a cursor to select the desired columns from the desired source table1
-- the input argument (which you might or might not need) is used in this example for row selection
DECLARE cursor1 -- cursor1 is an arbitrary label, an identifier for the cursor
CURSOR FOR
SELECT t1.c1,
t1.c2
FROM table1 t1
WHERE c3 = arg1;
-- this fancy spacing is of course not required; all of this could go on the same line.
-- a cursor that runs out of data throws an exception; we need to catch this.
-- when the NOT FOUND condition fires, "done" -- which defaults to FALSE -- will be set to true,
-- and since this is a CONTINUE handler, execution continues with the next statement.
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- open the cursor
OPEN cursor1;
my_loop: -- loops have to have an arbitrary label; it's used to leave the loop
LOOP
-- read the values from the next row that is available in the cursor
FETCH NEXT FROM cursor1 INTO val1, val2;
IF done THEN -- this will be true when we are out of rows to read, so we go to the statement after END LOOP.
LEAVE my_loop;
ELSE -- val1 and val2 will be the next values from c1 and c2 in table t1,
-- so now we call the procedure with them for this "row"
CALL the_other_procedure(val1,val2);
-- maybe do more stuff here
END IF;
END LOOP;
-- execution continues here when LEAVE my_loop is encountered;
-- you might have more things you want to do here
END $$
DELIMITER ;