MySQL 游标(Cursor)详解:与存储过程的结合使用

在前一篇文章中【一文搞懂 MySQL 存储过程-CSDN博客】,我们已经系统讲解了 MySQL 存储过程 ,包括参数类型、变量、流程控制等内容。但在实际开发中,还有一类需求是单条 SQL 无法完成的 ------👉 需要对查询结果"一行一行地处理"。这样就用到了游标(Cursor)。

用一句话说:

游标是存储过程中,用来"逐行处理查询结果集"的机制。


目录

一、为什么需要游标?

二、什么是游标

三、游标的使用

[1. 声明游标](#1. 声明游标)

[2. 打开游标](#2. 打开游标)

[3. 读取游标数据](#3. 读取游标数据)

[4. 关闭游标](#4. 关闭游标)

[5. 声明句柄Handler](#5. 声明句柄Handler)

(1)句柄是什么

(2)句柄的标准写法

四、游标举例


一、为什么需要游标?

在MySQL中,大多数操作都是面向集合的,比如:

sql 复制代码
UPDATE emp SET sal = sal + 100 WHERE deptno = 10;

这样虽然写法高效,但是这种方式只能处理"清一色"的数据,面对多种不同类的记录,没有办法用单一规则实现完全更新。

也就是说,遇到下面的情况就需要用到游标了

  1. 不同记录需要不同的处理逻辑

  2. 需要在处理过程(存储过程/函数)中做判断、计算、日志记录

  3. 需要逐行读取并操作数据

二、什么是游标

游标是对查询结果集的一种控制结构,允许我们:

  • 一行一行地访问查询结果

  • 像"指针"一样向下移动

  • 配合循环逐条处理数据

这里可以把游标理解为指向查询结果集的"指针变量"。

三、游标的使用

1. 声明游标

这里要知道++游标一般在存储过程中声明++。

sql 复制代码
DECLARE 游标名 CURSOR FOR 查询语句;

2. 打开游标

sql 复制代码
OPEN 游标名;

打开游标后,MySQL 会执行游标中定义的查询语句,并生成结果集。

3. 读取游标数据

sql 复制代码
FETCH 游标名 INTO 存储变量1 [, 变量2...];

这里要注意:****(1)FETCH一次只读取一行;(2)存储变量个数必须和查询字段个数一致。

(3)读取≠输出,如果想输出结果的话,还要搭配select一起使用。

4. 关闭游标

sql 复制代码
CLOSE 游标名;

使用完游标之后需要关闭游标,用于释放内存和资源。

5. 声明句柄Handler

(1)句柄是什么

当游标读取到最后一行时,再次FETCH(读取)就会发生"找不到数据"的情况,如果不做处理,程序会直接报错。MySQL为了解决这个问题,MySQL提供了CONTINUE HANDLER(继续执行处理器)。

(2)句柄的标准写法

sql 复制代码
DECLARE done INT DEFAULT 0;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

这样就可以在发生"NOT found"时自动设置开关变量done为1。

四、游标举例

假设有一张表名为emp,现在要遍历emp表中的员工姓名ename,每次读取一条后输出。

sql 复制代码
DROP PROCEDURE IF EXISTS testcursor;

CREATE PROCEDURE testcursor()
BEGIN
    -- 1. 声明结束标志变量
    DECLARE done INT DEFAULT 0;

    -- 2. 声明接收字段的变量
    DECLARE emp_name VARCHAR(20);

    -- 3. 声明游标
    DECLARE mycursor CURSOR FOR
    SELECT ename FROM emp;

    -- 4. 声明句柄(当游标读不到数据时触发)
    DECLARE CONTINUE HANDLER FOR NOT FOUND
    SET done = 1;

    -- 5. 打开游标
    OPEN mycursor;

    -- 6. 使用循环逐行读取游标数据
    WHILE done = 0 DO
        FETCH mycursor INTO emp_name;

        IF done = 0 THEN
            SELECT emp_name;
        END IF;
    END WHILE;

    CLOSE mycursor;
END;


call testcursor;

游标和句柄是相关联的,就体现在下面的过程中:

游标读不到数据 →→自动触发句柄 →→done自动设置为1 →→退出while循环

相关推荐
oradh1 小时前
Oracle TX 锁 Mode 4(Share)问题排查总结
数据库·oracle·tx 锁 mode 4·oracle tx 锁
2601_962065251 小时前
[MySQL] SQL优化之性能分析
java·sql·mysql
yi.Ist2 小时前
数据定义语言-DDL操作
数据库·学习·mysql·oracle·大海豚
阿kun要赚马内2 小时前
MySQL 索引基础
后端·mysql
2601_963282773 小时前
工程项目、政企采购为什么优先选择对讲机批量采购?
数据库
Doraemomo3 小时前
SQLite数据库
数据库·sqlite
2601_962177133 小时前
【MySQL篇】聚合查询,联合查询
android·java·mysql
云贝教育-郑老师3 小时前
MySQL 的“黑匣子“:Performance Schema 把数据库内部变成一张可查的表
数据库·mysql
这个DBA有点耶5 小时前
同城双活落地的三座山:网络延迟、脑裂预防、反向同步
数据库·架构·dba