• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 存储程序中的变量

    系统变量和用户定义的变量可以在存储程序中使用,就像它们可以在存储程序上下文之外使用一样。此外,存储的程序可以DECLARE用来定义局部变量,存储的例程(过程和函数)可以声明为采用在例程与其调用程序之间传递值的参数。

    • 声明局部变量,使用DECLARE的语句,如在第13.6.4.1,“局部变量声明语句”。
    • 可以使用该SET语句直接设置变量。请参见“变量分配的SET语法”。
    • 可以使用或通过打开游标并使用来将查询的结果检索到局部变量中。请参见“ SELECT ... INTO语句”和“游标”。SELECT ... INTO var_listFETCH ... 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, id INTO newname, xid
        FROM table1 WHERE xname = xname;
      SELECT newname;
    END;
    

    MySQL xnameSELECT语句中将其解释为对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;