MYSQL存储过程常见操作误区 - 游标(CURSOR) - 函数,过程调用 - 递归操作

这两天在做一些简单的存储过程,以前并未涉及过,现学现卖,碰到了不少问题,找了很多资料,也差不多解决了,废话不多说,希望用自己的失败经验给猿们提供点帮助。

  1. select into 导致游标处理未全部完成

    #一般来讲,我们会在某个过程(带有游标或其他循环操作)开始之前定义一个处理完毕的标识

    DECLARE done INT DEFAULT 0;

    #设置游标信息 (以查询 a 表 id 为实例) 

    DECLARE a_id INT DEFAULT 0; 
    DECLARE b_id INT DEFAULT 0;

    DECLARE cur CURSOR FOR (
      SELECT ` id`  FROM `a_table`;
    );

    #然而一般我们也会在出现错误或者其他情况下重置done的值,如下:

    #出现异常(SQLSTATE 02000 | NOT FOUND)
    DECLARE CONTINUE HANDLER for SQLSTATE '02000' SET done = 1;

    #然后开始游标

    OPEN cur;
    #获取第一层游标
    FETCH cur INTO a_id;

    #开始循环处理(While)

    WHILE (done = 0) DO

      #查询关联信息(这句在某些情况下会出现错误,导致游标结束)
      SELECT `id` INTO b_id from `b_table` WHERE `a_id` = a_id;

      #获取下一层游标,并继续循环
      FETCH cur INTO o_model_name;

    #结束循环处理
    END WHILE;

    #结束游标
  CLOSE cur;

  废话说了这么多,写了个简单的例子,简单的说说会出现问题的原因,正常来说,当b_table中不存在a_id对应的ID值时,将返回null,但由于DECLARE CONTINUE HANDLER for SQLSTATE '02000' SET done = 1;当出现查询为null的情况时,将会重置done为1,从而不在执行后面的游标,解决方案如下:

  SELECT `id` INTO b_id from `b_table` WHERE `a_id` = a_id;

  更改为

  SET b_id = (SELECT `id` FROM `b_table` WHERE `a_id` = a_id);

  后续逻辑可直接判断b_id的值

    IF b_id != '' THEN

      #处理逻辑

    END IF;

  2. function(函数) 与 PROCEDURE(过程)的不同调用方法

    function 采用  SELECT 调用,一般会返回返回值,所以最好先定义一个变量用于储存返回值(如果需要),如带参数可直接对应赋值参数即可。

    DECLARE a_result VARCHAR(100) DEFAULT '';

    SELECT function_A([param_1,param_2]) INTO a_result;

    procedure 采用 CALL 调用,没有返回值,主要处理逻辑,可传参数,特别注意的是:请留意 IN ,OUT ,INOUT三种模式,具体区别百度一下,讲的比我清楚。

    DECLARE param_1 INT DEFAULT 0;

    CALL procedure_A(param_1);


  3. 递归操作

    说实话刚开始使用递归是真把我难到了,网上也没有准确的操作方法,慢慢摸索才理清楚,这里也不出例子了,其实就是结合function(函数) 与 PROCEDURE(过程)就能完美的呈现递归操作,这里强调一点,当递归操作时,一般会报

    ERROR 1456 (HY000): Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine

    等错误,那是因为默认情况下是不允许使用递归操作的,这里需要在需要递归操作前生命一个系统变量:
    
    SET @@max_sp_recursion_depth = 100;
    
    后面的数值根据自己的情况设置,表示想要递归的层级


    总结:新熟悉一个东西都会有很大的难度,但是网上已经有很多前辈给的方法解决,大家一定要多动手多了解,可能我这里有说的错误的地方,希望多多理解,有问题就回复,我好更改,哈哈。

 

猜你喜欢

转载自www.cnblogs.com/abnermouke/p/9146830.html