存储程序中的变量
系统变量和用户定义的变量可以在存储程序中使用,就像它们可以在存储程序上下文之外使用一样。此外,存储的程序可以DECLARE
用来定义局部变量,存储的例程(过程和函数)可以声明为采用在例程与其调用程序之间传递值的参数。
- 声明局部变量,使用
DECLARE
的语句,如在第13.6.4.1,“局部变量声明语句”。 - 可以使用该
SET
语句直接设置变量。请参见“变量分配的SET语法”。 - 可以使用或通过打开游标并使用来将查询的结果检索到局部变量中。请参见“ SELECT ... INTO语句”和“游标”。
SELECT ... INTO var_list
FETCH ... INTO var_list
有关局部变量范围以及MySQL如何解析歧义名称的信息,请参见“局部变量范围和解析度”。
不允许将值分配DEFAULT
给存储过程或函数参数或存储程序局部变量(例如,使用语句)。在MySQL 8.0中,这会导致语法错误。SET var_name= DEFAULT
\r\n
局部变量DECLARE语句
DECLARE var_name [, var_name] ... type [DEFAULT value]
该语句在存储的程序中声明局部变量。要提供变量的默认值,请包含一个DEFAULT
子句。该值可以指定为表达式;它不必是常数。如果DEFAULT
缺少该子句,则初始值为NULL
。
就数据类型和溢出检查而言,将局部变量视为已存储的例程参数。请参见“ CREATE PROCEDURE和CREATE FUNCTION语句”。
变量声明必须出现在游标或处理程序声明之前。
局部变量名称不区分大小写。允许的字符和引用规则与其他标识符相同,如“架构对象名称”中所述。
局部变量的范围是BEGIN ... END
在其内声明的块。可以在声明块内嵌套的块中引用该变量,但那些声明了相同名称的变量的块除外。
局部变量的范围和解决方案
局部变量的范围是BEGIN ... END
在其内声明的块。可以在声明块内嵌套的块中引用该变量,但那些声明了相同名称的变量的块除外。
由于局部变量仅在存储程序执行期间才在范围内,因此在存储程序内创建的准备好的语句中不允许引用它们。准备的语句作用域是当前会话,而不是存储的程序,因此该语句可以在程序结束后执行,此时变量将不再在作用域内。例如,不能用作预备语句。此限制也适用于存储过程和函数参数。请参见“ 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, idINTO newname,xid FROM table1WHERE 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 TINYINTDEFAULT 0;DECLARE cur1CURSOR FOR SELECT xname, idFROM table1;DECLARE CONTINUE HANDLER FOR NOTFOUND SET done = 1;OPEN cur1; read_loop:LOOP FETCH FROM cur1INTO newname,xid ;IF doneTHEN LEAVE read_loop;END IF ;SELECT newname;END LOOP ;CLOSE cur1;END ;