循环调用修正sic86

  

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;

  

原文地址:https://www.cnblogs.com/Sunnor/p/4652977.html