MySQL 中的游标(Cursor)

一、游标的作用

  • ​逐行处理数据​:当需要对查询结果集中的每一行进行特定操作(如计算、条件判断、调用其他过程)时使用。
  • ​替代集合操作​:在无法通过单一 SQL 语句完成复杂逻辑时,游标提供逐行处理的能力。
  • ​典型场景​:数据迁移、报表生成、逐行校验等。

二、游标的使用步骤

游标使用遵循 ​​5个固定步骤​​,必须按顺序编写:

  1. ​声明游标​

    定义游标名称和对应的查询语句:

    复制代码
    DECLARE cursor_name CURSOR FOR SELECT_statement;
  2. ​声明错误处理器​

    处理游标遍历结束时的 NOT FOUND 状态,避免死循环:

    复制代码
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
  3. ​打开游标​

    执行查询语句,生成结果集:

    复制代码
    OPEN cursor_name;
  4. ​循环获取数据​

    逐行读取数据并进行处理:

    复制代码
    FETCH cursor_name INTO variables;
  5. ​关闭游标​

    释放资源:

    复制代码
    CLOSE cursor_name;

三、完整示例

示例1:计算员工平均工资
复制代码
DELIMITER //

CREATE PROCEDURE calculate_avg_salary()
BEGIN
    DECLARE emp_salary DECIMAL(10,2);
    DECLARE total DECIMAL(10,2) DEFAULT 0;
    DECLARE count INT DEFAULT 0;
    DECLARE done INT DEFAULT 0;
    
    -- 1. 声明游标
    DECLARE cur CURSOR FOR SELECT salary FROM employees;
    
    -- 2. 错误处理器
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    
    -- 3. 打开游标
    OPEN cur;
    
    -- 4. 循环读取
    read_loop: LOOP
        FETCH cur INTO emp_salary;
        IF done = 1 THEN
            LEAVE read_loop;
        END IF;
        SET total = total + emp_salary;
        SET count = count + 1;
    END LOOP;
    
    -- 5. 关闭游标
    CLOSE cur;
    
    -- 输出结果
    SELECT total / count AS avg_salary;
END //

DELIMITER ;

-- 调用存储过程
CALL calculate_avg_salary();
示例2:处理订单状态
复制代码
CREATE PROCEDURE update_order_status()
BEGIN
    DECLARE order_id INT;
    DECLARE order_status VARCHAR(20);
    DECLARE done INT DEFAULT 0;
    
    DECLARE cur CURSOR FOR 
        SELECT id, status FROM orders WHERE created_at < NOW() - INTERVAL 30 DAY;
    
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    
    OPEN cur;
    
    loop_start: LOOP
        FETCH cur INTO order_id, order_status;
        IF done THEN
            LEAVE loop_start;
        END IF;
        
        IF order_status = 'PENDING' THEN
            UPDATE orders SET status = 'EXPIRED' WHERE id = order_id;
        END IF;
    END LOOP;
    
    CLOSE cur;
END;

四、注意事项

  1. ​性能问题​

    游标逐行操作会 ​​增加数据库负载​ ​,数据量大时效率低下,优先考虑集合操作(如 UPDATEJOIN)。

  2. ​作用域限制​

    游标必须在存储过程或函数的 ​​BEGIN-END块​ ​ 中声明,且所有 DECLARE 需放在其他语句之前。

  3. ​只读性​

    MySQL 游标默认是 ​​只读​ ​ 的,无法通过游标直接修改数据(需配合 UPDATE 语句)。

  4. ​错误处理​

    必须通过 CONTINUE HANDLER 处理 NOT FOUND 状态,否则可能陷入死循环。

  5. ​资源释放​

    游标使用后必须用 CLOSE 释放,否则可能导致内存泄漏。

  6. ​事务控制​

    在事务中使用游标时,注意 COMMITROLLBACK 可能影响游标状态。

相关推荐
呉師傅5 分钟前
【使用技巧】Adobe Photoshop 2024调整缩放与布局125%后出现点菜单项漂移问题的简单处理
运维·服务器·windows·adobe·电脑·photoshop
玄同76513 分钟前
SQLite + LLM:大模型应用落地的轻量级数据存储方案
jvm·数据库·人工智能·python·语言模型·sqlite·知识图谱
吾日三省吾码14 分钟前
别只会“加索引”了!这 3 个 PostgreSQL 反常识优化,能把性能和成本一起打下来
数据库·postgresql
chian-ocean16 分钟前
百万级图文检索实战:`ops-transformer` + 向量数据库构建语义搜索引擎
数据库·搜索引擎·transformer
小Tomkk35 分钟前
数据库 变更和版本控制管理工具 --Bytebase 安装部署(linux 安装篇)
linux·运维·数据库·ci/cd·bytebase
getapi1 小时前
Ubuntu 22.04 服务器的系统架构是否为 amd64 x86_64
linux·服务器·ubuntu
qq_12498707531 小时前
基于JavaWeb的大学生房屋租赁系统(源码+论文+部署+安装)
java·数据库·人工智能·spring boot·计算机视觉·毕业设计·计算机毕业设计
消失的旧时光-19431 小时前
Linux 入门核心命令清单(工程版)
linux·运维·服务器
艾莉丝努力练剑1 小时前
【Linux:文件】Ext系列文件系统(初阶)
大数据·linux·运维·服务器·c++·人工智能·算法
倒流时光三十年2 小时前
SpringBoot 数据库同步 Elasticsearch 性能优化
数据库·spring boot·elasticsearch