ローカル変数のスコープは、それが宣言されている BEGIN ... END
ブロックです。この変数は、同じ名前を持つ変数を宣言しているブロックを除き、宣言しているブロック内でネストされたブロック内で参照できます。
ローカル変数はストアドプログラムの実行中にのみスコープ内にあるので、これらの参照は、ストアドプログラム内で作成された準備済みステートメントでは許可されていません。準備済みステートメントのスコープは現在のセッションであり、ストアドプログラムではないので、ステートメントはプログラムの終了後に実行でき、この時点で変数はスコープ内に存在しなくなります。たとえば、SELECT ... INTO
は準備済みステートメントとして使用できません。この制約は、ストアドプロシージャーおよびストアドファンクションのパラメータにも適用されます。セクション13.5.1「PREPARE 構文」を参照してください。
local_var
ローカル変数にテーブルカラムと同じ名前を付けてはいけません。SELECT ... INTO
ステートメントなどの SQL ステートメントに、カラムおよび同じ名前を持つ宣言されたローカル変数への参照が含まれている場合、MySQL は現在、その参照を変数の名前として解釈します。次のプロシージャー定義を考えてみます。
CREATE PROCEDURE sp1 (x VARCHAR(5))
BEGIN
DECLARE xname VARCHAR(5) DEFAULT 'bob';
DECLARE newname VARCHAR(5);
DECLARE xid INT;
SELECT xname, id INTO newname, xid
FROM table1 WHERE xname = xname;
SELECT newname;
END;
MySQL は、SELECT
ステートメント内の xname
を、xname
カラムではなく xname
変数への参照として解釈します。その結果、プロシージャー sp1()
が呼び出されると、table1.xname
カラムの値には関係なく、newname
変数は値 'bob'
を返します。
同様に、次のプロシージャー内のカーソル定義には、xname
を参照する SELECT
ステートメントが含まれています。MySQL はこれをカラム参照ではなく、その名前の変数への参照として解釈します。
CREATE PROCEDURE sp2 (x VARCHAR(5))
BEGIN
DECLARE xname VARCHAR(5) DEFAULT 'bob';
DECLARE newname VARCHAR(5);
DECLARE xid INT;
DECLARE done TINYINT DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT xname, id FROM table1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
read_loop: LOOP
FETCH FROM cur1 INTO newname, xid;
IF done THEN LEAVE read_loop; END IF;
SELECT newname;
END LOOP;
CLOSE cur1;
END;
セクションD.1「ストアドプログラムの制約」も参照してください。