首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 游標完整指南:聲明、打開、循環、關閉與實戰範例

     編輯:MySQL 綜合教學

游標是存儲過程中處理結果集逐行邏輯的核心機制。本文系統講解 MySQL 游標語法、操作流程、注意事項,並給出完整可運行範例。

游標適用場景

  • 需對查詢結果集逐行處理(如發送郵件、調用外部 API、複雜業務規則)。
  • 無法用單條 SQL 完成的行級迭代邏輯。

核心語法

1. 聲明


DECLARE cursor_name CURSOR FOR SELECT_statement;

2. 打開


OPEN cursor_name;

3. 獲取數據(FETCH)


FETCH cursor_name INTO var1, var2, ...;
-- 變量數量、順序、類型必須與 SELECT 列表一致

4. 關閉


CLOSE cursor_name;

關鍵特性與限制

  • 只讀、單向、不可滾動:只能順序向前讀取,無法回滾或跳轉。
  • 作用域:僅在存儲過程/函數/觸發器內有效,不能跨過程傳遞。
  • 結果集接收:存儲過程返回的結果集可被客戶端(PHP/Java)接收,但無法在另一存儲過程中直接接收,需通過臨時表中轉。
  • NOT FOUND 處理:必須聲明 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 UNTIL 循環


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,避免洩漏與死循環。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved