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();

 

posted @ 2018-05-17 19:36  达尔文在思考  阅读(302)  评论(0编辑  收藏  举报