首页 > 数据库 >MySQL存储过程实现双重for循环遍历结果集

MySQL存储过程实现双重for循环遍历结果集

来源:互联网 2026-07-25 08:47:09

通过MySQL存储过程实现双重for循环遍历结果集,使用游标获取外层结果集,在循环内根据外层变量执行内层SQL更新操作。该方法适用于按规则更新同类型数据,核心是将外层查询的oid作为参数代入内层更新语句。

背景

最近遇到一个实际需求:需要对下面这种类型的结果集进行更新。

MySQL存储过程实现双重for循环遍历结果集

长期稳定更新的攒劲资源: >>>点此立即查看<<<

更新的规则是:type为c的currentValue = (type为b的currentValue) / ((type为b的currentValue) + (type为a的currentValue)) * 100。

此类需求有多种解法。看到这个场景时,自然而然地想到了双重for循环:先查询第一个结果集,其中包含oid字段,然后遍历该结果集,将每个oid作为参数代入第二个SQL进行更新。

本文采用定义存储过程的方式来实现对结果集的遍历,即通常所说的“双重for循环”。

工具:na vicat。

数据准备:

DROP TABLE IF EXISTS `report_data`;CREATE TABLE `report_data` (  `id` int(255) NOT NULL,    `oid` int(255) NOT NULL,  `type` varchar(10)  not NULL,  `currentValue` double not NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `report_data` (`id`, `oid`, `type`, `currentValue`) VALUES (1, 1, 'a', 1);INSERT INTO `report_data` (`id`, `oid`, `type`, `currentValue`) VALUES (2, 1, 'b', 2);INSERT INTO `report_data` (`id`, `oid`, `type`, `currentValue`) VALUES (3, 1, 'c', 3);INSERT INTO `report_data` (`id`, `oid`, `type`, `currentValue`) VALUES (4, 1, 'd', 4);INSERT INTO `report_data` (`id`, `oid`, `type`, `currentValue`) VALUES (5, 2, 'a', 5);INSERT INTO `report_data` (`id`, `oid`, `type`, `currentValue`) VALUES (6, 2, 'b', 6);INSERT INTO `report_data` (`id`, `oid`, `type`, `currentValue`) VALUES (7, 2, 'c', 7);INSERT INTO `report_data` (`id`, `oid`, `type`, `currentValue`) VALUES (8, 2, 'd', 8);

对查询结果进行遍历

先看一个通用的结果模板,便于后续理解:

CREATE PROCEDURE [存储过程名称()]BEGIN        DECLARE s int DEFAULT 0;    DECLARE [变量名 1 ] INT DEFAULT 0;    DECLARE [变量名 2 ] VARCHAR ( 255 );    DECLARE [游标名] CURSOR FOR [包含结果集的 SQL ]         DECLARE CONTINUE HANDLER FOR NOT FOUND SET s=1;    OPEN [游标名];    FETCH [游标名] INTO [变量名 1 ],[变量名 2 ];    WHILE s <> 1 DO        [你想操作的 SQL语句 ]     FETCH [游标名] INTO [变量名 1 ],[变量名 2 ];    END WHILE;CLOSE [游标名];END;

逐条解释各个部分:

(1)CREATE PROCEDURE [存储过程名称()] 表示创建一个存储过程。假如起名为processdata,则这行是 CREATE PROCEDURE processdata()

(2)BEGINEND 标识函数体的开始和结束。

(3)

DECLARE[变量名 1 ] INT DEFAULT 0;DECLARE[变量名 2 ] VARCHAR ( 255 );

这两行定义变量,目的是将查询结果集放入变量中进行二次操作。需要注意:变量名不能与结果集中的字段名重复,例如结果集有id和name,则变量最好命名为idTemp、nameTemp。另外,变量类型需与字段类型对应。还有 DECLARE s int DEFAULT 0; 是定义循环控制变量,后面的while循环会用到它。

(4)

DECLARE [游标名] CURSOR FOR [包含结果集的 SQL ]

这行定义游标,里面存放结果集SQL。例如:

DECLARE stu CURSOR FOR select id,name from student group by id;

这样第一个结果集就出来了,下一步就是遍历它。

(5)DECLARE CONTINUE HANDLER FOR NOT FOUND SET s=1; 声明当游标遍历完后,将标志变量s置为1,作为循环结束条件。

(6)OPEN [游标名]; 打开游标。

(7)FETCH [游标名] INTO [变量名 1 ],[变量名 2 ]; 将游标当前行的数据赋给变量,顺序必须一一对应。例如:

FETCH stu INTO idTemp,nameTemp;

这里idTemp对应结果集中的id,nameTemp对应name。

(8)

WHILE s <> 1 DO....END WHILE;

这是while循环体。

(9)[你想操作的sql语句] 就是内部循环要执行的操作,比如写一个update:

update student set score='91' where id=idTemp and name = nameTemp;

这条语句会引用上方游标中的id和name值,代入条件进行更新。

(10)FETCH [游标名] INTO [变量名 1 ],[变量名 2 ]; 在循环体内再次fetch,将游标向后移动,供下一次循环使用。

定义完成后,执行存储过程,然后在na vicat的函数列表中找到刚才定义的函数执行即可。

完成需求

上面的模板已经讲清了整个流程,现在直接套用来解决本文开头的需求。

CREATE PROCEDURE processData()BEGINDECLARE s int DEFAULT 0;DECLARE oidTemp int DEFAULT 20;DECLARE report CURSOR FOR  SELECT oid from report_data  GROUP BY oid;DECLARE CONTINUE HANDLER FOR NOT FOUND SET s=1;    open report;    fetch report into oidTemp;    while s<>1 do            SET @fenzi=   (SELECT currentValue from report_data WHERE type='b' and oid =oidTemp);      set @fenmu=   (SELECT currentValue from report_data WHERE type='a' and oid =oidTemp) +                                     (SELECT currentValue from report_data WHERE type='b' and oid =oidTemp);            set  @result =  @fenzi/@fenmu *100;                          update report_data set currentvalue = @result WHERE oid =oidTemp and type='c';        fetch report into  oidTemp;    end while;    close report;END;

执行后的结果:

MySQL存储过程实现双重for循环遍历结果集

总结

以上就是用MySQL存储过程实现双重for循环遍历结果集的一个完整示例。核心思路是:先通过游标获取外层结果集,然后在循环内根据外层变量执行内层SQL。掌握这个模板后,类似的需求都可以快速套用。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备2026025700号-3 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。