存储过程和游标

需求:还是上文的那个多线程的退单的需求,经过和领导的沟通,既然要是用中间表,那为什么不能使用存储过程job定时去处理呢,然后就开始想咋用存储处理这个问题。具体需求,报账过程中退单的单据,按照单位分类进行展示,从组织级别进行分类,不同单位不同单据类型一定时间之内的退单以及提单数量。
使用技术:存储过程,游标
实现效果:将我们从对应的表中获取的数据,将对应的数据处理完成之后,更新到中间表中。
中间表表结构:

create table CHARGEBACKQUERY
(
  id               VARCHAR2(50) not null primary key,
  adminfirstname   VARCHAR2(300),
  adminfirstpath   VARCHAR2(50),
  adminmindname    VARCHAR2(300),
  adminmindpath    VARCHAR2(50),
  adminlastname    VARCHAR2(300),
  adminlastpath    VARCHAR2(50),
  adminrealid      VARCHAR2(50),
  adminrealname    VARCHAR2(300),
  adminrealpath    VARCHAR2(50),
  adminreallayer   VARCHAR2(50),
  documenttype     VARCHAR2(50),
  documentid       VARCHAR2(50),
  rejectiontype    VARCHAR2(50),
  rejectedquantity INTEGER,
  submitnum        INTEGER,
  by1              VARCHAR2(50),
  by2              VARCHAR2(50),
  by3              VARCHAR2(50),
  by4              VARCHAR2(50),
  num1             INTEGER,
  num2             INTEGER,
  num3             INTEGER,
  num4             INTEGER,
  num5             INTEGER,
  rejectiontime    TIMESTAMP(6)
)

存储过程

--test20230301         
create or replace procedure Chargebackprocedure is
    cursor emp_cursor1 is
    SELECT ID,ADMINREALPATH,ADMINREALID,DOCUMENTID,REJECTIONTIME FROM ChargebackQuery;
    v_id ChargebackQuery.ID%TYPE;
    v_path ChargebackQuery.ADMINREALPATH%TYPE;
    v_dwnm ChargebackQuery.ADMINREALID%TYPE;
    v_djlx ChargebackQuery.DOCUMENTID%TYPE;
    v_sdrq ChargebackQuery.REJECTIONTIME%TYPE;
begin
  delete ChargebackQuery;
insert into ChargebackQuery (id,ADMINFIRSTNAME,ADMINFIRSTPATH,adminrealid,adminrealname,adminrealpath,adminrealLAYER,documenttype,documentid,REJECTIONTIME,rejectedquantity)
 SELECT sys_guid(),
        ADMINORGfather.NAME_CHS as fathername,
        ADMINORGfather.TREEINFO_PATH as fatherpath,
        ADMINORG.id,
        ADMINORG.NAME_CHS,
        ADMINORG.TREEINFO_PATH,
        ADMINORG.TREEINFO_LAYER,
        DJLX.NAME_CHS AS FORMTYPENAME,
        TURN.FORMTYPE AS FORMTYPEid,
        to_timestamp(to_char(TURN.RUTURNTIME, 'YYYY-MM-DD'), 'YYYY-MM-DD'),
        count(1)
   FROM PFRUTURNBILLACTION TURN
   LEFT JOIN BFADMINORGANIZATION ADMINORG
     ON TURN.COMPANYID = ADMINORG.ID
   LEFT JOIN PFGERETURNTYPEDEF TYPE
     ON TURN.TYPEID = TYPE.ID
   LEFT JOIN PFGEFORMTYPE DJLX
     ON TURN.FORMTYPE = DJLX.ID
   LEFT JOIN FSBZDJ FB
     ON TURN.BILLCODE = FB.FSBZDJ_DJBH
   LEFT JOIN PFRUPROCINSTBILL
     ON TURN.PROCINSTID = PFRUPROCINSTBILL.PROCINSTID
   LEFT JOIN PFGEFORMTYPE PFGEFORMTYPE
     ON TURN.FORMTYPE = PFGEFORMTYPE.CODE
   LEFT JOIN BFADMINORGANIZATION ADMINORGfather
     ON ADMINORGfather.TREEINFO_PATH = '11111'
  where 1 = 1
    and ADMINORG.CODE is not null
    and (ADMINORG.TREEINFO_PATH like '11111%')
    and (TURN.RUTURNTIME >
        to_timestamp('20221201', 'YYYYMMDD') and
        TURN.RUTURNTIME <
        to_timestamp('20230301', 'YYYYMMDD') )
  group by ADMINORGfather.NAME_CHS,
           ADMINORGfather.TREEINFO_PATH,
           ADMINORG.id,
           ADMINORG.NAME_CHS,
           ADMINORG.TREEINFO_PATH,
           ADMINORG.TREEINFO_LAYER,
           DJLX.NAME_CHS,
           TURN.FORMTYPE,
           to_timestamp(to_char(TURN.RUTURNTIME, 'YYYY-MM-DD'), 'YYYY-MM-DD');
           commit;
           open emp_cursor1;
        loop
            fetch emp_cursor1 into v_id,v_path,v_dwnm,v_djlx,v_sdrq;
            exit when emp_cursor1%NOTFOUND;
                begin
                UPDATE ChargebackQuery SET ADMINMINDPATH = substr(v_path,0,16) WHERE ID = v_id;
                UPDATE ChargebackQuery SET ADMINMINDNAME = (SELECT NAME_CHS FROM BFADMINORGANIZATION WHERE TREEINFO_PATH = substr(v_path,0,16)) 
                WHERE ADMINMINDPATH = substr(v_path,0,16);
                UPDATE ChargebackQuery SET ADMINLASTPATH = substr(v_path,0,20) WHERE ID = v_id;
                UPDATE ChargebackQuery SET ADMINLASTNAME = (SELECT NAME_CHS FROM BFADMINORGANIZATION WHERE TREEINFO_PATH = substr(v_path,0,20))
                WHERE ADMINLASTPATH = substr(v_path,0,20);  
                UPDATE ChargebackQuery SET SUBMITNUM = 
                (SELECT COUNT(1) FROM FSBZDJ WHERE FSBZDJ_DWNM = v_dwnm AND FSBZDJ_DJLX = v_djlx and TO_CHAR(CREATEDDATE, 'YYYY-MM-DD') = TO_CHAR(v_sdrq,'YYYY-MM-DD')) 
                WHERE ADMINREALID = v_dwnm AND DOCUMENTID = v_djlx AND REJECTIONTIME = v_sdrq;
                end;
        end loop;
        close emp_cursor1;
        commit;
