李艳杰
(山东华宇工学院,山东 德州 253034)
数据库中会经常用到查询,查询的结果是符合条件的多条记录的集合。但有时在查询时并不需要把所有符合条件的记录全部取出,或是需要逐条获取记录的值,此时普通查询实现不了,需要用到游标来逐条读取记录值,并对逐条记录进行使用。在数据库中,游标是系统为用户开设的缓冲区域,存放SQL 语句的执行结果,实际上,游标是一种能从包括多条数据记录结果集中每次提取一条记录的机制,游标允许应用程序对查询语句select 返回的行结果集中每一条记录进行相同或不同的操作,而不是一次对整个结果集进行同一种操作,从而可以发挥每一条记录的作用。游标通常体现在存储过程中。
MySQL中使用declare 关键字来声明游标,其语法结构及解释如下所示:
Declare 游标名称 cursor for select语句。
注意:关键字是不能少的,游标名称符合标识符的定义即可。select语句根据需求不同,此时内存便分配一块空间来存储返回的结果集。这块空间也可以认为是一个虚表,这个虚表便是游标。
打开游标的关键字为open,其语法结构及解释如下所示:
Open 游标名称。
打开游标即激活查询并识别游标,此时游标中的指针指向查询出的结果集中第一行记录的前面。
使用游标的关键字为fetch和into,其语法结构及解释如下所示:
Fetch 游标名称 into 变量。
注意:第一次使用时,指针指向结果集中第一条记录并提取里面的值,每调用一次,指针会下移一条记录,此时的变量个数与select语句后面的字段个数一致。
关闭游标的关键字为close,其语法结构及解释如下所示:
Close 游标名称。
当游标指针指向最后一条记录之后,即不能提取数据时,此时需要关闭游标,释放资源,不能再用fetch来提取数据了。
游标是写在存储过程中的,有时数据量大,不清楚记录的行数,此时需要定义处理程序。定义处理程序说明如下:
declare 参数1 handler for 参数2 SQL语句。
参数1:exit退出当前程序,continue 继续执行程序。
参数2:not found 代表当fetch抓取不到数据时,即游标指针走到最后一条记录的后面,没有记录可以提取了。
SQL语句:set temp=1,注意temp是变量,必须提前声明,其值只能是0(false)或1(true)。
在ceshi1数据库下,建表。在create table book1(bid int,shl int,jg float),输入3条记录,代码如下:
Insert into book1 values(102,1,15),(103,3,5) ,(101,2,10);
3.2.1 建立案例anli7
建立存储过程anli7,获取book1表中的所有记录,并逐行获取进行显示。代码和解释如下:
create procedure anli7() -建立存储过程;
begin -把语句放到一个begin块内;
declare a,b int; -声明变量存放图书编号和数量;
declare c float; -声明变量存放图书价格;
declare c1 cursor for select * from book1; -声明游标;
open c1; -打开游标;
fetch c1 into a,b,c; -使用游标提取第一条记录;
select a,b,c; -显示a,b,c的值;
fetch c1 into a,b,c; -使用游标提取第二条记录;
select a,b,c; -显示a,b,c的值;
fetch c1 into a,b,c; -使用游标提取第三条记录;
select a,b,c; -显示a,b,c的值;
close c1; -关闭游标;
end // -此语句块结束。
完成之后,利用语句mysql> call anli7()//,执行存储过程,显示第一条记录的结果如图1所示:
图1 执行结果Fig.1 Execution results
此案例中,已经知道了此表中有3条记录,可以提取3次,假设不知道有几条记录,此时的解决办法是使用循环。由于用到循环,必须考虑循环退出条件,由于无法确定记录条数,所以退出条件无法写,需要定义处理程序,即当程序本身发现问题时,会自动去处理。以下用循环实现。
3.2.2 建立案例anli8
用循环获取book1表中的所有记录,并逐行获取进行显示。
create procedure anli8() -建立存储过程;
begin -把语句放到一个begin块内;
declare a,b int; -声明变量存放图书编号和数量;
declare c float; -声明变量存放图书价格;
declare temp int default 0; -声明一个变量,默认值为0;
declare c1 cursor for select * from book1; -声明游标;
declare exit handler for not found set temp=1; -not found代表拿不到数据。即select语句返回值为空。执行set语句,把原来的默认值0改为1,同时退出整个程序。即当游标通过循环取完记录,最终取不到记录时,退出循环。
open c1; -打开游标;
repeat -循环语句开始;
fetch c1 into a,b,c; -通过循环使用游标提取每一条记录;
select a,b,c; -显示a,b,c的值;
until temp=1 -循环结束条件;
end repeat; -退出循环;
close c1; -关闭游标;
end // --此语句块结束。
由此可见,通过循环获取每一条语句程序更简洁合理,因此在存储过程中绝大部分的游标是和循环结合使用的。
重点介绍了MySQL数据库中游标含义和使用游标的步骤及如何高效使用游标,并举例说明游标的具体使用,以便更方便地使用游标解决现实生活中的问题。