在最近的开发过程中,底层数据库的逻辑稍微有些复杂,在这个过程中涉及到了游标的使用,结合项目的逻辑我简单描述一下游标的使用,如果能对您有一点点的帮助,我将非常高兴,有不合理之处,欢迎大神随时指出。
首先,简述一下开发环境,我们的数据库是Oracle,IDE是PL/SQL Developer,游标是在存储过程中使用的。
我们总览一下代码:
create or replace procedure P_CRM_HGQD_MX(v_id varchar2,v_comp_code varchar2)
/*
v_id 供应商清单主表id 1111111111
v_comp_code 要进行统计的组织机构代码 21101
*/
as
CURSOR CUR_TABLE_LIST IS
SELECT id,corp_code,crm_minf_id FROM CRM_HGQD_MX WHERE main_id = v_id;
v_mxid varchar2(40);
v_corp_code varchar2(40);
-- v_yxq varchar2(1000);
v_syxmdm varchar2(2000);
v_syxmmc varchar2(2000);
v_zgyxq varchar2(2000);
v_zbjb varchar2(2000);
v_crm_minf_id varchar2(2000);
begin
--1如果存在主表对应的明细数据时,进行删除,程序界面应该进行提示用户
delete CRM_HGQD_MX WHERE main_id = v_id;
---2插入数据
insert into CRM_HGQD_MX (ID, MAIN_ID,corp_code,GYS_NAME,
gys_identity ,invoice_type ,tax_rate ,phone, server_area,
approve_time,describe,CRM_MINF_ID)
select v_id || rownum,v_id,a.corp_code,a.corp_name,
(case when a.taxpayeridentity='1' then '一般纳税人'
when a.taxpayeridentity='2' then '小规模纳税人'
else '' end ) as nsrsf,
(case when a.fplx ='1' then '增值税普通发票'
when a.fplx ='2' then '增值税专业发票'
when a.fplx ='3' then '通用发票'
else '' end ) as fplx,
(case when a.sl =1 then '2%'
when a.sl =2 then '3%'
when a.sl =3 then '5%'
when a.sl =4 then '6%'
when a.sl =5 then '11%'
when a.sl =6 then '13%'
when a.sl =7 then '17%'
else '' end ) as sl
,a.lxr||'/'||a.sj as lxfs,
a.business_scope,a.reg_date,a.remarks,b.id
from pub_cssc_inf a ,srm_crm_minf b where a.corp_type='供应商' and a.pub_cs_inf_id='GYS1_SCS'
and a.id = b.pub_cssc_inf_id;
--3循环
OPEN CUR_TABLE_LIST;
LOOP
--
FETCH CUR_TABLE_LIST INTO v_mxid,v_corp_code,v_crm_minf_id;
EXIT WHEN CUR_TABLE_LIST%NOTFOUND;
--4查询业务表相关数据。
---获取适用项目
select to_char(wm_concat(b.comp_code)),to_char(wm_concat(c.org_name))
into v_syxmdm,v_syxmmc
from srm_crm_minf b,auth_org_info c
where b.comp_code = c.org_code
and b.corp_code = v_corp_code;
--获取资格有效期
select wm_concat(to_char(b.yx_end_date,'yyyy-MM-dd')) into v_zgyxq from srm_crm_minf b
where b.corp_code = v_corp_code;
--获取质保级别
select to_char(wm_concat( (case when d.qa_class ='QA1' then '质保一级'
when d.qa_class ='QA2' then '质保二级'
when d.qa_class ='QA3' then '质保三级'
when d.qa_class ='QA4' then '质保四级'
else '' end ))) into v_zbjb from Srm_Review_Plan d
where d.corp_code = v_crm_minf_id;
--更新明细表相关字段
update CRM_HGQD_MX set fit_project = v_syxmmc,quality_level =v_zbjb,SYXMDM = v_syxmdm,validity_period = v_zgyxq
where id= v_mxid;
commit;
END LOOP;
end P_CRM_HGQD_MX;
我们可以看出来,这个存储过程的逻辑还是比较清楚的,只是在有些地方我们不是很熟悉,在写这个存储过程时,我自己也是这种感觉,有些细节的东西只有在自己写的过程中才能有一个自己的体会。看这个整体的代码,只要有一个整体上的认识就可以了,如整个存储过程是干什么的等,具体的内容,我下面还会说。
其实需求说简单点就是,我们需要从其他几张有数据的表中查出数据,更新到一张新的表。可是问题在哪呢?问题就在于整个新表中的字段,有些字段是可以从其他的表中查出开直接插入的,可是有些字段却不能字段却不能直接插入,需要逐条进行处理后再插入新表,这就用到了我们的游标,还有就是有些字段的一个位置,查出来可能会对应好几条数据,这时候我们就要用函数将一列中的几个值,放到一行中的一个位置。
具体是如何实现的呢?我们再来看一张图片
在这个存储过程中有两个参数;在创建游标处CUR_TABLE_LIST 是游标名,游标中保存的是id,corp_code,crm_minf_id,大家可以这样理解,我们把这三个字段找出来放到一张临时表中;接下来时begin,注意程序是从begin处开始资执行的;在2插入数据处insert---select这种写法是可以一次性插入查出的全部数据的,在查出的数据中还有一个转换,如果在旧表中查出的数据是3,则存入新表的数据是通用发票;打开游标开始循环,在创建游标时,可以这样理解我们把数据存入了一个有三个字段的临时表,现在我们要把这张临时表中的数据拿出来,利用循环一条条进行处理,我们把游标中的数据一条条赋值给变量,这样在第一次循环时,变量中就是游标中的第一天记录,第二次循环时,变量中就是游标中的第二条记录;下面是判断条件当游标中所有记录都经过遍历时退出循环;游标和循环结合在一起实现了逐条处理数据。最后不要忘记关闭游标。
其实这种方式(循环)是非常影响效率的,但是有时为了实现功能,这种做法于是必须的,只要我们能找到一个平衡点就可以了,不要一味的追求效率,但在任何情况下,都不能影响用户的使用。感谢您花费宝贵的时间来看我的博客。