Oracle开发9年,频繁使用存储过程。现转到mysql,使用存储过程还是不太习惯,语法差别比较大,而且没有深入去了解过mysql的存储过程语法。
现在公司有部分数据需要通过存储过程处理,只能硬着头皮上了。
1.循环
与oracle 用法基本一样,使用loop或者while
首先定义一个游标
DECLARE rs CURSOR FOR
SELECT
contract_id
FROM
data_sale_contract_delay
WHERE FLAG IS NULL or FLAG= '';
在游标定义后面要定义一个如果游标移动到最后一行数据后再次移动后处理的语句.
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1 ;
这个语句的含义是在fetch 不到内容时,将变量done 赋值为1.用来做跳出循环判断用.
此处与Oracle不同,Oracle会更简单,直接exit when v_cur%notfound;
就可以跳出循环.v_cur是游标的名字.
接下来打开游标,遍历:
OPEN rs;
FETCH NEXT FROM rs INTO v_contract_id;
WHILE (done<>1) DO
... -- 处理逻辑省略
FETCH NEXT FROM rs INTO v_contract_id;-- 处理完成后直接再从游标读取下一条数据,如果已是最后一条数据,再fetch时会出发上面的 CONTINUE HANDLER,将变量done 值改成1
END WHILE;
CLOSE rs;
2.循环无法正常退出问题
- 由于while中使用了select XX into XX from XXX的这种赋值语句在 select 的时候,没查到数据,导致出发handler将done修改为1,然后光标就会跳出循环。
- 或者多层循环嵌套时内循环出现将done修改为1的情况。
以上这两种情况,都是因为CONTINUE HANDLER把done更新造成的,如果遇到此类问题,需要在每次可能出现done被改变的地方处理完逻辑后增加set done=0;把变量值改一下,这样就可以继续执行了。
参考文章:
mysql游标实现时当内部查询有一次未查询到结果时就自动退出循环解决办法
MySQL 游标循环未完成就中止了