• MySQL-5.7 游标及DECLARE


    1.cursor游标

    用来声明一个数据集
    游标的声明必须在变量和条件声明之后,在handler声明之前

    游标特性:

    • 不灵敏:服务器可以或不复制其结果
    • 只读:不可更新
    • 不可滚动的:只能在一个方向上遍历,不能跳过行

    实例:

    CREATE PROCEDURE curdemo()
    BEGIN
      DECLARE done INT DEFAULT FALSE;
      DECLARE a CHAR(16);
      DECLARE b,c INT;
      DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
      DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
      DECLARE CONTINUE HANDLER FOR NOT FOUND SET done= TRUE;
    
      OPEN cur1;
      OPEN cur2;read_loop:LOOP
        FETCH cur1 INTO a,b;
        FETCH cur2 INTO c;
        IF done THEN
          LEAVE read_loop;
        END IF;
        IF b<c THEN
          INSERT INTO test.t3 VALUES (a,b);
        ELSE
          INSERT INTO test.t3 VALUES (a,c);
        END IF;
      END LOOP;
    
      CLOSE cur1;
      CLOSE cur2;
    END;
    

    说明:

    • cursor close用来关闭之前打开的游标;
    • 如果关闭一个未打开的游标,则MySQL会报错;
    • 如果在存储过程和函数中未使用此语句关闭打开的游标,则游标会在声明的begin...end语句块执行之后自动关闭;

    cursor declare用来声明一个游标和指定游标对应的数据集合,通常数据集合是一个select语句。

    DECLARE cursor_name CURSOR FOR select_statement
    

    cursor fetch用来获取游标指定数据集的下一行数据并将各个字段值赋予后面的变量

    FETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...
    
    • 数据集中的字段需要和INTO语句中定义的变量一一对应
    • 数据集中的数据都fetch完之后,则返回NOT FOUND

    2.Declare condition语句

    命名特定的错误条件,而该特定错误可以在declare...handler中指定处理方法
    语法:

    DECLARE condition_name CONDITION FOR condition_value
    
    condition_value:mysql_error_code
      | SQLSTATE [VALUE] sqlstate_value
    

    说明:
    condition_value指定特定的错误条件,有以下两种形式:

    ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'v1 int default 5;
    
    • mysql_err_code表示MySQL error code的整数
    • sqlstate_value表示MySQL中用5位字符串表达的语句状态
    DECLARE CONTINUE HANDLER FOR 1051
    BEGIN
    -- body of handler
    END;
    
    declare no_such_table condition for 1051;
    declare continue handler for no_such_table
    begin
    --body of handler
    end;
    
    declare no_such_table condition for sqlstate '42S02'
    declare continue handler for no_such_table
    begin
    --body of handler
    end;
    

    3.Declare handler语句

    语法:

    DECLARE handler_action HANDLER
        FOR condition_value [, condition_value] ...
        statement
    
    handler_action:CONTINUE
      | EXIT
      | UNDO
    
    condition_value:mysql_error_code
      | SQLSTATE [VALUE] sqlstate_value
      | condition_name
      | SQLWARNING
      | NOT FOUND
      | SQLEXCEPTION
    
    • 用来声明一个handler来处理一个或多个特殊条件,当其中的某个条件满足时触发其中的SQL语句执行;
    • SQL可以使一个简单的语句,也可以是begin...end组成的多个语句;

    handler_action声明当执行完SQL语句之后应该做什么:

    • CONTINUE表示继续执行该存储过程或函数
    • EXIT表示退出声明此handler的begin...end语句块
    • UNDO参数已不支持

    condition_value的值有以下几种:

    • mysql_err_code表示MySQL error code的整数;
    • sqlstate_value表示MySQL中用5位字符串表达的语句状态;
    • condition_name表示之前在declare...condition语句中声明的名字;
    • SQLWARNING表示所有的警告信息,即sqlstate中01打头的所有错误;
    • NOT FOUND表示查完或查不到数据,即sqlstate中02打头的所有错误;
    • SQLEXCEPTION表示所有的错误信息

    实例:

    DECLARE CONTINUE HANDLER FOR 1051
      BEGIN
        -- body of handler
      END;
    
    DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
      BEGIN
        -- body of handler
      END;
    
    DECLARE CONTINUE HANDLER FOR SQLWARNING
      BEGIN
        -- body of handler
      END;
    
    DECLARE CONTINUE HANDLER FOR NOT FOUND
      BEGIN
        -- body of handler
      END;
    
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
      BEGIN
        -- body of handler
      END;
    

    当conditon发生但没有声明handler时,则存储过程和函数依照如下规则处理:

    • 发生SQLEXCEPTION错误,则执行exit退出;
    • 发生SQLWARNING警告,则执行continue继续执行;
    • 发生NOT FOUND情况,则执行continue继续执行;

    实例:

    mysql> CREATE TABLE test.t(s1 INT, PRIMARY KEY (s1));
    Query OK, 0 rows affected (0.35 sec)
    
    SQLSTATE '23000'表示主键冲突
    
    mysql> delimiter //
    mysql> CREATE PROCEDURE handlerdemo()
        -> BEGIN
        -> DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
        -> SET @x = 1;
        -> INSERT INTO test.t VALUES (1);
        -> SET @x = 2;
        -> INSERT INTO test.t VALUES (1);
        -> SET @x = 3;
        -> END;
        -> //
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> call handlerdemo();
        -> //
    Query OK, 0 rows affected (0.03 sec)
    
    mysql> delimiter ;
    mysql> select @x;
    +------+
    | @x   |
    +------+
    |    3 |
    +------+
    1 row in set (0.00 sec)
    

    实例:

    mysql> delimiter //
    mysql> create procedure curdemo()
        -> begin
        -> declare done int default false;
        -> declare a char(16);
        -> declare b,c int;
        -> declare cur1 cursor for select id,data from t1;
        -> declare cur2 cursor for select i from test.t2;
        -> declare continue handler for not found set done = true;
        -> open cur1;
        -> open cur2;
        -> read_loop:loop
        -> fetch cur1 into a,b;
        -> fetch cur2 into c;
        -> if done then
        -> leave read_loop;
        -> end if;
        -> if b<c then
        -> insert into test.t3 values(a,b);
        -> else
        -> insert into test.t3 values(a,c);
        -> end if;
        -> end loop;
        -> close cur1;
        -> close cur2;
        -> end//
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> delimiter ;
    
  • 相关阅读:
    正则表达式预:
    cookie 二:
    Javascript之运动框架2
    cookie预:
    Javascript之链式运动框架1
    基于Azure的软件部署和开发系列沙龙
    在Docker中安装.NET Core(使用命令行工具)
    Xshell 无法连接虚拟机中的ubuntu的问题
    springboot09-redis
    springboot08-jpa-mysql
  • 原文地址:https://www.cnblogs.com/tongxiaoda/p/8024508.html
Copyright © 2020-2023  润新知