MySQL 8.0 参考手册  / 第 13 章 SQL 语句  / 13.6 复合语句语法  / 13.6.4 存储程序中的变量  /  13.6.4.2 局部变量作用域和解析

13.6.4.2 局部变量作用域和解析

局部变量的范围 BEGIN ... END是声明它的块。可以在声明块内嵌套的块中引用变量,但声明同名变量的块除外。

因为局部变量仅在存储程序执行期间在范围内,所以在存储程序中创建的准备语句中不允许引用它们。准备好的语句范围是当前会话,而不是存储的程序,因此语句可以在程序结束后执行,此时变量将不再在范围内。例如, 不能用作准备语句。此限制也适用于存储过程和函数参数。请参阅 第 13.5.1 节,“PREPARE 语句”SELECT ... INTO 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;

MySQLxnameSELECT语句中解释为对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;

另见第 23.8 节,“存储程序的限制”