MySQL 游标的使用
MySQL 游标
游标的特性
-
不敏感:数据库可以选择不复制结果集
-
只读
-
不滚动:游标只能向一方向前进,并且不可以跳过任何一行数据
游标的优点
-
游标是针对行操作的,对从数据库中 select 查询得到的结果集的 每一行可以
进行分开的独立的相同或者不相同的操作,是一种分离的思想。
游标的缺点
-
性能不高
-
只能一行一行操作
-
使用游标会产生死锁,造成内存开销大
游标的适用场景
-
存储过程
-
函数
-
触发器
-
事件
游标的操作
1、游标的定义
DECLARE 光标名称 CURSOR FOR 查询语法
declare cursor_name cursor for select_statement
2、打开游标
OPEN 光标名称
open cursor_name
3、取游标中的数据
FETCH 光标名称 INFO var_name [,var_name ].....
fetch cursor_name info var_name
4、关闭游标
CLOSE curso_name;
close 光标名称
5、释放游标
DEALLOCATE 光标名称
deallocate cursor_name;
游标示例
create table student( stuId int primary key auto_increment, stuName varchar(20), stuSex varchar(2), stuAge int )default charset=utf8; insert into student(stuName,stuSex,stuAge) values ('小明','男',20), ('小花','女',19), ('大赤','男',20), ('可乐','男',19), ('莹莹','女',19);
普通案例
delimiter //
create procedure p1()
begin
declare id int;
declare name varchar(100) character set utf8;
declare done int default 0;
-- 声明游标
declare mc cursor for select stuId,stuName from student where stuAge >19;
declare continue handler for not found set done = 1;
-- 打开游标
open mc;
-- 获取结果
fetch mc into id,name;
-- 这里是为了显示获取结果
select id,name;
-- 关闭游标
close mc;
end //
delimiter ;
试使用 三种方式 使用游标创建一个存储过程,统计年龄大于19的记录的数量
Loop循环
-- 定义语法结束符号
delimiter //
-- 创建一个 名称为 p2 的存储过程
create procedure p2()
begin
-- 创建 用于接收游标值的变量
declare id,age,total int;
-- 注意 接收游标值为中文时 需要 给变量 指定 字符集为utf8
declare name,sex varchar(20) character set utf8;
-- 游标结束的标志
declare done int default 0;
-- 声明游标
declare cur cursor for select stuId,stuName,stuSex,stuAge from student where stuAge > 19;
-- 指定游标循环结束时的返回值
declare continue handler for not found set done =1;
-- 打开游标
open cur;
-- 初始化 变量
set total = 0;
-- loop 循环
xxx:loop
-- 根据游标当前指向的一条数据
fetch cur into id,name,sex,age;
-- 当 游标的返回值为 1 时 退出 loop循环
if done = 1 then
leave xxx;
end if;
-- 累计
set total = total + 1;
end loop;
-- 关闭游标
close cur;
-- 输出 累计的结果
select total;
end //
delimiter ;
while 循delimiter /-- 创建一个 名称为 p3 的存储过程create procedure p3()
delimiter //
-- 创建一个 名称为 p3 的存储过程
create procedure p3()
begin
-- 创建 用于接收游标值的变量
declare id,age,total int;
-- 注意 接收游标值为中文时 需要 给变量 指定 字符集为utf8
declare name,sex varchar(20) character set utf8;
-- 游标结束的标志
declare done int default 0;
-- 声明游标
declare cur cursor for select stuId,stuName,stuSex,stuAge from student where stuAge > 19;
-- 指定游标循环结束时的返回值
declare continue handler for not found set done = 1;
-- 打开游标
open cur;
-- 初始化 变量
set total = 0;
-- while 循环
while done != 1 do
fetch cur into id,name,sex,age;
if done != 1 then
set total = total + 1;
end if;
end while;
-- 关闭游标
close cur;
-- 输出 累计的结果
select total;
end //
delimiter ;
repeat 循环
delimiter //
-- 创建一个 名称为 p3 的存储过程
create procedure p3()
begin
-- 创建 用于接收游标值的变量
declare id,age,total int;
-- 注意 接收游标值为中文时 需要 给变量 指定 字符集为utf8
declare name,sex varchar(20) character set utf8;
-- 游标结束的标志
declare done int default 0;
-- 声明游标
declare cur cursor for select stuId,stuName,stuSex,stuAge from student where stuAge > 19;
-- 指定游标循环结束时的返回值
declare continue handler for not found set done = 1;
-- 打开游标
open cur;
-- 初始化 变量
set total = 0;
-- repeat 循环
repeat
fetch cur into id,name,sex,age;
if done != 1 then
set total = total + 1;
end if;
until done = 1
end repeat;
-- 关闭游标
close cur;
-- 输出 累计的结果
select total;
end //
delimiter ;
while 循环 repeat 循环 不知道 是不是理解错了 会多循环一次…(还是游标多走了一次…) ----> 进行累加计算时,先判断游标的结束标志(done) 是否是为1