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

會(huì)員相冊(cè)數(shù)量表:

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

已經(jīng)正常了?。?!
3. 關(guān)于存儲(chǔ)過(guò)程的SQL補(bǔ)充
-- 顯示存儲(chǔ)過(guò)程的狀態(tài) show procedure status; -- 查詢(xún)指定數(shù)據(jù)庫(kù)的存儲(chǔ)過(guò)程名稱(chēng) select `name` from mysql.proc where db = 'your_db_name' and `type` = 'PROCEDURE'
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL地理空間數(shù)據(jù)完整使用實(shí)戰(zhàn)指南
地理空間數(shù)據(jù)主要用于存儲(chǔ)地理位置信息,如點(diǎn)、線(xiàn)、面等幾何對(duì)象,廣泛應(yīng)用于地圖服務(wù)、位置服務(wù)、物流追蹤等領(lǐng)域,本文介紹MySQL地理空間數(shù)據(jù)完整使用指南,感興趣的朋友跟隨小編一起看看吧2025-12-12
MySQL數(shù)據(jù)過(guò)濾與計(jì)算字段實(shí)戰(zhàn)指南
本文介紹了MySQL數(shù)據(jù)過(guò)濾與計(jì)算字段的實(shí)戰(zhàn)技術(shù),包括多條件組合、通配符過(guò)濾、正則表達(dá)式搜索和計(jì)算字段的使用,感興趣的朋友跟隨小編一起看看吧2025-11-11
Mysql中的排序規(guī)則utf8_unicode_ci、utf8_general_ci的區(qū)別總結(jié)
Mysql中utf8_general_ci與utf8_unicode_ci有什么區(qū)別呢?在編程語(yǔ)言中,通常用unicode對(duì)中文字符做處理,防止出現(xiàn)亂碼,那么在MySQL里,為什么大家都使用utf8_general_ci而不是utf8_unicode_ci呢?2014-04-04
MySQL聯(lián)合查詢(xún)?cè)敿?xì)示例代碼
MySQL聯(lián)合查詢(xún)是數(shù)據(jù)庫(kù)操作中十分重要的技能之一,它允許用戶(hù)從多個(gè)表中提取并組合數(shù)據(jù),下面這篇文章主要介紹了MySQL聯(lián)合查詢(xún)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-10-10
對(duì)MySQL子查詢(xún)的簡(jiǎn)單改寫(xiě)優(yōu)化
這篇文章主要介紹了對(duì)MySQL子查詢(xún)的簡(jiǎn)單改寫(xiě)優(yōu)化,文中的小修改主要將子查詢(xún)改為關(guān)聯(lián)從而降低查詢(xún)時(shí)關(guān)聯(lián)的次數(shù),需要的朋友可以參考下2015-05-05
mysql中的general_log(查詢(xún)?nèi)罩?開(kāi)啟和關(guān)閉
這篇文章主要介紹了mysql中的general_log(查詢(xún)?nèi)罩?開(kāi)啟和關(guān)閉問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
Centos7使用yum安裝MySQL及實(shí)現(xiàn)遠(yuǎn)程連接的方法
因?yàn)镸ySQL被Oracle收購(gòu),目前推薦使用mariadb數(shù)據(jù)庫(kù)。下面通過(guò)本文給大家分享Centos7使用yum安裝MySQL及實(shí)現(xiàn)遠(yuǎn)程連接的方法,感興趣的朋友一起看看吧2017-07-07

