昨天遇到一个mysql开发的问题,从网上发现一篇文章,问题得到解决,



文章内容如下:


mysql存储过程中两个CURSOR嵌套使用遇到的问题
我的这个东西就是模拟用户购买商品的一个小东西
user是用户
item是商品
数据库里面有三个表
user表
字段只有一个userid
item表
字段只有一个itemid


relation_used,记录user和item关系
我现在需要做的是这个事情
1.根据一个userid,查询这个user够买过哪些item
2.针对上一步查询出来的每个item,再查询这些item分别被那些user买过,然后对每个uer进行进一步处理


代码如下

CREATE DEFINER=`root`@`localhost` PROCEDURE `second1`( 

   IN id INTEGER(11) 

   ) 

 BEGIN 

 /*保存itemid*/ 

 declare myitemid int; 

 /*保存userid*/ 

 declare myuserid int; 

 /*保存度*/ 

 declare itemdegree float default 0; 



 /*当游标走到最后,设置done为1*/ 

 declare done int default 0; 

 /*查询一个user所购买的所有商品的id*/ 

 DECLARE rs_cursor CURSOR FOR select itemid from relation_used where userid=4; 

 /*查询购买过myitemid,这个myitemid是第一个游标查询的结果。*/ 

 DECLARE mycursor CURSOR FOR select userid from relation_used where itemid=myitemid;[/color] 

 /*当游标走到最后,设置done为1*/ 

 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; 

 /*打开第一个游标开始循环,查询userid=4这个用户都买过那些item*/ 

 open rs_cursor; 

 curso_loop:loop 

 /*获得一个itemid*/ 

 FETCH rs_cursor into myitemid; 

 if done=1 then 

 leave curso_loop; 

 end if; 

 /*记录这个itemid的度*/ 

 select count(*) from relation_used where itemid=myitemid into itemdegree; 





 /*打开第2个游标开始循环,对于每个item,在查询那些user购买过这个item*/ 

 open mycursor; 

 mycursor_loop:loop 

 /*获得一个userid*/ 

 FETCH mycursor into myuserid; 

 if done=1 then 

 leave mycursor_loop; 

 end if; 

 update user set degreeself=degreeself+itemdegree where userid=myuserid; 

 END LOOP; 

 close mycursor; 



 end loop curso_loop; 

 close rs_cursor; 

 END;




这里,第一个游标查询uerid=4分别买过那些商品,这个一步没有问题,我验证过了。这里假设查询结果是itemid分别为1,2,3


但是对于第二个游标就出现问题了,按说它应该对第一个游标查询出来的结果集合itemid(1,2,3)分别进行处理,但是实际上,它只处理了itemid=1这一种情况,对于第一步查询出来的2和3则没有处理
我可以肯定,我的问题一定是出在第二个游标的处理上,也就是红色的部分
可是我实在搞不清楚问题出在哪里,那位高人帮忙看一下
谢谢啦。


------解决方案--------------------------------------------------------

CREATE DEFINER=`root`@`localhost` PROCEDURE `second1`( 

 IN id INTEGER(11) 

 ) 

 BEGIN 

 declare myitemid int; 

 declare myuserid int; 

 declare itemdegree float default 0; 



 declare done int default 0; 

 DECLARE rs_cursor CURSOR FOR select itemid from relation_used where userid=4; 

 DECLARE mycursor CURSOR FOR select userid from relation_used where itemid=myitemid; 

 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; 

 open rs_cursor; 



 curso_loop:loop 

 set done=0; -- 加上这句。 

 FETCH rs_cursor into myitemid; 

 if done=1 then 

 leave curso_loop; 

 end if; 

 select count(*) from relation_used where itemid=myitemid into itemdegree; 





 open mycursor; 

 mycursor_loop:loop 

 FETCH mycursor into myuserid; 

 if done=1 then 

 leave mycursor_loop; 

 end if; 

 update user set degreeself=degreeself+itemdegree where userid=myuserid; 

 END LOOP; 

 close mycursor; 

 end loop curso_loop; 

 close rs_cursor; 

 END;


------解决方案--------------------------------------------------------
可以,不过 要注意DONE的值
curso_loop:loop
set done=0; 在第2个循环结束时,此值为1 
------解决方案--------------------------------------------------------
你可以给每个游标都设置它们单独的循环结束标志位。如DONE1,DONE2,DONE3等。
在游标开始前赋值为0,FOR NOT FOUND SET done=1。分别判断各自的标志位。 
------解决方案--------------------------------------------------------
检查是否有满足条件的记录
select count(*) from relation_used where itemid=myitemid into itemdegree;
update user set degreeself=degreeself+itemdegree where userid=myuserid;