MySQL 8.4 Release Notes
15.6.4.2 局部变量范围和解析
局部变量的作用域是其在BEGIN ... END
块中声明的那个块。该变量可以在嵌套在声明块中的块中引用,除非这些块中声明了同名的变量。
由于局部变量仅在存储程序执行期间有效,因此它们不能在存储程序内创建的预准备语句中引用。预准备语句的作用域是当前会话,而不是存储程序,所以语句可能在程序结束后执行,这时变量将不再有效。例如,SELECT ... INTO
不能作为预准备语句使用。这一限制也适用于存储程序和函数参数。请参阅第15.5.1节,“PREPARE Statement”。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;
请参见Section 27.8
,“存储程序限制”。