解決MySQL遊標循環多執行一次的問題 MySQL存儲過程使用遊標時,多執行一次的問題

   解決MySQL遊標循環多執行一次的問題 MySQL存儲過程使用遊標時,多執行一次的問題

 

一、問題描述

1、在寫MySQL存儲過程,使用到遊標遍歷數據時,遇到一個問題:遊標的循環比數據集填充到遊標要多執行1次

2、表述不清,這樣理解:填充到遊標時,select 查詢到10條, 實際循環會執行 11次。 即永遠 n+1 多一次。

 

二、問題重現

1、如下,存儲過程 pro_multi() ,將會執行 2次。

DROP PROCEDURE IF EXISTS pro_multi ;
CREATE PROCEDURE pro_multi()
BEGIN
DECLARE count int DEFAULT 0 ; -- 定義 count 計數
DECLARE done int DEFAULT FALSE; -- 定義遊標循環變量
DECLARE my_cursor CURSOR  FOR( SELECT 1) ; -- 定義遊標,獲取到1條數據
DECLARE CONTINUE HANDLER FOR NOT FOUND  set done = TRUE ; -- 遊標循環結束時,將控制變量done = TRUE
	
OPEN my_cursor ; -- 打開遊標
WHILE NOT done DO -- 開始循環 
	FETCH  my_cursor INTO count ; -- 獲取一行數據,賦值到自定義變量中
	INSERT INTO `batch` (`id`,`name`, `age`) VALUES (UUID(),count, '0'); -- 插入數據
	SET count = count + 1; -- 變量+1
END WHILE ; -- 結束循環
END ;

 

三、問題定位

1、原因:遊標第一次獲取數據時,正常 ;第二次獲取數據時,執行到末尾,沒有數據,此時done = TRUE , 然而下面的 INSERT 語句,卻不知道遊標已經到末尾,仍然插入了一條數據。

2、從而造成了,MySQL遊標循環執行多一次的問題。

 

 

四、問題解決

1、方法一:在循環體外,先獲取一次遊標數據

DROP PROCEDURE IF EXISTS pro_multi_fix1 ;

CREATE PROCEDURE pro_multi_fix1()

BEGIN

-- 解決 多執行一次的問題

DECLARE count int DEFAULT 0 ; -- 定義 count 計數

DECLARE done int DEFAULT FALSE; -- 定義遊標循環變量

DECLARE my_cursor CURSOR FOR( SELECT 1) ; -- 定義遊標,獲取到1條數據

DECLARE CONTINUE HANDLER FOR NOT FOUND set done = TRUE ; -- 遊標循環結束時,將控制變量done = TRUE

OPEN my_cursor ; -- 打開遊標

FETCH my_cursor INTO count ; -- 循環外,先獲取一次數據

WHILE NOT done DO -- 開始循環

       INSERT INTO `batch` (`id`,`name`, `age`) VALUES (UUID(),count, '0'); -- 插入數據

       FETCH my_cursor INTO count ; -- 再一次獲取數據

       SET count = count + 1; -- 變量+1

END WHILE ; -- 結束循環

END ;

 

2、方法二:在循環體內,增加判斷遊標是否已經執行結束

DROP PROCEDURE IF EXISTS pro_multi_fix2 ;

CREATE PROCEDURE pro_multi_fix2()

BEGIN

-- 解決 多執行一次的問題 (方法二)

DECLARE count int DEFAULT 0 ; -- 定義 count 計數

DECLARE done int DEFAULT FALSE; -- 定義遊標循環變量

DECLARE my_cursor CURSOR FOR( SELECT 1) ; -- 定義遊標,獲取到1條數據

DECLARE CONTINUE HANDLER FOR NOT FOUND set done = TRUE ; -- 遊標循環結束時,將控制變量done = TRUE

OPEN my_cursor ; -- 打開遊標

WHILE NOT done DO -- 開始循環

       FETCH my_cursor INTO count ; -- 再一次獲取數據

       IF NOT done THEN -- 增加判斷,遊標循環結束後,不插入數據

             INSERT INTO `batch` (`id`,`name`, `age`) VALUES (UUID(),count, '0'); -- 插入數據

        END IF ;

        SET count = count + 1; -- 變量+1

END WHILE ; -- 結束循環

END ;

 

 

---- 還有更多 .... 

MySQL觸發器資料整理創建觸發器及查看、刪除觸發器

MySQL存儲過程學習整理,遊標使用,參數輸入輸出

 MyBatis調用存儲過程,MyBatis調用函數的使用方法

MySQL 創建函數, MySQL定義函數實現漢字轉拼音 MySQL漢字轉拼音MySQL漢字生成拼音字符串

        MySQL創建視圖

        MySQL WHILE和LOOP和REPEAT循環的用法區別 MySQL三種循環的區別 MySQL循環使用方法

      解決MySQL遊標循環多執行一次的問題

 

 

發佈了155 篇原創文章 · 獲贊 155 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章