在MySQL存储过程里,游标是用来逐行遍历查询结果集的重要工具。当我们需要对查询出来的每一行数据做不同处理时,使用游标会比一次性操作整个结果集更灵活。下面介绍在存储过程中声明、打开、读取和关闭游标的完整方法。
游标的基本使用步骤
在存储过程中使用游标通常包含四个步骤:声明游标、打开游标、读取数据和关闭游标。同时为了避免循环读取越界,还要配合声明一个 continue handler 来捕获 not found 状态。
1. 声明游标与处理程序
游标必须在变量声明之后、handler之前用 declare cursor 定义,并且要关联一个 select 语句。
drop procedure if exists demo_cursor;
delimiter //
create procedure demo_cursor()
begin
declare v_id int;
declare v_name varchar(50);
declare done int default 0;
-- 声明游标,绑定查询语句
declare cur cursor for
select id, name from users where age > 18;
-- 当读取不到数据时,将done设为1
declare continue handler for not found set done = 1;
open cur;
read_loop: loop
fetch cur into v_id, v_name;
if done then
leave read_loop;
end if;
-- 这里可以对每行数据做处理
insert into user_log(user_id, user_name)
values(v_id, v_name);
end loop;
close cur;
end //
delimiter ;
2. 打开与关闭游标
使用 open cur 执行游标关联的查询,使用 close cur 释放资源。游标打开后如果没有关闭,可能会造成连接资源占用。
3. 读取数据
fetch cur into 变量 每次取一行,把列值赋给变量。当没有更多行时,上面定义的 not found handler 会触发,将 done 改为 1,从而退出循环。
使用游标的注意事项
- 游标只能用于存储过程或函数中,不能在普通SQL里直接用。
- declare 的顺序必须是:变量、游标、handler。
- 如果循环里使用了 insert 或 update,要注意事务提交方式,避免大量数据导致长事务。
- 游标处理大数据集时性能一般,能写成集合操作就尽量不用游标。
常见错误示例
下面写法会报错,因为 handler 写在了游标之前:
-- 错误示例:handler在cursor之前声明 declare continue handler for not found set done = 1; declare cur cursor for select id from users;
正确顺序应反过来,先声明游标再声明 handler。
小结
在MySQL存储过程中,游标通过 declare cursor、open、fetch、close 配合 not found handler 实现逐行处理。掌握这种结构,就能应对大部分需要行级逻辑的数据维护任务。