end;


begin
  Chargebackprocedure;
end;   

存储过程,基本样式

create or replace procedure Chargebackprocedure is
--游标声明
begin
--逻辑开始  
end;

--无参游标的调用
begin
  Chargebackprocedure;
end; 

游标,基本样式

declare
    cursor emp_cursor1 is
    SELECT ID,ADMINREALPATH,ADMINREALID,DOCUMENTID,REJECTIONTIME FROM TEST20230220;
    v_id TEST20230220.ID%TYPE;
    v_path TEST20230220.ADMINREALPATH%TYPE;
    v_dwnm TEST20230220.ADMINREALID%TYPE;
    v_djlx TEST20230220.DOCUMENTID%TYPE;
    v_sdrq TEST20230220.REJECTIONTIME%TYPE;
    --游标名称以及游标各个参数
    begin
        open emp_cursor1;
        --打开游标
        loop
        --开始循环
            fetch emp_cursor1 into v_id,v_path,v_dwnm,v_djlx,v_sdrq;
            --游标取数
            exit when emp_cursor1%NOTFOUND;
                begin
                --开始基本的逻辑
                UPDATE TEST20230220 SET ADMINMINDPATH = substr(v_path,0,16) WHERE ID = v_id;
                UPDATE TEST20230220 SET ADMINMINDNAME = (SELECT NAME_CHS FROM BFADMINORGANIZATION WHERE TREEINFO_PATH = substr(v_path,0,16)) 
                WHERE ADMINMINDPATH = substr(v_path,0,16);
                UPDATE TEST20230220 SET ADMINLASTPATH = substr(v_path,0,20) WHERE ID = v_id;
                UPDATE TEST20230220 SET ADMINLASTNAME = (SELECT NAME_CHS FROM BFADMINORGANIZATION WHERE TREEINFO_PATH = substr(v_path,0,20))
                WHERE ADMINLASTPATH = substr(v_path,0,20);  
                UPDATE TEST20230220 SET SUBMITNUM = 
                (SELECT COUNT(1) FROM FSBZDJ WHERE FSBZDJ_DWNM = v_dwnm AND FSBZDJ_DJLX = v_djlx and TO_CHAR(CREATEDDATE, 'YYYY-MM-DD') = TO_CHAR(v_sdrq,'YYYY-MM-DD')) 
                WHERE ADMINREALID = v_dwnm AND DOCUMENTID = v_djlx AND REJECTIONTIME = v_sdrq;
                end;
        end loop;
        close emp_cursor1;
        --一定要注意关闭游标
end;

主要是为了巩固存储过程以及游标的完成,之前学习过但是太久太久没有在温习过了。

总结:其实我整体只完成了大部分的构思,我最开始做的时候其实还是没有当成一个sql去处理的,我还是在想需要几个loop来完成,但是其实只是需要一个loop就可以完成了,后来其实反应过来了,真的需要游标嘛,直接全部删除了,然后全部插入,一点一点update就可以了,应该是不需要游标来完成,就当是熟悉一下游标吧。

你可能感兴趣的:(sql,数据库,oracle)