MySql存儲(chǔ)過(guò)程循環(huán)的使用分析詳解
簡(jiǎn)介
每一門數(shù)據(jù)庫(kù)語(yǔ)言語(yǔ)法都基本相似,但是對(duì)于他們各自的一些特性(函數(shù)、存儲(chǔ)過(guò)程等)的用法就不大相同了,就好比Oracle
與Mysql
存儲(chǔ)過(guò)程寫起來(lái)就很多不同的地方,在這里主要是跟大家分享一下MySql
存儲(chǔ)過(guò)程中使用游標(biāo)循環(huán)的處理方法。
場(chǎng)景描述
我們舉一個(gè)簡(jiǎn)單的場(chǎng)景,首先我們可能會(huì)有這樣一種情況,考試成績(jī)表(t_achievement
)有一堆的sql腳本處理,需要依賴另一個(gè)學(xué)生表(t_student
)數(shù)據(jù)對(duì)部分學(xué)生做考試成績(jī)匯總記錄到成績(jī)匯總表(t_achievement_report
)。
解決方案
- 有一種方式就是通過(guò)代碼優(yōu)先將要匯總的學(xué)生表數(shù)據(jù)獲取出來(lái),然后按成績(jī)匯總流程逐個(gè)將學(xué)生信息數(shù)據(jù)傳遞到成績(jī)匯總業(yè)務(wù)代碼進(jìn)行處理。
- 另一種方式也是我們今天的主題,那就是通過(guò)存儲(chǔ)過(guò)程的方式去做。
案例
建表語(yǔ)句:
-- 學(xué)生信息表 DROP TABLE IF EXISTS t_student; CREATE TABLE `t_student` ( `id` BIGINT(12) NOT NULL AUTO_INCREMENT COMMENT '主鍵', `code` VARCHAR(10) NOT NULL COMMENT '學(xué)號(hào)', `name` VARCHAR(20) NOT NULL COMMENT '姓名', `age` INT(2) NOT NULL COMMENT '年齡', `gender` CHAR(1) NOT NULL COMMENT '性別(M:男,F(xiàn):女)', PRIMARY KEY (`id`), UNIQUE KEY UK_STUDENT (`code`) ) CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- 學(xué)生成績(jī)表 DROP TABLE IF EXISTS t_achievement; CREATE TABLE `t_achievement` ( `id` BIGINT(12) NOT NULL AUTO_INCREMENT COMMENT '主鍵', `year` INT(4) NOT NULL COMMENT '學(xué)年', `subject` CHAR(2) NOT NULL COMMENT '科目(01:語(yǔ)文,02:數(shù)學(xué),03:英語(yǔ))', `score` INT(3) NOT NULL COMMENT '得分', `student_id` BIGINT(12) NOT NULL COMMENT '所屬學(xué)生id', PRIMARY KEY (`id`) ) CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- 成績(jī)匯總表 DROP TABLE IF EXISTS t_achievement_report; CREATE TABLE `t_achievement_report` ( `id` BIGINT(12) NOT NULL AUTO_INCREMENT COMMENT '主鍵', `student_id` BIGINT(12) NOT NULL COMMENT '學(xué)生id', `year` INT(4) NOT NULL COMMENT '學(xué)年', `total_score` INT(4) NOT NULL COMMENT '總分', `avg_score` DECIMAL(4,2) NOT NULL COMMENT '平均分', PRIMARY KEY (`id`) ) CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
初始化數(shù)據(jù):
INSERT INTO t_student(id, CODE, NAME, age, gender) VALUES (1, '2022010101', '小張', 18, 'M'), (2, '2022010102', '小李', 18, 'F'), (3, '2022010103', '小明', 18, 'M'); INSERT INTO t_achievement(YEAR, SUBJECT, score, student_id) VALUES (2022, '01', 80, 1), (2022, '02', 85, 1), (2022, '03', 90, 1), (2022, '01', 60, 2), (2022, '02', 90, 2), (2022, '03', 98, 2), (2022, '01', 75, 3), (2022, '02', 100, 3), (2022, '03', 85, 3);
存儲(chǔ)過(guò)程:
在這里主要以上面的場(chǎng)景為例,使用存儲(chǔ)過(guò)程循環(huán)去處理數(shù)據(jù)。寫一個(gè)存儲(chǔ)過(guò)程,將以上數(shù)據(jù)每個(gè)學(xué)生的成績(jī)進(jìn)行匯總。
-- 如果存儲(chǔ)過(guò)程存在,先刪除存儲(chǔ)過(guò)程 DROP PROCEDURE IF EXISTS statistics_achievement; DELIMITER $$ -- 定義存儲(chǔ)過(guò)程 CREATE PROCEDURE statistics_achievement() BEGIN -- 定義變量記錄循環(huán)處理是否完成 DECLARE done BOOLEAN DEFAULT FALSE; -- 定義變量傳遞學(xué)生id DECLARE studentid BIGINT(12); -- 定義游標(biāo) DECLARE cursor_student CURSOR FOR SELECT id FROM t_student; -- 定義CONTINUE HANDLER,當(dāng)循環(huán)結(jié)束時(shí) done=true DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=TRUE; -- 打開(kāi)游標(biāo) OPEN cursor_student; -- 重復(fù)遍歷 REPEAT -- 每次讀取一次游標(biāo) FETCH cursor_student INTO studentid; -- 計(jì)算總分、平均分插入?yún)R總表 INSERT INTO t_achievement_report(student_id, `YEAR`, total_score, avg_score) SELECT studentid, `YEAR`, SUM(score), ROUND(SUM(score) / 3, 2) FROM t_achievement t1 WHERE student_id = studentid AND NOT EXISTS( SELECT 1 FROM t_achievement_report t2 WHERE student_id = studentid AND t1.year = t2.year ) GROUP BY `YEAR`; -- 結(jié)束循環(huán),意思是等到done=true時(shí),結(jié)束循環(huán)REPEAT UNTIL done END REPEAT; -- 查詢結(jié)果,僅會(huì)展示查出的最后一條 SELECT studentid; -- 關(guān)閉游標(biāo) CLOSE cursor_student; END$$ DELIMITER ;
-- 執(zhí)行存儲(chǔ)過(guò)程 CALL statistics_achievement();
- 執(zhí)行結(jié)果,返回查詢結(jié)果3,即最后一條學(xué)生記錄id
總結(jié)
存儲(chǔ)過(guò)程也有很強(qiáng)大的功能,如果是一名DBA那么寫存儲(chǔ)過(guò)程是分分鐘的事,但是作為一名專做業(yè)務(wù)的碼農(nóng)還是不建議去使用存儲(chǔ)過(guò)程寫業(yè)務(wù)代碼。前公司同事適應(yīng)了寫存儲(chǔ)過(guò)程,有業(yè)務(wù)改動(dòng)時(shí)不時(shí)的直接用存儲(chǔ)過(guò)程搞定了,到最后直接就是一大堆堆存儲(chǔ)過(guò)程代碼,一個(gè)存儲(chǔ)過(guò)程下來(lái)幾百上千行sql代碼頭都看暈掉,出問(wèn)題巨難維護(hù),稍有不熟的人員都不敢輕舉妄動(dòng),今天在這里也只是為了講解存儲(chǔ)過(guò)程中的循環(huán)而舉了個(gè)栗子請(qǐng)別介意。
總之我認(rèn)為存儲(chǔ)過(guò)程主要還是用來(lái)臨時(shí)處理一些數(shù)據(jù)方便而用一下,特別有些業(yè)務(wù)改造大,需要做數(shù)據(jù)割接總不能挨個(gè)去寫一個(gè)業(yè)務(wù)代碼吧。
到此這篇關(guān)于MySql存儲(chǔ)過(guò)程循環(huán)的使用分析詳解的文章就介紹到這了,更多相關(guān)MySql存儲(chǔ)過(guò)程循環(huán)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Mysql 存儲(chǔ)過(guò)程中使用游標(biāo)循環(huán)讀取臨時(shí)表
- 詳解MySql存儲(chǔ)過(guò)程參數(shù)的入門使用
- MySQL存儲(chǔ)過(guò)程中使用WHILE循環(huán)語(yǔ)句的方法
- Mysql存儲(chǔ)過(guò)程循環(huán)內(nèi)嵌套使用游標(biāo)示例代碼
- 詳解MySQL存儲(chǔ)過(guò)程的創(chuàng)建和調(diào)用
- mysql創(chuàng)建存儲(chǔ)過(guò)程及函數(shù)詳解
- MySQL之存儲(chǔ)過(guò)程按月創(chuàng)建表的方法步驟
- mysql存儲(chǔ)過(guò)程之創(chuàng)建(CREATE PROCEDURE)和調(diào)用(CALL)及變量創(chuàng)建(DECLARE)和賦值(SET)操作方法
- MySQL動(dòng)態(tài)創(chuàng)建表,數(shù)據(jù)分表的存儲(chǔ)過(guò)程
- MySQL存儲(chǔ)過(guò)程的創(chuàng)建和使用示例詳解
相關(guān)文章
Mac os 解決無(wú)法使用localhost連接mysql問(wèn)題
今天在mac上搭建好了php的環(huán)境,把先前在window、linux下運(yùn)行良好的程序放在mac上,居然出現(xiàn)訪問(wèn)不了數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)連接的host用的是localhost,可以確認(rèn)數(shù)據(jù)庫(kù)配置是正確的,下面特為大家分享下2014-05-05MySQL中DATE_FORMAT()函數(shù)將Date轉(zhuǎn)為字符串
時(shí)間、字符串、時(shí)間戳之間的互相轉(zhuǎn)換很常用,下面這篇文章主要給大家介紹了關(guān)于MySQL中DATE_FORMAT()函數(shù)將Date轉(zhuǎn)為字符串的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09淺談MySQL數(shù)據(jù)查詢太多會(huì)OOM嗎
本文主要介紹了淺談MySQL數(shù)據(jù)查詢太多會(huì)OOM嗎?文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08mysql Community Server 5.7.19安裝指南(詳細(xì))
這篇文章主要介紹了mysql Community Server 5.7.19安裝指南(詳細(xì)),需要的朋友可以參考下2017-10-10詳解MySQL 重做日志(redo log)與回滾日志(undo logo)
這篇文章主要介紹了MySQL redo與undo日志的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)MySQL,感興趣的朋友可以了解下2020-08-08MySQL運(yùn)維實(shí)戰(zhàn)使用RPM進(jìn)行安裝部署
這篇文章主要為大家介紹了MySQL運(yùn)維實(shí)戰(zhàn)使用RPM進(jìn)行安裝部署實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12mysql數(shù)據(jù)庫(kù)應(yīng)付大流量網(wǎng)站的的3種架構(gòu)擴(kuò)展方式介紹
這篇文章主要介紹了mysql數(shù)據(jù)庫(kù)應(yīng)付大流量網(wǎng)站的的3種架構(gòu)擴(kuò)展方式介紹,它們分別是讀寫分離、垂直分區(qū)、水平分區(qū),本文分別對(duì)它們做了講解,需要的朋友可以參考下2014-07-07