跳到主要内容

存储程序的变量

在存储程序中可以使用系统变量和用户定义变量,存储程序可以使用 DECLARE 来定义局部变量,存储例程(过程和函数)可以声明参数,以在例程及其调用者之间传递值。

定义局部变量

使用 DECLARE 语句定义局部变量。局部变量可以在声明的时候指定默认值或者使用 SET 语句赋值。

定义存储程序中的局部变量时,DECLARE 语句通过 DEFAULT 子句为变量提供默认值。该默认值可以指定为表达式,而且不一定是常量。如果缺少 DEFAULT 子句,则初始值为 NULL。语法如下:

DECLARE var_name [, var_name] ... data_type [DEFAULT value]

其中,data_type 支持 SQL 数据类型。此外,PL 还兼容如下数据类型:

  • INT2(内部转换为 SMALLINT

  • INT4(内部转换为 INT

  • LONG(内部转换为 MEDIUMTEXT

不允许将 DEFAULT 值分配给存储过程或函数的参数和局部变量(例如,使用 SET var_name=DEFAULT 语句),这将导致语法报错。

使用 SELECT INTO 或使用打开游标的 FETCH INTO 语句可以将查询结果检索到局部变量中。

变量声明必须出现在游标或异常处理程序声明之前。局部变量名不区分大小写。允许的字符和引用规则与其他标识符相同。

局部变量作用范围和解析

有关局部变量的作用范围以及如何解析不明确名称的信息。

局部变量的作用范围是它所被声明的 BEGIN END 块中。该变量可以在声明块中的嵌套块中被引用,但不包括具有相同变量名称的块。

由于局部变量仅在存储程序执行期间有效,因此在存储程序内创建的 Prepared 语句中不允许引用这些局部变量。Prepared 语句的作用域是当前会话,而不是存储程序,因此该语句可以在程序结束后执行,此时变量将不会存在于作用域中。例如,SELECT ... INTO local_var 不能用作 Prepared 语句。此限制也适用于存储过程和函数参数。

信息

局部变量不应与表的列名称相同。如果 SQL 语句,例如 SELECT INTO 语句,包含对列的引用的同时具有相同名称的已声明的局部变量,数据库将该引用解析为变量的名称。

如下示例中,seekdb 将 SELECT 语句中的 vname 解析为对 vname 变量的引用,而不是对 vname 列的引用。因此,当调用存储过程 proc1() 时,无论 tbl1.vname 的值是多少,newname 变量都会返回值"seekdb"。

DELIMITER //

CREATE PROCEDURE proc1 (x VARCHAR(10))
BEGIN
DECLARE vname VARCHAR(10) DEFAULT 'seekdb';
DECLARE newname VARCHAR(10);
DECLARE xid INT;

SELECT vname, id INTO newname, xid
FROM tbl1 WHERE vname = vname;
SELECT newname;
END //
Query OK, 0 rows affected

类似地,以下示例的存储过程中的游标定义包含的 SELECT 语句引用了 vname。数据库将其解析为对该名称对应变量的引用,而不是列引用。

 CREATE PROCEDURE proc2 (x VARCHAR(10))
BEGIN
DECLARE vname VARCHAR(10) DEFAULT 'seekdb';
DECLARE newname VARCHAR(10);
DECLARE xid INT;
DECLARE done TINYINT DEFAULT 1;
DECLARE curdo CURSOR FOR SELECT vname, id FROM tbl1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 0;

OPEN curdo;
readlable1: LOOP
FETCH FROM curdo INTO newname, xid;
IF done THEN LEAVE readlable1; END IF;
SELECT newname;
END LOOP;
CLOSE curdo;
END //
Query OK, 0 rows affected