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
列的值如何。
同样,以下过程中的游标定义包含指向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;
另请参见第 23.8 节“对存储程序的限制”。