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

MySQL 游標完整使用指南:宣告、開啟、迴圈、異常處理與巢狀範例

     編輯:MySQL 綜合教學

MySQL 游標完整使用指南:宣告、開啟、迴圈、異常處理與巢狀範例

游標用於在預存程序中逐行處理查詢結果集,適合複雜邏輯、逐行計算、動態 SQL 構建等場景。

核心語法流程

  1. 宣告:DECLARE cursor_name CURSOR FOR SELECT ...;
  2. 異常處理:DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
  3. 開啟:OPEN cursor_name;
  4. 讀取:FETCH cursor_name INTO var1, var2...;
  5. 迴圈處理:WHILE NOT done DO ... END WHILE; 或 LOOP ... END LOOP;
  6. 關閉:CLOSE cursor_name;

範例一:WHILE 迴圈累加字串

DROP PROCEDURE IF EXISTS useCursor;
DELIMITER $$
CREATE PROCEDURE useCursor()
BEGIN
  DECLARE tmpName VARCHAR(20) DEFAULT '';
  DECLARE allName VARCHAR(255) DEFAULT '';
  DECLARE done INT DEFAULT 0;

  DECLARE cur1 CURSOR FOR SELECT name FROM test.level;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  OPEN cur1;
  FETCH cur1 INTO tmpName;

  WHILE NOT done DO
    SET tmpName = CONCAT(tmpName, ';');
    SET allName = CONCAT(allName, tmpName);
    FETCH cur1 INTO tmpName;
  END WHILE;

  CLOSE cur1;
  SELECT allName AS result;
END$$
DELIMITER ;

CALL useCursor();

範例二:LOOP + LEAVE 迴圈

DELIMITER $$
DROP PROCEDURE IF EXISTS cursor_example$$
CREATE PROCEDURE cursor_example()
READS SQL DATA
BEGIN
  DECLARE l_employee_id INT;
  DECLARE l_salary DECIMAL(8,2);
  DECLARE l_department_id INT;
  DECLARE done INT DEFAULT 0;

  DECLARE cur1 CURSOR FOR SELECT employee_id, salary, department_id FROM employees;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  OPEN cur1;
  emp_loop: LOOP
    FETCH cur1 INTO l_employee_id, l_salary, l_department_id;
    IF done = 1 THEN LEAVE emp_loop; END IF;
    -- 處理邏輯:如動態構建 SQL、寫入臨時表等
  END LOOP emp_loop;
  CLOSE cur1;
END$$
DELIMITER ;

範例三:REPEAT 迴圈

DELIMITER //
DROP PROCEDURE IF EXISTS test //
CREATE PROCEDURE test()
BEGIN
  DECLARE done INT DEFAULT 0;
  DECLARE a VARCHAR(200) DEFAULT '';
  DECLARE c VARCHAR(200) DEFAULT '';
  DECLARE mycursor CURSOR FOR SELECT fusername FROM uchome_friend;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  OPEN mycursor;
  REPEAT
    FETCH mycursor INTO a;
    IF NOT done THEN
      SET c = CONCAT(c, a);
    END IF;
  UNTIL done END REPEAT;
  CLOSE mycursor;
  SELECT c;
END //
DELIMITER ;

關鍵注意事項

項目說明
作用域游標僅在預存程序/函數/觸發器中可用,不可在普通 SQL 使用。
唯讀/敏感度MySQL 游標為非捲動、唯讀、敏感(反映開啟時的資料快照,或即時變更視存儲引擎而定)。
FETCH 後必須檢查 NOT FOUND否則迴圈無法終止,導致無限迴圈或例外。
巢狀游標支援,內層游標在外層迴圈中 OPEN/FETCH/CLOSE,注意變數名不衝突。
效能逐行處理遠慢於集合操作(JOIN/子查詢/窗口函數),能用單條 SQL 解決盡量不用游標。

替代方案建議

  • 集合操作:INSERT ... SELECT, UPDATE ... JOIN, MERGE (8.0+)
  • 窗口函數:ROW_NUMBER(), LAG(), SUM() OVER() 等
  • 應用層處理:取回結果集在程式碼中迴圈,減少資料庫 CPU 壓力
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved