游标从入门到实战:MySQL逐行处理的4步法与5大避坑指南!

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS Agent(兼容OpenClaw),2核4GB
简介: 数据库小学妹带你轻松掌握MySQL游标!游标是逐行处理结果集的“智能指针”,适用于个性化积分计算、字段拆分、批量发信等集合操作无法胜任的场景。本文详解游标四步法(声明/打开/提取/关闭)、实战案例及四大避坑指南,强调“能不用则不用”——性能优先,集合操作为首选!

📌 今日关键词:游标、逐行处理、结果集遍历、存储过程、MySQL进阶

大家好呀!我是​数据库小学妹​👋

前面我们学的SQL都是​集合操作​——一次对整张表或整个结果集进行操作。但有时候,我们需要​一行一行地处理数据​:

  • 对每个用户的积分进行不同规则的累加
  • 把某个字段的值拆分成多行插入另一张表
  • 批量发送邮件,每封内容根据用户定制

这时候,普通的SQL就不够用了。数据库给我们准备了 ​“游标 ——就像一只“逐行扫描仪”,可以一行一行地读取、处理和操作数据。游标看起来有点“高级”,但别担心,小学妹会用生活化的例子,带你从原理到实战,彻底搞懂这个数据库中的“智能指针”!

一、什么是游标?

游标(Cursor) 是一种​逐行处理结果集的机制​。你可以把它想象成一个可移动的“指针”,它指向结果集中的某一行,然后你可以移动指针,每次处理一行。

💡 类比:你有一摞试卷(结果集),你想逐张批改。游标就是你的“手”,可以一张一张拿起来看,改完后放一边,再拿下一张。

📢什么时候用游标?

  • 需要对每一行执行​不同的计算​(不能用一个UPDATE搞定)
  • 需要把一行数据拆成多行(如把“苹果,香蕉”拆成两行)
  • 需要调用外部程序(如发邮件、调API)对每行数据单独操作

🔍游标的核心思想:

将查询结果集视为可移动的“数据队列”,通过游标指针逐行读取、处理,甚至修改数据,实现精细化的流程控制! 它打破了SQL“集合操作”的限制,让数据库也能像编程一样逐行处理逻辑!

⚠️ ​警告​:游标​性能较差​,能不用就不用。大数据量下尽量避免,优先用集合操作(UPDATEINSERT...SELECT)。

二、游标的基本步骤(4步法)

在存储过程中,游标的使用分为四步:

步骤 关键字 说明
1. 声明游标 DECLARE 游标名 CURSOR FOR SELECT... 定义游标要遍历的结果集
2. 打开游标 OPEN 游标名 初始化,准备读取数据
3. 提取数据 FETCH 游标名 INTO 变量列表 获取当前行的值,并存储到变量
4. 关闭游标 CLOSE 游标名 释放资源

通常还需要一个 ​NOT FOUND​ 处理程序​,用于判断是否已经取完所有行。

三、游标的使用场景

📊 批量更新+条件判断:

  • 场景:更新员工工资时,根据部门不同,涨幅规则不同。
  • 方案:用游标遍历员工表,对每条记录判断部门后计算新工资。

📊数据导出与转换:

  • 场景:需要将数据库中的订单数据逐条导出到Excel,并添加自定义备注。
  • 方案:通过游标逐行读取订单,生成格式化数据。

📊复杂报表生成:

  • 场景:需要按学生分数段生成统计报表,并附加评语(如“优秀”“需加强”)。
  • 方案:游标遍历成绩表,动态计算评语并写入临时表。

📊事务中的补偿逻辑:

  • 场景:转账时,若某条记录失败,需回滚并标记错误日志。
  • 方案:用游标逐笔处理转账,异常时通过游标定位到问题记录。

四、实战:用游标给每个用户增加不同积分

假设有一个用户表 users(id, name, score),需求是:

  • 金牌会员(level='gold')增加 100 积分
  • 银牌会员(level='silver')增加 50 积分
  • 普通会员(level='normal')增加 10 积分

如果用普通SQL,需要写三个 UPDATE。这里用游标演示“逐行判断”的过程。

🌰创建示例表

CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(20),
    level VARCHAR(10),
    score INT
);

INSERT INTO users VALUES (1, '小明', 'gold', 0), (2, '小红', 'silver', 0), (3, '小刚', 'normal', 0);

📝编写存储过程 + 游标

DELIMITER //

CREATE PROCEDURE update_score_cursor()
BEGIN
    -- 声明变量,用于存储当前行的数据
    DECLARE done INT DEFAULT 0;
    DECLARE v_id INT;
    DECLARE v_level VARCHAR(10);
    DECLARE v_score INT;

    -- 声明游标
    DECLARE cur CURSOR FOR SELECT id, level FROM users;

    -- 声明当游标读取不到数据时,设置 done = 1
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    -- 打开游标
    OPEN cur;

    -- 开始循环
    read_loop: LOOP
        -- 提取一行数据到变量
        FETCH cur INTO v_id, v_level;

        -- 如果没数据了,退出循环
        IF done THEN
            LEAVE read_loop;
        END IF;

        -- 根据等级计算新积分
        CASE v_level
            WHEN 'gold' THEN SET v_score = 100;
            WHEN 'silver' THEN SET v_score = 50;
            ELSE SET v_score = 10;
        END CASE;

        -- 更新该用户的积分
        UPDATE users SET score = v_score WHERE id = v_id;

    END LOOP;

    -- 关闭游标
    CLOSE cur;
END //

DELIMITER ;

📅调用游标

CALL update_score_cursor();
SELECT * FROM users;

结果:

id name level score
1 小明 gold 100
2 小红 silver 50
3 小刚 normal 10

五、更实用的例子:将逗号分隔的字符串拆分为多行

假设有一张 student_courses 表,其中 courses 字段存着“数学,语文,英语”,你需要把它拆分成多行插入到 student_course 表中。

-- 原始表
CREATE TABLE student_courses (
    student_id INT,
    courses VARCHAR(100)
);
INSERT INTO student_courses VALUES (1, '数学,语文,英语');

-- 目标表
CREATE TABLE student_course (
    student_id INT,
    course_name VARCHAR(20)
);

游标 + 字符串处理函数实现拆分(略简化版):

DELIMITER //

CREATE PROCEDURE split_courses()
BEGIN
    DECLARE done INT DEFAULT 0;
    DECLARE v_stu_id INT;
    DECLARE v_courses VARCHAR(100);
    DECLARE v_course VARCHAR(20);
    DECLARE comma_pos INT;

    DECLARE cur CURSOR FOR SELECT student_id, courses FROM student_courses;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    OPEN cur;

    read_loop: LOOP
        FETCH cur INTO v_stu_id, v_courses;
        IF done THEN LEAVE read_loop; END IF;

        -- 循环取出每个逗号前的子串
        WHILE LENGTH(v_courses) > 0 DO
            SET comma_pos = LOCATE(',', v_courses);
            IF comma_pos = 0 THEN
                SET v_course = v_courses;
                SET v_courses = '';
            ELSE
                SET v_course = SUBSTRING(v_courses, 1, comma_pos - 1);
                SET v_courses = SUBSTRING(v_courses, comma_pos + 1);
            END IF;
            INSERT INTO student_course VALUES (v_stu_id, TRIM(v_course));
        END WHILE;

    END LOOP;

    CLOSE cur;
END //

DELIMITER ;

调用后,student_course 表会生成三行:(1, '数学'), (1, '语文'), (1, '英语')。

六、游标避坑指南

💢坑1:游标​​滥用导致性能雪崩​:

  • 避坑​:能用集合操作(如UPDATE/DELETE语句)解决的,绝不使用游标!游标是“最后手段”。
  • 优化技巧​:若必须用,限制处理行数,或分批次处理。

💢坑2:资源泄漏​:

  • 避坑​:必须显式关闭游标!未关闭的游标会占用数据库连接资源,导致系统卡顿。
  • 最佳实践​:在存储过程结尾或异常处理中确保关闭游标。

💢坑3:嵌套游标​​陷阱​:

  • 避坑​:避免在循环内嵌套游标,极易导致性能噩梦。
  • 替代方案​:用临时表或变量暂存数据,减少嵌套。

