在 MySQL 預存程序中操作游標時,常需在循環中實現「跳過本次迭代」或「跳出整個循環」的邏輯。MySQL 提供了 ITERATE(對應 CONTINUE)與 LEAVE(對應 BREAK)標籤語句,但僅能在具名的循環結構中使用。本文詳細說明三種循環結構的語法與游標控制實戰技巧。
REPEAT
Statements;
UNTIL expression
END REPEAT;
WHILE expression DO
Statements;
END WHILE;
loop_label: LOOP
Statements;
IF condition THEN
LEAVE loop_label; -- 跳出循環
END IF;
IF skip_condition THEN
ITERATE loop_label; -- 跳過本次,進入下一次
END IF;
Statements;
END LOOP;
| 語句 | 對應關鍵字 | 作用 | 使用限制 |
|---|---|---|---|
| LEAVE label | BREAK | 立即跳出指定標籤的循環/區塊 | 需在標籤作用域內 |
| ITERATE label | CONTINUE | 結束本次迭代,直接進入下一次循環判斷 | 需在標籤作用域內,僅限 LOOP、REPEAT、WHILE |
DECLARE done INT DEFAULT FALSE;
DECLARE cur CURSOR FOR SELECT id, name FROM users;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO v_id, v_name;
IF done THEN
LEAVE read_loop; -- 資料讀完,跳出循環
END IF;
IF v_id % 2 = 0 THEN
ITERATE read_loop; -- 偶數 ID 跳過處理
END IF;
-- 處理奇數 ID 的業務邏輯
UPDATE stats SET cnt = cnt + 1 WHERE user_id = v_id;
END LOOP;
CLOSE cur;
xxx_loop 命名慣例。done 變數控制多個游標時,每次 OPEN 新游標前務必 SET done = FALSE,否則第二個游標不會執行。若需在同一預存程序處理多個獨立游標,可使用 BEGIN ... END 區塊隔離變數作用域,各自宣告獨立的 done 變數,避免互相干擾:
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE cur_1 CURSOR FOR ...;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- 處理第一個游標
END;
BEGIN
DECLARE done INT DEFAULT FALSE; -- 獨立變數
DECLARE cur_2 CURSOR FOR ...;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- 處理第二個游標
END;
掌握 ITERATE 與 LEAVE 的正確用法,能讓游標邏輯更清晰、可控,避免無限循環或漏處理資料的風險。