MYSQL学习拓展一:MySQL 存储过程之游标的使用!

时间:2023-03-09 07:45:18
MYSQL学习拓展一:MySQL 存储过程之游标的使用!

一、MySQL游标的概念

  游标介绍:

      MySQL的游标(cursor)是一个重要的概念,通过查找资料与自己的理解,主要得出以下几点关于自己的理解。

        有数据缓冲的思想:游标的设计是一种数据缓冲区的思想,用来存放SQL语句执行的结果

        先有数据基础:游标是在先从数据表中检索出数据之后才能继续灵活操作的技术。

         类似于指针:游标类似于指向数据结构堆栈中的指针,用来pop出所指向的数据,并且只能每次取一个。

  游标优缺点:

    游标的优点:

      因为游标是针对行操作的,所以对从数据库中select查询得到的每一行可以进行分开的独立的相同或不同的操作,是一种分离的思想。可以满足对某个结果行进行特殊的操作。

     游标与基于游标位置的增删改查能力。 MySQL数据库中没有专门描述一行的表达形式,但这是需要的,所以,个人理解的话,我觉得游标是在关系数据库这种面向集合的系统中抽离出来,

    单独针对行进行表达(也可以理解成网上资料说的:游标是面向集合与面向行的设计思想之间的一种桥梁

    游标缺点:

      游标的缺点是针对有点而言的,也就是只能一行一行操作,在数据量大的情况下,是不适用的,速度过慢。这里有个比喻就是:当你去ATM存钱是希望一次性存完呢,

    还是100一张一张的存,这里的100一张一张存就是游标针对行的操作。 数据库大部分是面对集合的,业务会比较复杂,而游标使用会有死锁,影响其他的业务操作,不可取。 当数据量大时,使用游标会造成内存不足现象。

  游标的使用场景

      针对游标的优缺点,我总结游标的使用场景,主要用在循环处理、存储过程、函数中使用,用来查询结果集,就比如:我们需要从表中循环判断并得到想要的结果集,这时候使用游标操作很方便速度也很快。

二、游标的使用

  游标的使用步骤

      游标的使用一般分为5个步骤,主要是:定义游标->打开游标->使用游标->关闭游标->释放游标。

      定义游标

        语法为:

DECLARE <游标名> CURSOR FOR select语句;

      打开游标

        打开游标很简单就是下面的语句

open <游标名>    

      使用游标

        使用游标需要用关键字fetch来取出数据,然后取出的数据需要有存放的地方,我们需要用declare声明变量存放列的数据其语法格式为:

declare 变量1 数据类型(与列值的数据类型相同)
declare 变量2 数据类型(与列值的数据类型相同)
declare 变量3 数据类型(与列值的数据类型相同)
FETCH [NEXT | PRIOR | FIRST | LAST] FROM <游标名> [ INTO 变量名1,变量名2,变量名3[,…] ]

        说明:

          NEXT:取下一行的数据,游标一开始默认的第一行之前,故要让游标指向第一行,就必须第一次就执行FETCH NEXT操作

          INTO:将一行中每个对应的列下的数据放到与列 的数据类型相同的变量中。

      关闭游标:

        很简单的使用语句:

close <游标名>;

      释放游标:

deallocate <变量名>;

  具体示例:

      未使用循环的游标实例:

 --默认数据
DROP TABLE IF EXISTS `shops_info`;
CREATE TABLE `shops_info` (
`pid` int(11) NOT NULL,
`name` varchar(20) NOT NULL,
`price` int(11) NOT NULL,
`pdesc` varchar(20) NOT NULL,
PRIMARY KEY (`pid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `shops_info` VALUES
(1,'手机',2500,'打电话'),
(2,'电话机',5000,'看电视'),
(3,'电饭煲',400,'煮饭');

默认数据测试

        具体操作:

 --查询shops_info第二行数据的全部信息
drop procedure if exists cursor_test;
delimiter //
create procedure cursor_test()
begin
-- 声明与列的类型相同的四个变量
declare id varchar(20);
declare pname varchar(20);
declare pprice varchar(20);
declare pdescription varchar(20); -- 1、定义一个游标mycursor
declare mycursor cursor for
select *from shops_info WHERE pid=2;
-- 2、打开游标
open mycursor;
-- 3、使用游标获取列的值
fetch mycursor into id,pname,pprice,pdescription;
-- 4、显示结果
select id,pname,pprice,pdescription;
-- 5、关闭游标
close mycursor;
end;
//
delimiter ;
call cursor_test();

无循环游标测试

      使用循环的游标实例:

 CREATE TABLE IF NOT EXISTS `store` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`count` int(11) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7; INSERT INTO `store` (`id`, `name`, `count`) VALUES
(1, 'android', 15),
(2, 'iphone', 14),
(3, 'iphone', 20),
(4, 'android', 5),
(5, 'android', 13),
(6, 'iphone', 13);

默认数据

        具体操作

 --统计这个表中'iphone'一共多少台
delimiter //
drop procedure if exists StatisticStore;
CREATE PROCEDURE StatisticStore()
BEGIN
declare c int;
declare n varchar(20);
declare total int default 0; declare done int default false;
declare cur cursor for select name,count from store where name = 'iphone';
declare continue HANDLER for not found set done = true; open cur;
read_loop:loop
fetch cur into n,c;
if done then
leave read_loop;
end if;
set total = total + c;
end loop;
close cur; select total;
END;
// delimiter ;
call StatisticStore();

有循环游标操作测试

        讲解:

--统计这个表中'iphone'一共多少台
delimiter //
drop procedure if exists StatisticStore;
CREATE PROCEDURE StatisticStore()
BEGIN
--创建接收游标数据的变量
declare c int;
declare n varchar(20);
--创建总数变量
declare total int default 0;
--创建结束标志变量
declare done int default false;
--创建游标
declare cur cursor for select name,count from store where name = 'iphone';
--指定游标循环结束时的返回值
declare continue HANDLER for not found set done = true;
--设置初始值
set total = 0;
--打开游标
open cur;
--开始循环游标里的数据
read_loop:loop
--根据游标当前指向的一条数据
fetch cur into n,c;
--判断游标的循环是否结束
if done then
leave read_loop; --跳出游标循环
end if;
--获取一条数据时,将count值进行累加操作,这里可以做任意你想做的操作,
set total = total + c;
--结束游标循环
end loop;
--关闭游标
close cur; --输出结果
select total;
END;
// --修改回默认结束符
delimiter ;
--调用存储过程
call StatisticStore();