MySQL遊標雙層循環方法 MySQL存儲過程遊標嵌套循環 MySQL使用多個遊標
一、需求描述
1、在項目中,需要將A表中主鍵id,逐個取出,作爲條件,在B表中去逐一查詢,將B表查詢到的結果集(A表B表關係:一對多),逐一遍歷,連同A表的id,逐個插入到C表中。
2、 在Java中很容易實現,A表獲取到的結果集,循環遍歷取出id,去B表查詢;遍歷B表結果集,插入到C表中。 相當於2個循環,即可實現需求。 這樣會有一個問題,頻繁連接數據庫,造成大量資源開銷。 那麼在存儲過程中,該怎麼實現呢?
二、思路
1、要實現逐行獲取數據,需要用到MySQL中的遊標,一個遊標相當於一個for循環,這裏需要用到2個遊標。如何在MySQL中實現遊標雙層循環呢?
三、代碼實現
1、 client 表中有8條數據
2、account 表中有2條數據
3、要實現client表和account表中數據組合插入到batch表中。 (相當於需求)
4、創建存儲過程 pro_cursor_nest() , 實現需求。
DROP PROCEDURE IF EXISTS pro_cursor_nest;
CREATE PROCEDURE pro_cursor_nest()
BEGIN -- out BEGIN
DECLARE c_name VARCHAR(200) ;
DECLARE out_done INT DEFAULT FALSE ; -- 外層遊標控制變量
DECLARE out_cursor CURSOR FOR (SELECT NAME FROM client ); -- 外層遊標
DECLARE CONTINUE HANDLER FOR NOT FOUND SET out_done = TRUE ; -- 外層遊標執行結束,置爲TRUE
OPEN out_cursor ; -- 打開外層遊標
WHILE NOT out_done DO -- out WHILE
FETCH out_cursor INTO c_name ; -- 從【外層遊標】中獲取數據,賦值到定義變量中
IF NOT out_done THEN -- out IF
-- 開始定義內層遊標
BEGIN -- inner BEGIN
DECLARE money INT ;
DECLARE inner_done int DEFAULT FALSE ;
DECLARE inner_cursor CURSOR FOR ( SELECT balance FROM account );
DECLARE CONTINUE HANDLER FOR NOT FOUND SET inner_done = TRUE ;
OPEN inner_cursor ; -- 打開內層遊標
WHILE NOT inner_done DO -- inner WHILE
FETCH inner_cursor INTO money ; -- 從【內層遊標】中獲取數據,賦值到定義變量中
IF NOT inner_done THEN
INSERT INTO `batch` (`id`, `name`, `age`) VALUES (UUID(),c_name ,money);
END IF;
END WHILE ; -- END inner WHILE
CLOSE inner_cursor; -- 循環結束後,關閉內層遊標
END; -- END inner BEGIN
END IF; -- END out IF
END WHILE; -- END out WHILE
CLOSE out_cursor ; -- 循環結束後 ,關閉外層遊標
END; -- END out BEGIN
(給一代碼結構更好看的圖片)
5、執行存儲過程: CALL pro_cursor_nest ();
6、查看 batch 表結果如下:
四、總結
1、創建一個遊標步驟如下:
-
定義變量,接收遊標賦值 c_name
-
定義遊標開關變量 done
-
定義遊標 out_cursor
-
遊標結束後,關閉開關 --- DECLARE CONTINUE HANDLER FOR NOT FOUND SET
-
打開遊標 OPEN out_cursor
-
開啓循環 WHILE .. DO ( 還有LOOP ,REPEAT 也可以)
-
從遊標中獲取數據,賦值到變量 (FETCH)
-
判斷遊標是否執行結束 (IF NOT out_done )
-
執行相應業務邏輯操作 do Something
-
結束循環 (END WHILE)
-
關閉遊標 (CLOSE out_cursor)
2、創建雙層遊標,即在 【執行相應業務邏輯操作】,再 BEGIN ... END , 重新定義一個新遊標,注意嵌套關係即可。
3、覺得雙層遊標循環麻煩,不易理解的,分別寫兩個存儲過程,也可以,那樣業務更簡單,易於理解,便於後期維護。
瞭解更多 ....
MySQL WHILE和LOOP和REPEAT循環的用法區別 MySQL三種循環的區別 MySQL循環使用方法