在前一篇文章中【一文搞懂 MySQL 存储过程-CSDN博客】,我们已经系统讲解了 MySQL 存储过程 ,包括参数类型、变量、流程控制等内容。但在实际开发中,还有一类需求是单条 SQL 无法完成的 ------👉 需要对查询结果"一行一行地处理"。这样就用到了游标(Cursor)。
用一句话说:
游标是存储过程中,用来"逐行处理查询结果集"的机制。
目录
[1. 声明游标](#1. 声明游标)
[2. 打开游标](#2. 打开游标)
[3. 读取游标数据](#3. 读取游标数据)
[4. 关闭游标](#4. 关闭游标)
[5. 声明句柄Handler](#5. 声明句柄Handler)
一、为什么需要游标?
在MySQL中,大多数操作都是面向集合的,比如:
sql
UPDATE emp SET sal = sal + 100 WHERE deptno = 10;
这样虽然写法高效,但是这种方式只能处理"清一色"的数据,面对多种不同类的记录,没有办法用单一规则实现完全更新。
也就是说,遇到下面的情况就需要用到游标了:
-
不同记录需要不同的处理逻辑
-
需要在处理过程(存储过程/函数)中做判断、计算、日志记录
-
需要逐行读取并操作数据
二、什么是游标
游标是对查询结果集的一种控制结构,允许我们:
-
一行一行地访问查询结果
-
像"指针"一样向下移动
-
配合循环逐条处理数据
这里可以把游标理解为指向查询结果集的"指针变量"。
三、游标的使用
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循环