前言:新項目需要添加 刪除用戶在系統內的所有痕跡、新增排行榜及獲取用戶的排名 兩個功能
因為排行榜模塊相對而言比較有代表性,故此處僅使用排行榜模塊,
游標的定義
用於臨時存儲一個查詢返回的多行數據(結果集,類似於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