这两天在做一些简单的存储过程,以前并未涉及过,现学现卖,碰到了不少问题,找了很多资料,也差不多解决了,废话不多说,希望用自己的失败经验给猿们提供点帮助。
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;
后面的数值根据自己的情况设置,表示想要递归的层级
总结:新熟悉一个东西都会有很大的难度,但是网上已经有很多前辈给的方法解决,大家一定要多动手多了解,可能我这里有说的错误的地方,希望多多理解,有问题就回复,我好更改,哈哈。