游标
有时,需要在检索出来的行中前进或后退一行或多行 - 游标是一个存储在MySQL服务器上的数据库查询 - 它不是一条
SELECT
语句,而是被该语句检索出来的结果集 - 在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据 游标主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或做出更改MySQL的游标只能用于存储过程和函数
使用游标
- 几个明确的步骤:
- 声明(定义)游标
- 一旦声明后,必须打开游标以供使用
- 这个过程用前面定义的
SELECT
语句把数据实际检索出来
- 这个过程用前面定义的
- 对于填有数据的游标,根据需要取出(检索)各行
- 在结束游标使用时,必须关闭游标
创建游标
- 游标使用
DECLARE
语句创建,并且定义相应的SELECT
语句,根据需要带WHERE
和其他字句 - 在声明时即确定游标中包含的数据
打开和关闭游标
- 打开游标:
OPEN cursor_name;
- 在处理
OPEN
语句时执行查询,存储检索出的数据以供浏览和滚动
- 在处理
- 关闭游标:
CLOSE cursor_name;
CLOSE
释放游标使用的所有内部内存和资源,因此在每个游标不在需要时都应该关闭在一个游标关闭后,如果没有重新打开,则不能使用它 但是,声明过的游标无需再次声明,使用
OPEN
语句直接打开,即可使用
隐含关闭:如果不明确关闭游标,则MySQL将会在到达
END
语句时自动关闭
游标数据的使用
- 一个游标打开后,可以使用
FETCH
语句分别访问他的每一行FETCH
指定检索什么数据,检索出来的数据存储在什么地方
- 从游标中检索单个行
- 循环检索数据,从第一行到最后一行
create procedure processorders() begin DECLARE done BOOLEAN DEFAULT 0; DECLARE o INT; declare ordernumbers cursor for select order_num from orders; -- declare continue handler DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; open ordernumbers; REPEAT FETCH ordernumbers INTO o; UNTIL done END REPEAT; close ordernumbers; end;
- 本例中的
FETCH
语句在REPEAT
中,它将反复执行直到done
为真 DECLARE done BOOLEAN DEFAULT 0;
- 用默认值0为
done
赋值
- 用默认值0为
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
- 作用:设置结束时为真
- 定义了一个
CONTINUE HANDLER
,这是一个在条件出现时被执行的代码- 当
SQLSTATE '02000'
出现时,SET done = 1
SQLSTATE '02000'
是一个未找到的条件,当没有更多行供循环而不能继续时,出现改条件 错误代码:MySQL :: MySQL 8.0 Reference Manual :: B Error Messages and Common Problems
- 当
- 本例中的
DECLARE语句的次序: DECLARE语句定义的局部变量必须定义在任意游标或句柄之前定义,而句柄必须在游标之后定义
通常
REPEAT
语句的语法使它更适合于对游标进行循环,同时,也支持使用它来重复执行代码,直到使用LEAVE
语句手动退出为止
终版代码
create procedure processorders()
begin
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE t DECIMAL(8,2);
declare ordernumbers cursor
for
select order_num from orders;
-- declare continue handler
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
CREATE TABLE IF NOT EXISTS ordertotals
(order_num INT, total DECIMAL(8,2));
open ordernumbers;
REPEAT
FETCH ordernumbers INTO o;
CALL ordertotal(o, 1, t);
INSERT INTO ordertotals(order_num, total)
VALUES(o,t);
UNTIL done END REPEAT;
close ordernumbers;
end;