mysql游标提前退出(详细说明,完整用例,结果)

目录

问题:

原因:

问题复现:

解法一:

解法二:

解法三:

解法四: 


问题:

游标中, 如果 select 没有记录,游标提前退出(即使游标没有遍历完也会退出)

原因:

declare continue handler for not found set done = true 是对全局的select有效的,只要有一条select语句返回空,那么就是触发该语句。

问题复现:

例 :如 select 没有数据的时候,就会执行:

declare continue handler for not found set done = true;  done = true,所以循环体会提前跳出。

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 = 1;
  
  open c_cur;
    fetch c_cur into p_id;
    while !done do
        select a  into  b from user_role r where r.user_id = p_id;
    fetch c_cur into p_id;
    end while;
  close c_cur;
end;

 

解法一:

循环结束后加上set done = 0 ;完整版例子:

delimiter $$
create procedure test()
declare tmp_ia integer;
declare tmp_ib integer;
declare done integer default 0;
#将所有变量存在cur_test 中
declare cur_test cursor for
select
        sum(a.ia),
        sum(b.ib)
from
         a_test a, 
         b_test b
where
         a.id=b.id;

declare continue handler for not found set done = 1;
#打开游标,查询出的值依次插入变量tmp_ia和tmp_ib
open cur_test;
	test_loop:loop
	fetch next from cur_test into tmp_ia, tmp_ib;
	if done then
		leave test_loop;
	end if;

#插入到结果表中
replace   into r_test(
                ia,
                ib)
values(
                tmp_ia,
                tmp_ib
);
end loop test_loop;
close cur_test;
set done = 0;
end $$
delimiter ;

解法二:

采用set 赋值语句,适合查询少量的字段。

 set b = (select a from test);

解法三:

select if 语句,适合少量数据:

用法:select  if(条件,表达式1,表达式2);
注意:条件为真(非0),则返回表达式1,条件为假(0)返回表达式2,如select if(-1,5,2),返回值是5。如果select 多个数据的时候, if条件判断写需要一一对其类型,比较麻烦。多值数据不推荐。

select 中有聚合函数,用法:

 select  if (sum(a) != '', sum(a),  '') from  test 
结果
+------------------------------------------+
| if (sum(a) != '', sum(a),  '') |
+------------------------------------------+
|                                          |
+------------------------------------------+

select中没有聚合函数,可以采用select  if count语句 语句比如:

select if(count(a)>0,count(a),'') from test where a=11;

结果:
+----------------------------+
| if(count(a)>0,count(a),'') |
+----------------------------+
|                            |
+----------------------------+


select if(count(a)>0,count(a),'kong') from test where a=11;

结果
+--------------------------------+
| if(count(a)>0,count(a),'kong') |
+--------------------------------+
| kong                           |
+--------------------------------+

解法四: 

因为当select· into赋值结果为null的时候,会自动修改循环触底的标志,

所以手动在循环底部增加  set no_more = 0 这样也可以避免提前退出循环,

注意set no_more = 0要放在 放在每次循环里面,即end loop之前

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值