13.6.4.2 局部变量的范围和解决方案

局部变量的范围是在其内声明的开始...结束块。可以在嵌套在声明块中的块中引用该变量,但那些声明了具有相同名称的变量的块除外。

因为局部变量仅在存储程序执行期间才是作用域,所以在存储程序内创建的准备好的语句中不允许引用它们。准备好的语句作用域是当前会话,而不是存储的程序,因此该语句可以在程序结束后执行,此时变量将不再在作用域内。例如,SELECT ... INTO local_var不能用作预备语句。此限制也适用于存储过程和函数参数。参见第 13.5.1 节“ PREPARE 语句”

局部变量的名称不应与 table 列的名称相同。如果一个 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()时,newname变量将返回值'bob'而不管table1.xname列的值如何。

同样,以下过程中的游标定义包含指向xnameSELECT语句。 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;

另请参见第 23.8 节“对存储程序的限制”