MySQL存儲過程如何實現(xiàn)雙重for循環(huán)遍歷結(jié)果集?
背景
有這么一個需求:對以下的類型結(jié)果集進行更新。

更新的原則是type為c的currentValue的值= (type為b的currentValue) / ((type為b的currentValue) + (type為a的currentValue)) *100。
上面這個需求有很多種實現(xiàn)方法,看到這個需求的時候,我想到的雙重for循環(huán):先查詢第一個結(jié)果集,第一個結(jié)果集合里面包含oid字段。
然后對第一個結(jié)果集進行遍歷,把oid作為參數(shù)更新到第二個sql語句中進行更新。
本文是用定義存儲過程的方式實現(xiàn)對結(jié)果集的遍歷,也就是我所希望的雙重for循環(huán)。
工具:navicat。
數(shù)據(jù):
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);
對查詢結(jié)果進行遍歷
先展示結(jié)果模板:
CREATE PROCEDURE [存儲過程名稱()]
BEGIN
DECLARE s int DEFAULT 0;
DECLARE [變量名 1 ] INT DEFAULT 0;
DECLARE [變量名 2 ] VARCHAR ( 255 );
DECLARE [游標名] CURSOR FOR [包含結(jié)果集的 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 [存儲過程名稱()] 表示創(chuàng)建一個存儲過程。我們這里假設(shè)名稱叫processdata,那么這行代碼就寫成 CREATE PROCEDURE processdata()
(2). BEGIN 和 END 是函數(shù)的開始和結(jié)束
(3).
DECLARE [變量名 1 ] INT DEFAULT 0; DECLARE [變量名 2 ] VARCHAR ( 255 );
這兩行代碼是定義變量,為什么要定義變量呢,是因為我們查詢出的結(jié)果集要放到變量中進行二次操作。
這里需要注意的是,變量名的命名規(guī)則除了跟普通變量一樣以外,還不能夠跟結(jié)果集中對應的字段名重復。
比如 select id,name from student;這個sql中有兩個字段,id和name。那么定義變量的時候就不要再定義id和name了??梢該Q成idTemp 和nameTemp。
另外,變量的類型要和查詢結(jié)果集的字段類型對應。
DECLARE s int DEFAULT 0; 這行sql比較特別是定義循環(huán)變量s的,下面的while循環(huán)要用到。
(4).
DECLARE [游標名] CURSOR FOR [包含結(jié)果集的 SQL ]
這行sql就是定義游標,其中包含了我們的結(jié)果集,比如下面這樣:
DECLARE stu CURSOR FOR select id,name from student group by id;
這樣的話,我們第一個結(jié)果集就出來了。后面就考慮遍歷這個結(jié)果集。
(5).DECLARE CONTINUE HANDLER FOR NOT FOUND SET s=1; 聲明當游標遍歷完后將標志變量置成某個值
(6). OPEN [游標名]; 這個不用過多解釋,上面定義完游標后,這里打開游標。
(7).FETCH [游標名] INTO [變量名 1 ],[變量名 2 ]; 這段sql是將我們查詢的結(jié)果集與我們定義的變量進行關(guān)聯(lián),注意順序應該一一對應。比如下面這樣
FETCH stu INTO idTemp,nameTemp;
這里的idTemp就表示上面結(jié)果集中的id,nameTemp就表示上面結(jié)果集中的nameTemp
(8).
WHILE s <> 1 DO .... END WHILE;
這段代碼是while循環(huán)。
(9).
[你想操作的sql語句]
這個地方就是內(nèi)部for循環(huán)了,比如我們在這個地方寫一個update語句。
update student set score='91' where id=idTemp and name = nameTemp;
這個語句就會去尋找上方結(jié)果集中的id和name,然后把值代入到idTemp中和nameTemp中,進行操作。
(10).
FETCH [游標名] INTO [變量名 1 ],[變量名 2 ];
這段表示將游標中的值再賦值給變量,供下次循環(huán)使用。
當定義完了以后,執(zhí)行sql。然后就是navicat的函數(shù),找個我們剛才定義的函數(shù)進行執(zhí)行。
完成需求
上面已經(jīng)說明白了整個過程的含義,下面我們來完成本文的需求。
CREATE PROCEDURE processData()
BEGIN
DECLARE 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;
結(jié)果

總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
my.cnf參數(shù)配置實現(xiàn)InnoDB引擎性能優(yōu)化
目前來說:InnoDB是為Mysql處理巨大數(shù)據(jù)量時的最大性能設(shè)計。它的CPU效率可能是任何其它基于磁盤的關(guān)系數(shù)據(jù)庫引擎所不能匹敵的。在數(shù)據(jù)量大的網(wǎng)站或是應用中Innodb是倍受青睞的。另一方面,在數(shù)據(jù)庫的復制操作中Innodb也是能保證master和slave數(shù)據(jù)一致有一定的作用。2017-05-05
Mysql8.0密碼問題mysql_native_password和caching_sha2_password詳解
這篇文章主要介紹了Mysql8.0密碼問題mysql_native_password和caching_sha2_password,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08

