MySQL Cursor
495人浏览 / 0人评论
参考
https://blog.51cto.com/u_12260130/6178914
https://lifelmy.cn/post/2023_04_09_mysql_cursor/
定义
Cursor 就是游标,可以理解为 Java 集合迭代器的游标,或者数组的下标。在存储过程中对查询的数据进行处理时,由于 Select 返回的是个数据集,无法处理第一行、下一行、前十行的数据,除非每次修改 where 条件获得想要的那一条记录,而 Cursor 可以很方便的处理这种情况。
MySQL游标是只读的,不可滚动且不敏感的。
- 只读:无法通过游标更新表中的数据。
- 不可滚动:只能朝着一个方向挨个遍历,不能反向遍历;不能跳行或者跳转到特定行。
- 不敏感:有两种光标:敏感型游标和不敏感游标。敏感型光标指向实际数据,而不敏感型光标使用数据的临时副本。敏感型游标比不敏感游标执行得更快,因为它不必创建临时数据副本。但是,其他连接所做的任何更改都将影响敏感光标正在使用的数据。MySQL游标是不敏感的。
比较适合在刷数据或迁移数据时使用。
使用
Cursor 的使用分为如下四步:
- 声明游标
- 打开游标
- 获取数据
- 关闭游标
声明游标
DECLARE cursor_name CURSOR FOR select_statement
注意:
- 游标声明中,必须有一个 Select 语句;
- Select 语句中不能包含 into 关键字;
- 游标声明,必须在 handler 声明之前,在 变量 和 condition 声明之后;
- 在一个代码块中可以声明多个游标,但是多个游标的名字不能相同。
打开游标
OPEN cursor_name
获取数据
FETCH cursor_name INTO var_name [, var_name] ...
注意:
- fetch 中的 cursor_name 必须是开启状态;
- fetch 语句中,var_name 的数量要与声明语句中 Select 查询列的数量一致,保证每个列都有变量接收。
使用 fetch 获取游标中 Select 语句的下一条记录,并将游标前进一步。如果查询到数据,就将每列对应的值赋值给相应变量;如果已经到了数据集末尾,没有数据可以获取了,会产生一个值为 '02000' 的 SQLSTATE (NOT FOUND),此时可以声明一个 handler 来处理这种情况。
如果我们在一个代码块中有多个游标,那么一个游标 fetch 时如果产生 NOT FOUND,handler 的触发可能会对另一个游标产生影响。如果想避免这种影响,可以在多个 BEGIG…END 代码块中分别声明各自的handler,然后再操作游标,保证互不影响。
关闭游标
CLOSE cursor_name
- 如果关闭一个非开启状态的游标会报错;
- 对于声明在一个 BEGIN…END 中的游标,如果没有显示的使用 close 去关闭的话,执行到 END 会自动关闭游标。
示例
如下示例中,我们声明了两个游标 cur1 和 cur2,分别查询 id、data 和 i 字段;还声明了一个 CONTINUE handler,当其中一个游标访问到数据集末尾时,设置变量 done 为 TRUE,用于控制循环退出。
其中几个注意点:
- 声明游标必须在 handler 声明之前,在 变量 和 condition 声明之后;
- 多个游标名称不能重复;
- 使用游标前需要先打开游标;
- 游标中 select 列的数量,与 fetch into 变量数量一样;
- 使用完关闭游标。
CREATE PROCEDURE curdemo()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE a CHAR(16);
DECLARE b, c INT;
DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
OPEN cur2;
read_loop: LOOP
FETCH cur1 INTO a, b;
FETCH cur2 INTO c;
IF done THEN
LEAVE read_loop;
END IF;
IF b < c THEN
INSERT INTO test.t3 VALUES (a,b);
ELSE
INSERT INTO test.t3 VALUES (a,c);
END IF;
END LOOP;
CLOSE cur1;
CLOSE cur2;
END;
全部评论