> 数据库 > MySQL >

mysql 存储过程、游标及逐行处理的配合使用

1. 数据准备
 
+----+------+--------+
| id | name | price1 |
+----+------+--------+
|  1 | 大米 | 5      |
|  2 | 鸡蛋 | 4.5    |
|  3 | 苹果 | 6      |
|  4 | 面粉 | 4      |
|  5 | 小米 | 5.5    |
+----+------+--------+
 
2. 定义一个存储过程(供下一存储过程调用)
delimiter //
create procedure getPrice1(
    in id int,
    in addSelf boolean,
    out ototal decimal(6,2)
) comment '根据id及是否价格乘2来获取价格'
begin
    -- 声明临时变量price
    declare price decimal(6,2);
    -- 根据id查询price1保存到临时变量price 
    select price1 from aa01 where aa01.id = id into price;
    -- 判断是否需要乘2
    if addSelf then
        select price * 2 into price;
    end if;
    -- 最后将临时变量赋值给输出变量
    select price into ototal;
end //
delimiter ;
 
3. 存储过程、游标及逐行处理的配合使用
delimiter //
create procedure copyIdAndDoublePrice1()
comment '将原始表中id和price1*2结果赋值到表aa02中'
begin
-- 声明局部变量
declare done boolean default 0;
declare tempId int;
declare tempDoublePrice1 decimal(6,2);
-- 声明游标
declare idIndex cursor
for
select id from aa01;
-- 声明循环结束条件
declare continue handler for sqlstate '02000' set done = 1;
-- 创建aa02表用于保存结果集
create table if not exists aa02(
id int,
doublePrice1 decimal(6,2)
);
-- 打开游标
open idIndex;
-- 循环所有行
repeat
-- 获得当前循环的id
fetch idIndex into tempId;
-- 调用另一个存储过程获取结果
call getPrice1(tempId, 1, tempDoublePrice1);
-- 将结果插入aa02表
insert into aa02(id, doublePrice1) values (tempId, tempDoublePrice1);
-- 结束循环
until done end repeat;
-- 关闭游标
close idIndex;
end //
delimiter ;
 
4. 调用存储过程及查询表aa02结果
call copyIdAndDoublePrice1();
select * from aa02;
 
+----+--------------+
| id | doublePrice1 |
+----+--------------+
|  1 | 10           |
|  2 | 9            |
|  3 | 12           |
|  4 | 8            |
|  5 | 11           |
|  5 | 11           |
+----+--------------+
 
5. 注意事项
 
这条语句定义了一个CONTINUE HANDLER,它是在条件出现时被执行的代码。这里,它指出当SQLSTATE '02000'出现时,SET done=1。SQLSTATE'02000'是一个未找到条件,当REPEAT由于没有更多的行供循环而不能继续时,出现这个条件。
 
 
 
DECLARE语句的次序 DECLARE语句的发布存在特定的次序。用DECLARE语句定义的局部变量必须在定义任意游标或句柄之前定义,而句柄必须在游标之后定义。不遵守此顺序将产生错误消息。
 




(责任编辑:IT)