MySQL 游标的定义与使用方式
创建游标
首先在MySql中创建一张数据表:
CREATETABLEIFNOTEXISTS`store`( `id`int(11)NOTNULLAUTO_INCREMENT, `name`varchar(20)NOTNULL, `count`int(11)NOTNULLDEFAULT'1', PRIMARYKEY(`id`) )ENGINE=InnoDBDEFAULTCHARSET=latin1AUTO_INCREMENT=7; INSERTINTO`store`(`id`,`name`,`count`)VALUES (1,'android',15), (2,'iphone',14), (3,'iphone',20), (4,'android',5), (5,'android',13), (6,'iphone',13);
我们现在要用存储过程做一个功能,统计iphone的总库存是多少,并把总数输出到控制台。
--在windows系统中写存储过程时,如果需要使用declare声明变量,需要添加这个关键字,否则会报错。 delimiter// dropprocedureifexistsStatisticStore; CREATEPROCEDUREStatisticStore() BEGIN --创建接收游标数据的变量 declarecint; declarenvarchar(20); --创建总数变量 declaretotalintdefault0; --创建结束标志变量 declaredoneintdefaultfalse; --创建游标 declarecurcursorforselectname,countfromstorewherename='iphone'; --指定游标循环结束时的返回值 declarecontinueHANDLERfornotfoundsetdone=true; --设置初始值 settotal=0; --打开游标 opencur; --开始循环游标里的数据 read_loop:loop --根据游标当前指向的一条数据 fetchcurinton,c; --判断游标的循环是否结束 ifdonethen leaveread_loop;--跳出游标循环 endif; --获取一条数据时,将count值进行累加操作,这里可以做任意你想做的操作, settotal=total+c; --结束游标循环 endloop; --关闭游标 closecur; --输出结果 selecttotal; END; --调用存储过程 callStatisticStore();
fetch是获取游标当前指向的数据行,并将指针指向下一行,当游标已经指向最后一行时继续执行会造成游标溢出。
使用loop循环游标时,他本身是不会监控是否到最后一条数据了,像下面代码这种写法,就会造成死循环;
read_loop:loop fetchcurinton,c; settotal=total+c; endloop;
在MySql中,造成游标溢出时会引发mysql预定义的NOTFOUND错误,所以在上面使用下面的代码指定了当引发notfound错误时定义一个continue的事件,指定这个事件发生时修改done变量的值。
declarecontinueHANDLERfornotfoundsetdone=true;
所以在循环时加上了下面这句代码:
--判断游标的循环是否结束 ifdonethen leaveread_loop;--跳出游标循环 endif;
如果done的值是true,就结束循环。继续执行下面的代码。
使用方式
游标有三种使用方式:
第一种就是上面的实现,使用loop循环;
第二种方式如下,使用while循环:
dropprocedureifexistsStatisticStore1; CREATEPROCEDUREStatisticStore1() BEGIN declarecint; declarenvarchar(20); declaretotalintdefault0; declaredoneintdefaultfalse; declarecurcursorforselectname,countfromstorewherename='iphone'; declarecontinueHANDLERfornotfoundsetdone=true; settotal=0; opencur; fetchcurinton,c; while(notdone)do settotal=total+c; fetchcurinton,c; endwhile; closecur; selecttotal; END; callStatisticStore1();
第三种方式是使用repeat执行:
dropprocedureifexistsStatisticStore2; CREATEPROCEDUREStatisticStore2() BEGIN declarecint; declarenvarchar(20); declaretotalintdefault0; declaredoneintdefaultfalse; declarecurcursorforselectname,countfromstorewherename='iphone'; declarecontinueHANDLERfornotfoundsetdone=true; settotal=0; opencur; repeat fetchcurinton,c; ifnotdonethen settotal=total+c; endif; untildoneendrepeat; closecur; selecttotal; END; callStatisticStore2();
游标嵌套
在mysql中,每个beginend块都是一个独立的scope区域,由于MySql中同一个error的事件只能定义一次,如果多定义的话在编译时会提示Duplicatehandlerdeclaredinthesameblock。
dropprocedureifexistsStatisticStore3; CREATEPROCEDUREStatisticStore3() BEGIN declare_nvarchar(20); declaredoneintdefaultfalse; declarecurcursorforselectnamefromstoregroupbyname; declarecontinueHANDLERfornotfoundsetdone=true; opencur; read_loop:loop fetchcurinto_n; ifdonethen leaveread_loop; endif; begin declarecint; declarenvarchar(20); declaretotalintdefault0; declaredoneintdefaultfalse; declarecurcursorforselectname,countfromstorewherename='iphone'; declarecontinueHANDLERfornotfoundsetdone=true; settotal=0; opencur; iphone_loop:loop fetchcurinton,c; ifdonethen leaveiphone_loop; endif; settotal=total+c; endloop; closecur; select_n,n,total; end; begin declarecint; declarenvarchar(20); declaretotalintdefault0; declaredoneintdefaultfalse; declarecurcursorforselectname,countfromstorewherename='android'; declarecontinueHANDLERfornotfoundsetdone=true; settotal=0; opencur; android_loop:loop fetchcurinton,c; ifdonethen leaveandroid_loop; endif; settotal=total+c; endloop; closecur; select_n,n,total; end; begin end; endloop; closecur; END; callStatisticStore3();
上面就是实现一个嵌套循环,当然这个例子比较牵强。凑合看看就行。。
动态SQL
Mysql支持动态SQL的功能,
set@sqlStr='select*fromtablewherecondition1=?'; prepares1for@sqlStr; --如果有多个参数用逗号分隔 executes1using@condition1; --手工释放,或者是connection关闭时,server自动回收 deallocateprepares1;
以上就是MySQL游标的定义与使用方式的详细内容,更多关于MySQL游标的资料请关注毛票票其它相关文章!