在实际应用场景中,需要通过存储过程解决批量录入,数据处理,批量返回的操作,且业务是实时的,即一次批量数据是一次性的。
针对这个场景,考虑过以下方法:使用临时缓存表,将数据处理后存入,需要使用时读取并删除;从其他业务上环节批量录入或批量返回的压力
而后确定批量一次数据量在200条内,此存储的调用比较频繁,存在被多处调用的情况。
考虑实际,如果使用临时表频繁读写删数据,可能会出现锁数据的情况;在业务上通过其他环节来找补也是下策。
最后确定了使用自定义数据类型和类型集合缓存处理好的数据,整体方案:将录入的格式约定成字符串,数据处理后缓存在集合,最后游标遍历集合返回数据。
自定义数据格式类型
-- 定义需要的数据类型,类似编程中的类
create or replace Type Check_Record
Is Object(P_Id NUMBER,V_Code Varchar2(2),V_Message NVARCHAR2(50))
-- 定义类型的集合,类似编程中的列表
create or replace Type PrescriptionCheck_Table
Is Table Of PrescriptionCheck_Record
使用自定义类型,并通过游标返回类型列表信息
create or replace PROCEDURE p_check_refund_state (
in_str VARCHAR2, --输入字符串,格式:类型,ID;类型,ID...
scur OUT SYS_REFCURSOR -- 返回值
) IS
--临时变量
v_tempStr VARCHAR(1000); -- 缓存解析字符串
v_temp_in_str VARCHAR(1000); -- 缓存输入字符串
v_count_begin int; -- 临时计数
v_count_end int; -- 临时计数
v_type NUMBER; --类型 检查申请 = 5,病理申请 = 6, 治疗申请 =7, 检验申请 = 8,手术申请 =9,用血申请 = 10,其他 = 99
v_id NUMBER; --ID
v_code VARCHAR(2); -- 返回值临时缓存
v_message VARCHAR(255); -- 返回信息临时缓存
datatab Check_Table := Check_Table(); -- 自定义类型的返回集合
BEGIN
IF(in_str IS NOT NULL AND LENGTH(in_str) > 0) THEN
v_temp_in_str := in_str;
LOOP --循环解析字符串
datatab.extend;-- 扩充一条
datatab(datatab.count) := Check_Record(-1,0,'传入第' || datatab.count || '条数据有误!');
--判断‘;’有无,若无取全部字符串,反之前取到第一个分号前位置。
IF(INSTR(v_temp_in_str,';',1,1) != 0) THEN
v_tempStr := SUBSTR(v_temp_in_str,0,INSTR(v_temp_in_str,';',1,1));
ELSE
v_tempStr := v_temp_in_str;
END IF;
v_count_end := LENGTH(v_tempStr);
--解析目标字符串
--判断','进行类型与id的分取,
IF(INSTR(v_tempStr,',',1,1) != 0) THEN
v_count_begin := INSTR(v_tempStr,',',1,1);
v_type := TO_NUMBER(SUBSTR(v_tempStr,0,v_count_begin-1));
IF(INSTR(v_tempStr,';',1,1) != 0) THEN
v_id := TO_NUMBER(SUBSTR(v_tempStr,v_count_begin+1,v_count_end-v_count_begin-1));
ELSE
v_id := TO_NUMBER(SUBSTR(v_tempStr,v_count_begin+1,v_count_end));
END IF;
-- 单条业务数据处理
p_check_One_state(v_type,v_id,v_code,v_message);
-- 将处理后数据放入自定义集合
datatab(datatab.count) := Check_Record(v_id,v_code,v_message);
END IF;
v_count_begin := LENGTH(v_temp_in_str);
--丢弃解析过的字符串
IF(v_count_begin != v_count_end) THEN
v_temp_in_str := SUBSTR(v_temp_in_str,v_count_end+1,v_count_begin);
ELSE
v_temp_in_str := '';
END IF;
EXIT WHEN v_temp_in_str IS NULL OR LENGTH(v_temp_in_str) = 0;
END LOOP;
END IF;
-- 遍历集合,数据返回
OPEN scur FOR SELECT * FROM table(datatab);
-- 异常处理
EXCEPTION
WHEN OTHERS THEN
OPEN scur FOR SELECT * FROM table(datatab);
END;
过程中参考文章:
信息加载中,请等待
微信客服(速回)
微信客服(慢回)