需求:还是上文的那个多线程的退单的需求,经过和领导的沟通,既然要是用中间表,那为什么不能使用存储过程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就可以了,应该是不需要游标来完成,就当是熟悉一下游标吧。