mysql游标动态传参实现(动态游标)
1.问题
众所周知,mysql存储过程功能是没有oracle的包功能强大的,但是在去O的趋势下,mysql存储过程的编写还是要掌握的。今天在编写mysql存储过程的时候,就遇到一个问题,可能是先入为主的思想,同事之前说过:mysql的存储过程很难用,游标都不能使用oracle那种动态传参实现动态遍历结果集内容。我也就一直以为mysql的邮编只能在begin的DECLARE最后的部分进行一次确切的sql声明,但是很多时候我并不能事先确定每一个字段的范围,这样游标就很鸡肋了。搜了许久没有找到相关博库,难道是我搜索方式不对?那我就来水一篇博客了~
2.需求描述
现在想要在存储过程中间遍历某个游标,这个游标实际是查一个表ib_tbs_prepareduty
,这个表有一个ftaskid
字段,这个字段的值我不能在声明游标的时候确定,我可能在存储过程中间某一部分处理后才能得到,这个时候我们该怎么declare
游标,又怎么让游标准确拿到这部分我想要的记录呢?
如果是oracle就好了,我可以像函数一样定义游标,然后open
游标,接着遍历就可以了。
DECLARE
r_emp emp%ROWTYPE; --该类型为emp表中一行的类型
cursor c_emp(v_no number) is SELECT * FROM emp where deptno = v_no;
BEGIN
OPEN c_emp(20); --给v_no传参20
LOOP
FETCH c_emp into r_emp ; --游标中查询出来的一行into进定义的变量r_emp中
EXIT WHEN c_emp%NOTFOUND;
dbms_output.put_line('员工姓名:' || r_emp.ename );
END LOOP;
CLOSE c_emp;
END;
3.实现
3.1.使用
其实,mysql的游标也是可以传参数的,只不过定义和传参的时候和oracle的带参数的游标有一点不同,但是使用的时候就和普通的静态游标一模一样了。
首先是定义:
接着是或者@parameter
并赋值,然后游标在open
的时候就会执行具体的sql,拿到我们要的结果集,最后使用循环进行遍历就可以了。
起始就是比静态游标的时候多一个传参,比如倒数第二个游标cur_bq
就是静态游标:
废话不多说,直接上代码:
3.2.代码(直接看这都可以)
CREATE DEFINER=`root`@`%` PROCEDURE `p_prepareduty`({你的入参和出参数})
BEGIN
#下面定义一些变量用来存你要从游标中取出的字段内容
DECLARE for_i int DEFAULT 0;
DECLARE cur_fid VARCHAR(50);
DECLARE cur_fdate date;
DECLARE cur_fcityno VARCHAR(20);
DECLARE cur_foverseas VARCHAR(200);
DECLARE cur_freason VARCHAR(50);
DECLARE cur_fspecial text;
DECLARE var_ftaskid VARCHAR(50);#你的其他变量
DECLARE done INT DEFAULT 0;#用于退出LOOP循环
#DECLARE最后部分是定义你的游标,可以定义静态和动态游标
declare cur_bq cursor for
select fid,fdate,fcityno,foverseas,freason,fspecial from ib_tbs_prepareduty
where ftaskid = ls_ftaskid and fempid = ls_fempid and fifvalid = '1';#静态
declare cur_lastbq cursor for
select fcityno,foverseas,freason,fspecial from ib_tbs_prepareduty
where fempid = ls_fempid and fifvalid = '1' and ftaskid = @parameter;#动态
#@parameter是域变量,也就是游标的参数
declare continue handler for not found set done = 1;
{这里处理你的业务,并且获得你需要的@parameter的值}
#下面演示动态游标使用
SET @parameter= var_ftaskid;#给动态游标传参
open cur_lastbq;#打开游标
read_loop:LOOP#循环遍历
fetch cur_lastbq into cur_fcityno,cur_foverseas,cur_freason,cur_fspecial;#取出你要的字段
IF done = 1 THEN LEAVE read_loop;
END IF;#游标遍历完后退出循环
{你的其他操作}
END LOOP read_loop;
close cur_lastbq;#关闭游标
#下面演示静态游标使用
open cur_bq;
lable1:loop
fetch cur_bq into cur_fid,cur_fdate,cur_fcityno,cur_foverseas,cur_freason,cur_fspecial;
IF done = 1 THEN LEAVE lable1;
END IF;
{你的其他操作}
end loop lable1;
close cur_bq;
END