前言:新项目需要添加 删除用户在系统内的所有痕迹、新增排行榜及获取用户的排名 两个功能
因为排行榜模块相对而言比较有代表性,故此处仅使用排行榜模块,
游标的定义
用于临时存储一个查询返回的多行数据(结果集,类似于java的jdbc连接返回的ResultSet集合),通过遍历游标,可以逐行访问处理该结果集的数据.
游标的使用方式: 声明---打开--读取---关闭
游标的语法
游标声明:
CURSOR 游标名(参数列表) IS 查询语句;
游标的打开:
OPEN 游标名
游标的取值:
FETCH 游标名 INTO 变量列表
游标的关闭:
CLOSE 游标名
游标的属性
游标的属性 | 返回值类型 | 说明 |
%ROWCOUNT | 整型 | 获取FETCH语句返回的数据行数 |
%FOUND | 布尔型 | 最近的FETCH语句返回一行数据则为真,否则为加 |
%NOTFOUND | 布尔型 | 与%FOUND属性返回值相反 |
%ISOPEN | 布尔型 | 游标已经打开时值为真,否则为假 |
以上内容摘抄自:https://www.cnblogs.com/tanlei-sxs/p/9807982.html
首先,写一个存储过程的基础语法(参考上一篇文章):https://www.cnblogs.com/fuhui-study-footprint/p/11975812.html
之后将游标的语法搬过来融合
-- 插入科目一数据 drop procedure p_ranking_subject1; CREATE PROCEDURE `p_ranking_subject1`() begin -- 声明接收游标返回的变量 DECLARE user_id1 INT; DECLARE score1 INT; DECLARE test_type1 INT; DECLARE test_time1 INT; -- 声明排名变量 DECLARE ranking_no int DEFAULT 0; -- 声明游标是否是最后一页变量 DECLARE done int DEFAULT 0; -- 此处声明游标,获取排名的信息,将结果集,放入ranking游标 DECLARE ranking CURSOR FOR select user_id,score,test_type,test_time from t_user_test where test_type = 1 group by user_id order by score desc, test_time asc, create_time asc;
-- 若没有数据返回,程序继续,并将变量IS_FOUND设为0 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- 此处执行一次,排名+1,因为查询语句已经是根据排名查询出来的,所以按照顺序设置排名就可以了 set ranking_no = ranking_no + 1; -- 打开游标 open ranking; -- 将游标中的值赋值给变量,注意:变量名不要和返回的列名同名,变量顺序要和sql结果列的顺序一致 fetch ranking into user_id1, score1, test_type1, test_time1; -- 当s不等于1,也就是未遍历完时,会一直循环 while done <> 1 do -- 执行业务逻辑 insert into t_ranking(`no`,`user_id`,`score`,`test_type`,`test_time`, `create_time`) values (ranking_no, user_id1, score1, test_type1, test_time1, now()); set ranking_no = ranking_no + 1; fetch ranking into user_id1, score1, test_type1, test_time1; -- 当s等于1时表明遍历以完成,退出循环 end while; -- 关闭游标 close ranking; end;
-- 执行存储过程 call p_ranking_subject1();
上面存储过程是我的逻辑,很low勉强算是达到目的,如果有大神看出有更好的方法,非常期望您能给予指点!
在写这篇文章的时候,又看了几篇文章,其中有双游标的使用,例:
CREATE PROCEDURE procedureDemo() BEGIN DECLARE done INT DEFAULT FALSE;
-- 声明光标接收游标 DECLARE a CHAR(16); DECLARE b, c INT;
-- 声明游标 DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1; DECLARE cur2 CURSOR FOR SELECT i FROM test.t2; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- 打开游标 OPEN cur1; OPEN cur2;
-- 遍历游标 read_loop: LOOP
-- 将游标的值取出 FETCH cur1 INTO a, b; FETCH cur2 INTO c;
-- 判断循环是否结束 IF done THEN LEAVE read_loop; END IF;
-- 逻辑 IF b < c THEN INSERT INTO test.t3 VALUES (a,b); ELSE INSERT INTO test.t3 VALUES (a,c); END IF; END LOOP; CLOSE cur1; CLOSE cur2; END;
其中大部分文章对游标的循环用的都是loop,loop也是mysql循环的一种方式,具体参考:https://www.cnblogs.com/Luouy/p/7301360.html?utm_source=itdadao&utm_medium=referral