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;