MySQL 8.0 リファレンスマニュアル


13.6.4.2 ローカル変数のスコープと解決

ローカル変数のスコープは、それが宣言されている BEGIN ... END ブロックです。 この変数は、同じ名前を持つ変数を宣言しているブロックを除き、宣言しているブロック内でネストされたブロック内で参照できます。

ローカル変数はストアドプログラムの実行中にのみスコープ内にあるので、これらの参照は、ストアドプログラム内で作成された準備済みステートメントでは許可されていません。 準備済みステートメントのスコープは現在のセッションであり、ストアドプログラムではないので、ステートメントはプログラムの終了後に実行でき、この時点で変数はスコープ内に存在しなくなります。 たとえば、SELECT ... INTO local_var は準備済みステートメントとして使用できません。 この制約は、ストアドプロシージャーおよびストアドファンクションのパラメータにも適用されます。 セクション13.5.1「PREPARE ステートメント」を参照してください。

ローカル変数にテーブルカラムと同じ名前を付けてはいけません。 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;

セクション25.8「ストアドプログラムの制約」も参照してください。


関連キーワード:  ステートメント, CREATE, TABLE, 変数, DROP, DECLARE, サブクエリー, xname, FUNCTION, カラム