MySQL 8.3 Release Notes
局部变量的作用域是声明它的 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 将 xname 在 SELECT 语句中解释为对 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;