create or replace procedure rebuild_sic86_wyl(pi_aac001 in number, po_fhz out varchar2, po_msg out varchar2) is --1.根据账户类型来判断是本地的还是转入的, --2.如果是本地的, -- 写一个游标存放sic86.截止上年末缴费月数jzsnm,本年度缴费月数bn,本年累计缴费月数bnnj, -- 从最小的年份开始,清空最小年费的下一年jzsnm,bnlj -- update sic86 set jzsnm = null ,bnlj = null where aae001 >min(aae001) -- update 最小年费下一年的 jzsnm = 最小年份bn+bnlj v_count number(4); v_zhlx sic86.zhlx%type; v_aae001_min sic86.aae001%type; v_aae001_max sic86.aae001%type; v_nf sic86.aae001%type; v_bn sic86.bn%type; v_bnlj sic86.bnlj%type; v_jzsnm sic86.jzsnm%type; cursor c_zhlx_list is select zhlx from sic86 where aac001 = pi_aac001; begin po_fhz := '1'; po_msg := '修正成功'; for rec_zhlx in c_zhlx_list loop --选取最小年份和最小年份 select min(aae001) into v_aae001_min from sic86 where aac001 = pi_aac001; select min(aae001) into v_aae001_max from sic86 where aac001 = pi_aac001; if rec_zhlx.zhlx = '0' then for nf in v_aae001_min .. v_aae001_max loop --去最小年份的本年缴费月数 select bn into v_bn from sic86 where aac001 = pi_aac001 and aae001 = nf; --取最小年份的本年累计月数 select bnlj into v_bnlj from sic86 where aac001 = pi_aac001 and aae001 = nf; --最小年份下一年 v_nf v_nf := nf + 1; -- 修正1 最小年份下一年的的 jzsnm = 最小年度bn+最小年度bnlj update sic86 set jzsnm = (v_bn + v_bnlj) where aac001 = pi_aac001 and aae001 = v_nf; --取最小年份下一年的的截至上年末月数 select jzsnm into v_jzsnm from sic86 where aac001 = pi_aac001 and aae001 = v_nf; -- po_msg :=v_nf||'年份的jzsnm='||v_jzsnm; --return; --调试用,正式用的时候注释掉 --去最小年份下一年的本年缴费月数 select bn into v_bn from sic86 where aac001 = pi_aac001 and aae001 = v_nf; --清空最小年份下一年的 截至上年末月数 和 本年累计(其实清空不情况无所谓,不影响) /* update sic86 set jzsnm = null, bnlj = null where aac001 = pi_aac001 and aae001 = v_nf; */ -- 修正2 最小年份下一年的 本年累计月数 bnlj = 本年的jzsnm+本年的bn update sic86 set bnlj = (v_jzsnm + v_bn) where aac001 = pi_aac001 and aae001 = v_nf; end loop; po_fhz := '1'; po_msg := '循环修正成功'; elsif rec_zhlx.zhlx = '1' then po_fhz := '-1'; po_msg := '转入的暂不处理'; return; end if; end loop; end;
以上只能修正最小年度的下一年。
以下是建表语句:
-- Create table create table SIC86 ( jzsnm NUMBER(4), bn NUMBER(4), bnlj NUMBER(4), zhlx VARCHAR2(2), aac001 NUMBER(10), aae001 NUMBER(4) ) tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage ( initial 64K next 1M minextents 1 maxextents unlimited ); -- Add comments to the table comment on table SIC86 is '模拟养老年度账户'; -- Add comments to the columns comment on column SIC86.jzsnm is '截至上年末缴费月数'; comment on column SIC86.bn is '本年缴费月数'; comment on column SIC86.bnlj is '截止本年累计月数'; comment on column SIC86.zhlx is '账户类型,0:本地; 1:转入生成'; comment on column SIC86.aac001 is '个人编号';
最终的修正程序:
可以正常使用,要分两段,第一:最小年份的要单独更新 本年累计bnlj = 截至上年末 jzsnm+本年bn ;
第二:最大年份的时候同上。
CREATE OR REPLACE PROCEDURE REBUILD_SIC86_WYL(PI_AAC001 IN NUMBER, PO_FHZ OUT VARCHAR2, PO_MSG OUT VARCHAR2) IS --1.根据账户类型来判断是本地的还是转入的, --2.如果是本地的, -- 写一个游标存放sic86.截止上年末缴费月数jzsnm,本年度缴费月数bn,本年累计缴费月数bnnj, -- 从最小的年份开始,清空最小年费的下一年jzsnm,bnlj -- update sic86 set jzsnm = null ,bnlj = null where aae001 >min(aae001) -- update 最小年费下一年的 jzsnm = 最小年份bn+bnlj V_ZHLX SIC86.ZHLX%TYPE; V_AAE001_MIN SIC86.AAE001%TYPE; V_AAE001_MAX SIC86.AAE001%TYPE; V_NF SIC86.AAE001%TYPE; V_BN SIC86.BN%TYPE; V_BNLJ SIC86.BNLJ%TYPE; V_JZSNM SIC86.JZSNM%TYPE; CURSOR C_ZHLX_LIST IS SELECT ZHLX FROM SIC86 WHERE AAC001 = PI_AAC001; BEGIN PO_FHZ := '1'; PO_MSG := '修正成功'; FOR REC_ZHLX IN C_ZHLX_LIST LOOP --选取最小年份和最小年份 SELECT MIN(AAE001) INTO V_AAE001_MIN FROM SIC86 WHERE AAC001 = PI_AAC001; SELECT MAX(AAE001) INTO V_AAE001_MAX FROM SIC86 WHERE AAC001 = PI_AAC001; FOR NF IN V_AAE001_MIN .. V_AAE001_MAX LOOP --修正01 最小年份的本年累计,只修正最小年份,只修正一次 IF (NF = V_AAE001_MIN) THEN --取最小年份的截止上年末月数,这个只用一次 UPDATE SIC86 SET BNLJ = (NVL(JZSNM, 0) + NVL(BN, 0)) WHERE AAC001 = PI_AAC001 AND AAE001 = NF; ELSE NULL; END IF; --去最小年份的本年缴费月数 SELECT BN INTO V_BN FROM SIC86 WHERE AAC001 = PI_AAC001 AND AAE001 = NF; --取最小年份的本年累计月数 SELECT BNLJ INTO V_BNLJ FROM SIC86 WHERE AAC001 = PI_AAC001 AND AAE001 = NF; --最小年份下一年 v_nf V_NF := NF + 1; -- 修正1 最小年份下一年的的 jzsnm = 最小年度bnlj UPDATE SIC86 SET JZSNM = V_BNLJ WHERE AAC001 = PI_AAC001 AND AAE001 = V_NF; --加入判断截至上年末下一年v_nf是否为最后一年,如果直接退出 IF V_NF = V_AAE001_MAX THEN --取最小年份的截止上年末月数,这个只用一次 UPDATE SIC86 SET BNLJ = (NVL(JZSNM, 0) + NVL(BN, 0)) WHERE AAC001 = PI_AAC001 AND AAE001 = V_NF; PO_FHZ := '1'; PO_MSG := '修复成功'; RETURN; END IF; --取最小年份下一年的的截至上年末月数 SELECT JZSNM INTO V_JZSNM FROM SIC86 WHERE AAC001 = PI_AAC001 AND AAE001 = V_NF; -- po_msg :=v_nf||'年份的jzsnm='||v_jzsnm; --return; --调试用,正式用的时候注释掉 --去最小年份下一年的本年缴费月数 SELECT BN INTO V_BN FROM SIC86 WHERE AAC001 = PI_AAC001 AND AAE001 = V_NF; -- 修正2 最小年份下一年的 本年累计月数 bnlj = 本年的jzsnm+本年的bn UPDATE SIC86 SET BNLJ = (V_JZSNM + V_BN) WHERE AAC001 = PI_AAC001 AND AAE001 = V_NF; END LOOP; PO_FHZ := '1'; PO_MSG := '循环修正成功'; END LOOP; END;