💢坑4:忽略事务影响​:

  • 避坑​:游标操作通常在事务中,需注意隔离级别(如可重复读 vs 读已提交),避免数据不一致。

七、今日学习心得

  1. 游标逐行处理​,适合那些“每一行都要特殊对待”的场景
  2. 四步法​:声明 → 打开 → 提取 → 关闭,别忘了 NOT FOUND 处理
  3. 性能杀手,慎用​:优先思考是否能用集合操作代替

👋 我是数据库小学妹一个用设计师思维学数据库的转行人。我们一起,把复杂的技术变得简单有趣!💕

本文为个人学习总结,所有命令均在MySQL​*​ 8.0环境下验证。游标是把“双刃剑”,在使用过程中需平衡它的优缺点,勿滥用!

相关文章
|
2天前
|
SQL 缓存 关系型数据库
主从延迟的5大“元凶”+3个排查命令,别再让从库拖后腿
数据库小学妹详解MySQL主从延迟:5大元凶(硬件弱、写压大、慢查询、网络差、大事务)+3条核心排查命令(SHOW SLAVE STATUS等),助你快速定位、精准优化,避坑生产故障!
|
15天前
|
SQL 关系型数据库 MySQL
锁机制(Locking):解决数据库“死锁”与“阻塞”的终极指南
数据库小学妹带你轻松掌握锁机制!🔒 详解行锁/表锁、共享锁/排他锁、记录/间隙/临键锁,剖析死锁成因与避坑技巧(如索引缺失、长事务、间隙锁副作用),附MySQL实战命令。
|
22天前
|
安全 关系型数据库 MySQL
用户权限管理,把好数据库的第一道门
数据库小学妹带你轻松掌握MySQL权限管理!通过创建用户、授/回收权限(GRANT/REVOKE)、设置安全边界(localhost/%/IP段)和最小权限原则,实现角色分离与事前防护。牢记FLUSH PRIVILEGES刷新生效,告别root滥用,守好数据大门!
|
关系型数据库 MySQL Java
基于 SpringBoot+Vue 的家政服务管理平台(附源码)
基于 SpringBoot+Vue 的家政服务管理平台(附源码)
|
1月前
|
SQL 关系型数据库 MySQL
数据量大查询慢?索引让你的SQL秒级响应!|转行学DB第9天
用生活化比喻(如字典目录)详解索引原理:它通过B+树结构加速查询,避免全表扫描;涵盖创建、查看、删除索引方法,联合索引的最左前缀原则,以及读写平衡等实战要点——让查询从“等几秒”变“秒出”!
数据量大查询慢?索引让你的SQL秒级响应!|转行学DB第9天
|
16天前
|
SQL 关系型数据库 MySQL
EXPLAIN 执行计划:一眼看穿你的SQL慢在哪
数据库小学妹带你轻松掌握SQL性能诊断!通过EXPLAIN查看执行计划,精准识别索引失效、全表扫描(ALL)、key为NULL等瓶颈。聚焦type、key、rows等6个关键字段,结合实战案例与避坑指南(如函数滥用、最左前缀破坏),让优化有的放矢。学完即用,告别盲目调优!
|
2月前
|
人工智能 Linux API
OpenClaw内网离线方案:Windows/Mac/Linux/阿里云部署+千问/Coding Plan/Ollama配置实战指南
OpenClaw(龙虾)作为轻量化AI Agent工具,在自动化任务、文件处理、代码生成、信息检索等场景中表现突出,但云端API高额Token费用与数据隐私问题,一直是个人与企业使用的阻碍。通过本地部署Ollama运行千问等开源大模型,可实现OpenClaw完全离线使用,达成Token自由与数据安全双重目标。本文基于2026年最新实践,完整覆盖本地Windows11/MacOS/Linux部署、阿里云云端部署、Ollama本地模型对接、阿里云千问API与免费Coding Plan配置,同时提供全流程代码命令与高频问题解决方案,打造可直接落地的私有化AI Agent体系。
2440 5
|
存储 数据处理 Python
Python读写文件
Python读写文件
499 61
|
SQL 存储 关系型数据库
17. Mysql 动态SQL
17. Mysql 动态SQL
591 1

热门文章

最新文章