2019独角兽企业重金招聘Python工程师标准>>>
我们在使用储存过程中使用游标遍历数据的时候的基本写法如下:
create procedure proc_test() sql security invoker
begin
declare p_id varchar(32);
declare done tinyint default false;
declare c_cur cursor for select id from user;
declare continue handler for not found set done = true;
open c_cur;
fetch c_cur into p_id;
while !done do
... #程序逻辑
fetch c_cur into p_id;
end while;
close c_cur;
end;
正常情况这么写是没问题的,可是如果你在while里面的要是有select语句的话就有问题了。如果说你的处理逻辑是这样的:
while !done do
select * from user_role r where r.user_id = p_id;
fetch c_cur into p_id;
end while;
那么当你的select * from user_role r where r.user_id = p_id;找不到数据的时候,declare continue handler for not found set done = true;这句就会执行,有done = true,所以循环体会提前跳出。通过测试得出,declare continue handler for not found set done = true 是对全局的select有效的,只要有一条select语句返回空,那么就是触发该语句。
解决方法就是确保while里面的select永远不会返回空
select * from user_role r where r.user_id = p_id;
#改成下面这样
select col1, col2, ... from
(select col1, col2, ... from user_role r where r.user_id = p_id
union all
select '' col1, '' col2, ...) t
这样的话就可以保证select肯定不是空集合。