游標是存儲過程中處理結果集逐行邏輯的核心機制。本文系統講解 MySQL 游標語法、操作流程、注意事項,並給出完整可運行範例。
DECLARE cursor_name CURSOR FOR SELECT_statement;
OPEN cursor_name;
FETCH cursor_name INTO var1, var2, ...;
-- 變量數量、順序、類型必須與 SELECT 列表一致
CLOSE cursor_name;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; 避免循環無限執行報錯。
DELIMITER //
CREATE PROCEDURE `batch_update_balance`()
BEGIN
-- 1. 定義局部變量
DECLARE done INT DEFAULT 0;
DECLARE v_callee_name VARCHAR(128);
-- 2. 定義游標
DECLARE cur_account CURSOR FOR
SELECT callee_name FROM account_tbl WHERE acct_timeduration = 10800;
-- 3. 定義 NOT FOUND 處理器
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- 4. 打開游標
OPEN cur_account;
-- 5. 循環處理
read_loop: LOOP
FETCH cur_account INTO v_callee_name;
IF done THEN
LEAVE read_loop;
END IF;
-- 業務邏輯:每賬戶增加 72,消費扣減 72
UPDATE account
SET allMoney = allMoney + 72,
lastMonthConsume = lastMonthConsume - 72
WHERE NumTg = v_callee_name;
END LOOP;
-- 6. 關閉游標
CLOSE cur_account;
END//
DELIMITER ;
REPEAT
FETCH cur_account INTO v_callee_name;
IF NOT done THEN
-- 業務邏輯
END IF;
UNTIL done END REPEAT;
| 場景 | 建議方案 |
|---|---|
| 簡單批量更新/刪除 | 單條 SQL(UPDATE ... WHERE ...)集合操作,避免游標開銷 |
| 需調用外部服務/複雜邏輯 | 游標 + 應用層異步隊列(存儲過程只產生任務表) |
| 大結果集(>10萬行) | 分批游標(LIMIT offset, size)或改用應用層流式處理 |
游標是「最後手段」,優先考慮集合操作。必須使用時,記住:聲明 HANDLER、檢查 done、及時 CLOSE,避免洩漏與死循環。