1、游标的概念:
一条sql 取出对应n条结果资源的接口/句柄,就是游标,沿着游标可以一次取出一行。
通俗说法:
我们写一条select查询语句,按理上会一下查询出所有的结果。但我们想对查询结果数据进行一条条获取并筛选,这时相当于对查询结果集进行筛选,这个过程就是游标。
2、使用游标的步骤
declare
游标名
cursor
for
select_statement
#
使用declare进行声明
open
游标名
#
打开游标
fetch
游标名
into
var1,var2[,...] #
fetch是获取游标当前指向的数据行,并将指针指向下一行,当游标已经指向最后一行时继续执行会造成游标溢出。
close
游标名
#
关闭游标
3、使用游标循环:
使用游标进行循环时,如果 当游标读到末尾,如果继续进行取值操作会发生报错。所以需要在游标读到末尾或末尾前,结束循环。
3.1、使用计数器来循环
drop procedure if exists test17;
delimiter $$
create procedure test17()
begin
declare orgId varchar(20) ;
declare orgName varchar(20);
declare parentOrgId varchar(20);
declare currentRow int default 1;
declare total int;
declare test0107 cursor for select org_id,org_name,parent_org_id from org_info where org_id BETWEEN '100001' and '100005' ; -- 定义游标
select count(1) into total from org_info where org_id BETWEEN '100001' and '100005' ;
open test0107; -- 打开游标
while currentRow <= total do
fetch test0107 into orgId,orgName,parentOrgId; -- 从游标中取值
-- insert IGNORE into org_info_0107 values(orgId,orgName,parentOrgId);
select orgId,orgName,parentOrgId;
set currentRow = currentRow+1;
end while;
close test0107; -- 关闭游标
end$$
delimiter ;
call test17();
select * from org_info_0107;
3.2、使用越界标志来控制循环
在mysql cursor中,可以声明declare continue handler
来操作1个越界标志
语法:
declare
continue/exist
handler
for
not
found statement;
continue和exit的区别:
continue : 若没有数据返回,程序继续,并将变量is_found 设为0。
exit : 若没有数据返回,退出程序,并将变量is_found 设为0。
drop procedure if exists test17;
delimiter $$
create procedure test17()
begin
declare orgId varchar(20) ;
declare orgName varchar(20);
declare parentOrgId varchar(20);
declare have boolean default true; -- 声明是否有下一行,默认有
declare test0107 cursor for select org_id,org_name,parent_org_id from org_info where org_id BETWEEN '100001' and '100005' ; -- 定义游标
declare CONTINUE HANDLER for not found set have = false;
open test0107; -- 打开游标
fetch test0107 into orgId,orgName,parentOrgId; -- 从游标中取值,f防止取不到数据,直接执行CONTINUE HANDLER,设置have = false
while have do
select orgId,orgName,parentOrgId;
-- insert IGNORE into org_info_0107 values(orgId,orgName,parentOrgId);-- 将提取数据插入临时表
fetch test0107 into orgId,orgName,parentOrgId; -- 从游标中取值
end while; -- 没有下一行(即到游标末尾),结束循环
close test0107; -- 关闭游标
end$$
delimiter ;
call test17();
select * from org_info_0107;
select count(1) from org_info_0107;
3.3、注意事项
在一些特殊情况下,有可能会读到空数据,或者sql语句就有错误,为了避免出现 对空数据的操作,需正确使用游标操作。如:
在打开游标后,应先手动 fetch 操作获取到一行数据,然后在通过循环,在循环里先做 处理内容,后进行 fetch操作。 这样如果在手动获取数据期间就没有获得到数据的话,就会执行 hava = false。