《mysql存储过程编程》之游标

1、什么是游标?

 

游标就类似于迭代器或者指针之类的东西,它指向第一条数据库中的记录,每取一次记录则游标向后移动一位

 

 

2、游标的4个部分
1、declare 申明  -- declare 游标名 cursor for select statement
2、open 打开     --open 游标名
3、fetch 取值    --fetch 游标名 into var1,var2,[...]
4、close 关闭 --close 游标名

3、游标要和select语句配合使用
declare c cursor for select * from user 
这句话就表示游标c指向select * from user查询结果集的第一条记录(该记录还未从数据库中取出,这儿可以写逻辑决定要不要返回该记录给调用程序,每取一次,游标就向后移动一位)

4、定义游标并循环游标(推荐使用repeat循环)

 

 XML Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

 

create procedure use_cursor()
begin
    declare row_id int default 0;
    declare row_name varchar(20) default '';
    declare flag int default 0;
    
    declare c cursor for select id,name from t1;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET FLAG=1;
    open c;
    repeat
            fetch c into row_id,row_name;
            select concat('id=',row_id,' name=',row_name);
        until flag
    end repeat;
    close c;
end$$

 

 

 

5、发现最后一条记录打印了两次???这是为什么?
 这是因为当游标指向最后一条记录时,把row_id,row_name赋值为10,name-10,当下一次执行时发现没有数据可取,
 所以就出发了前面定义的handler使flag=1,但是这是一个continue类型handler即当触发该handler后程序依然继续往下
 执行,由于本次没有数据可取,故没有给row_id和row_name赋值,就接着把上一次row_id和row_name打印了出来
 这是为什么会出现两次的原因

6、解决这个问题有两种办法

   6.1 最简单的办法是使用exit类型的handler即当触发该类型的handler时程序不在往下执行也就是说直接跳出了循环(存储过程)
    个人不推荐这种做法,如果后面还有代码要执行则通过这种方式就不能实现

 

 XML Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

 

        create procedure use_e_handler()
        begin
            declare row_id int default 0;
            declare row_name varchar(20) default '';
            declare flag int default 0;
            
            declare c cursor for select id,name from t1;
            DECLARE exit HANDLER FOR NOT FOUND SET FLAG=1;
            open c;
            repeat
                fetch c into row_id,row_name;
                until flag
            end repeat;
            close c;
            select 'continue over...';
        end$$

 

 

   6.2手动检测flag标志的值,如果发现触发了handler就手动离开循环

 

 XML Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

 

    create procedure use_cursor_e()
    begin
        declare row_id int default 0;
        declare row_name varchar(20) default '';
        declare flag int default 0;
        declare c cursor for select id,name from t1;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET FLAG=1;
        open c;
        r:repeat
                fetch c into row_id,row_name;
                if flag  then 
                    leave r;
                end if;
                select concat('id=',row_id,' name=',row_name);
            until flag
        end repeat r;
        close c;
    end$$

 

 

 

7,存储过程之间的通信(唯一的方法是创建临时表)

--创建一个创建临时表的存储过程

 

 XML Code 

1
2
3
4

 

create procedure p_producer()
begin
    create temporary table t2 as select * from t1;
end$$

--创建一个用于消费前一个存储过程创建的表的存储过程

 

 

 XML Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

 

create procedure p_consumer()
begin
    declare flag int default 0;
    declare row_id int default 0;
    declare row_name varchar(10) default '';
    declare c cursor for select id,name from t2;
    declare continue handler for not found set flag=1;
    open c;
    r:repeat 
        fetch c into row_id,row_name;
        if flag then 
            leave r;
        end if;
        select row_id,row_name;
        until flag
    end repeat r;
end$$

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值