MySQL存儲過程之循環(huán)遍歷查詢的結(jié)果集詳解
前言
近來碰到這樣一個問題:在生產(chǎn)上導入的數(shù)據(jù)發(fā)現(xiàn)會員的相冊數(shù)量統(tǒng)計結(jié)果與相冊中實際的數(shù)量不一致的問題。
解決這個問題有兩種辦法:
- 1:使用程序修正數(shù)量不一致的問題
- 2:使用MySQL的存儲過程
若使用第一種辦法的話,需要重新發(fā)布版本,比較麻煩,再加上領(lǐng)導對發(fā)布版本有些抵觸,我覺得我們還是使用第二種方式比較快捷。
1. 表結(jié)構(gòu)
測試表結(jié)構(gòu)如下:
CREATE TABLE `member_album` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '數(shù)據(jù)ID', `member_id` int(11) DEFAULT NULL COMMENT '會員ID', `file_type` varchar(8) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件類型(image:照片;video:視頻)', `file_id` int(11) DEFAULT NULL COMMENT '文件ID', `file_path` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件地址(相對地址)', `create_date` datetime DEFAULT NULL COMMENT '創(chuàng)建時間', `del_flag` tinyint(1) DEFAULT '0' COMMENT '刪除標識(0:正常;1:已刪除)', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='會員相冊';
CREATE TABLE `member_album_count` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '數(shù)據(jù)ID', `member_id` int(11) DEFAULT NULL COMMENT '會員ID', `img_pass_count` int(11) DEFAULT '0' COMMENT '照片通過的數(shù)量', `img_verify_count` int(11) DEFAULT '0' COMMENT '照片審核中的數(shù)量', `img_fail_count` int(11) DEFAULT '0' COMMENT '照片未通過的數(shù)量', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='會員照片數(shù)量表';
測試表數(shù)據(jù)如下:
會員相冊表:

會員相冊數(shù)量表:

很明顯,會員相冊數(shù)量表中的數(shù)據(jù)是不對的,例如會員ID為10024的照片有3張,而在會員相冊數(shù)量表中顯示的是0張。
2. 存儲過程
-- 建立存儲過程之前需要判斷該存儲過程是否存在,若存在則刪除 DROP PROCEDURE IF EXISTS update_album_count; -- 創(chuàng)建存儲過程,update_album_count為存儲過程名 CREATE PROCEDURE update_album_count() -- 標識存儲過程開始 BEGIN -- 定義變量 DECLARE s int DEFAULT 0; DECLARE memberId int; DECLARE count int; -- 定義游標,并將sql結(jié)果集賦值到游標中,report為游標名 DECLARE report CURSOR FOR SELECT member_id, COUNT(member_id) FROM member_album GROUP BY member_id HAVING COUNT(member_id) > 0 ORDER BY member_id ASC; -- 聲明當游標遍歷完后將標志變量置為某個值 DECLARE CONTINUE HANDLER FOR NOT FOUND SET s = 1; -- 打開游標 OPEN report; -- 將游標中的值賦值給變量,注意:變量名不要與sql返回的列名相同,變量順序要和sql結(jié)果列的順序一致 FETCH report INTO memberId, count; -- 當s不等于1時,也就是未遍歷完時,會一直循環(huán) WHILE s <> 1 DO -- 執(zhí)行業(yè)務(wù)邏輯 UPDATE member_album_count t SET t.img_pass_count = count WHERE t.member_id = memberId; -- 當s等于1時代表遍歷已完成,退出循環(huán) FETCH report INTO memberId, count; END WHILE; -- 關(guān)閉游標 CLOSE report; -- 標識存儲過程結(jié)束 END;
執(zhí)行存儲過程:
CALL update_album_count();
此時再來看會員相冊數(shù)量表數(shù)據(jù):

已經(jīng)正常了?。?!
3. 關(guān)于存儲過程的SQL補充
-- 顯示存儲過程的狀態(tài) show procedure status; -- 查詢指定數(shù)據(jù)庫的存儲過程名稱 select `name` from mysql.proc where db = 'your_db_name' and `type` = 'PROCEDURE'
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
mysql explain的用法(使用explain優(yōu)化查詢語句)
mysql explain可以幫助你檢查索引和更好的優(yōu)化查詢語句,今天特地學習了下mysql explain的用法,需要的朋友可以參考下2017-01-01

