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 <变量名>;
具体示例:
未使用循环的游标实例:
1 --默认数据 2 DROP TABLE IF EXISTS `shops_info`; 3 CREATE TABLE `shops_info` ( 4 `pid` int(11) NOT NULL, 5 `name` varchar(20) NOT NULL, 6 `price` int(11) NOT NULL, 7 `pdesc` varchar(20) NOT NULL, 8 PRIMARY KEY (`pid`) 9 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 10 11 INSERT INTO `shops_info` VALUES 12 (1,'手机',2500,'打电话'), 13 (2,'电话机',5000,'看电视'), 14 (3,'电饭煲',400,'煮饭');
具体操作:
1 --查询shops_info第二行数据的全部信息 2 drop procedure if exists cursor_test; 3 delimiter // 4 create procedure cursor_test() 5 begin 6 -- 声明与列的类型相同的四个变量 7 declare id varchar(20); 8 declare pname varchar(20); 9 declare pprice varchar(20); 10 declare pdescription varchar(20); 11 12 -- 1、定义一个游标mycursor 13 declare mycursor cursor for 14 select *from shops_info WHERE pid=2; 15 -- 2、打开游标 16 open mycursor; 17 -- 3、使用游标获取列的值 18 fetch mycursor into id,pname,pprice,pdescription; 19 -- 4、显示结果 20 select id,pname,pprice,pdescription; 21 -- 5、关闭游标 22 close mycursor; 23 end; 24 // 25 delimiter ; 26 call cursor_test();
使用循环的游标实例:
1 CREATE TABLE IF NOT EXISTS `store` ( 2 `id` int(11) NOT NULL AUTO_INCREMENT, 3 `name` varchar(20) NOT NULL, 4 `count` int(11) NOT NULL DEFAULT '1', 5 PRIMARY KEY (`id`) 6 ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7; 7 8 INSERT INTO `store` (`id`, `name`, `count`) VALUES 9 (1, 'android', 15), 10 (2, 'iphone', 14), 11 (3, 'iphone', 20), 12 (4, 'android', 5), 13 (5, 'android', 13), 14 (6, 'iphone', 13);
具体操作
1 --统计这个表中'iphone'一共多少台 2 delimiter // 3 drop procedure if exists StatisticStore; 4 CREATE PROCEDURE StatisticStore() 5 BEGIN 6 declare c int; 7 declare n varchar(20); 8 declare total int default 0; 9 10 declare done int default false; 11 declare cur cursor for select name,count from store where name = 'iphone'; 12 declare continue HANDLER for not found set done = true; 13 14 open cur; 15 read_loop:loop 16 fetch cur into n,c; 17 if done then 18 leave read_loop; 19 end if; 20 set total = total + c; 21 end loop; 22 close cur; 23 24 select total; 25 END; 26 // 27 28 delimiter ; 29 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();