MySQL 8.4 发行说明
局部变量的作用域是声明它的 BEGIN ... END
块。可以在声明块嵌套的块中引用该变量,但声明具有相同名称的变量的块除外。
因为局部变量仅在存储程序执行期间处于作用域内,所以在存储程序中创建的预处理语句中不允许引用它们。预处理语句的作用域是当前会话,而不是存储程序,因此可以在程序结束后执行该语句,此时变量将不再处于作用域内。例如,SELECT ... INTO
不能用作预处理语句。此限制也适用于存储过程和函数参数。请参见 第 15.5.1 节“PREPARE 语句”。local_var
局部变量不应与表列具有相同的名称。如果 SQL 语句(例如 SELECT ... INTO
语句)包含对列的引用以及声明的具有相同名称的局部变量,则 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
列的值是多少。
类似地,以下过程中光标定义包含一个 SELECT
语句,该语句引用了 xname
。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;