oracle使用存储过程返回游标实现报表查询
最近在oracle中通过存储过程实现一个报表查询,查询涉及到数据计算这里使用了临时表和存储过程实现输出查询,java接受游标变量返回结果集
第一步、创建统计使用的临时表
CREATE GLOBAL TEMPORARY TABLE T_TMP_REPORT_YFCHSLZZ(
DRUG_ID NUMBER(22) not null, --药品id
MAX_UNIT_ID NUMBER(22) not null, --最大包装id
DRUG_UNIT_ID NUMBER(22), --药房包装单位id
RECORD_FLAG NUMBER(4) not null, --记录类型0药品记录,1期初,2入库,3盘点盈亏,4出库,5报损
PRE_QUANTITY NUMBER(18,4) default 0 not null, --期初发生数量
QUANTITY NUMBER(18,4) default 0 not null, --发生数量
RELATION NUMBER(12) --业务单据包装单位换算比
) ON COMMIT PRESERVE ROWS
/
create index IDX_TMP_REPORT_YFCHSLZZ_DF
on T_TMP_REPORT_YFCHSLZZ (DRUG_ID,RECORD_FLAG);
/
第二步、创建存储过程,过程代码省略部分统计语句
create or replace PROCEDURE P_RPT_YFCHSLZZ (
--药房统计存货数量总账用过程 liuyc 20230317
v_typeIds IN VARCHAR2, --药品类别id逗号隔开字符串
v_drugId IN VARCHAR2, --药品id
v_deptId IN INT, --药房id
v_hosId IN INT, --医院id
v_includeDisable IN INT, --是否包含停用药品0否1是
v_beginDate IN DATE, --统计起日期
v_endDate IN DATE, --统计止日期
v_result out SYS_REFCURSOR --返回结果列表
)
IS
v_sql varchar2(2000); --动态执行的语句
v_expType varchar2(500); --药品类别查询条件
v_expDrug varchar2(100); --药品id查询条件
v_expDis varchar2(100); --药品停用查询条件
v_firstDay DATE; --统计期间月份的第一天
BEGIN
--取得要统计的药品记录
delete from T_TMP_REPORT_YFCHSLZZ;
--构建查询药品的条件
v_expType:='';
if length(nvl(v_typeIds,''))>0 then
v_expType:=' and a.DRUG_TYPE_ID in ('||v_typeIds||')';
end if;
v_expDrug:='';
if length(nvl(v_drugId,''))>0 then
v_expDrug:=' and a.ID='||v_drugId;
end if;
v_expDis:=' a.STATUS=''1''';
if v_includeDisable=1 then
v_expDis:=' 1=1';
end if;
v_sql:='insert into T_TMP_REPORT_YFCHSLZZ(DRUG_ID,MAX_UNIT_ID,DRUG_UNIT_ID,RECORD_FLAG)
select a.ID,min(b.ID) MAX_UNIT_ID,nvl(min(c.PACKAGE_UNIT_ID),min(b.ID)) DRUG_UNIT_ID,0 RECORD_FLAG
from T_PHARMACY_DRUG a
inner join T_PHARMACY_DRUG_PACKAGE b on b.DRUG_ID=a.ID and b.IS_MAX_PACKAGE_UNIT=''1'' and b.STATUS=''1''
left join T_PHARMACY_DRUGSTORE_PACKAGE c on c.DRUG_ID=a.ID and c.DEPT_ID='||v_deptId||' and c.STATUS=''1''
where '||v_expDis||v_expType||v_expDrug||' and a.HOSPITAL_ID='||v_hosId||' GROUP BY a.ID order by a.ID';
execute immediate v_sql;
--更新药房包装单位换算比
merge into T_TMP_REPORT_YFCHSLZZ a
using T_PHARMACY_DRUG_PACKAGE b on (a.DRUG_UNIT_ID=b.ID)
when matched then update set a.RELATION=b.RELATION
where a.RECORD_FLAG=0;
--添加期初数据,药房定时盘点库存数量是药房包装单位的数量,非基本单位数量
select trunc(v_beginDate,'MM') into v_firstDay from dual;
insert into T_TMP_REPORT_YFCHSLZZ(DRUG_ID,MAX_UNIT_ID,RECORD_FLAG,PRE_QUANTITY,DRUG_UNIT_ID)
select t1.DRUG_ID,0,1,t1.STOCK_COUNT,t1.MAX_PACKAGE_UNIT_ID
from T_DRUGSTORE_INVENTORY_VOUCHER t
join T_DRUGSTORE_INVENTORY_DETAIL t1 on t1.VOUCHER_ID = t.ID and t1.STOCK_COUNT!=0
join T_TMP_REPORT_YFCHSLZZ c on t1.DRUG_ID=c.DRUG_ID and c.RECORD_FLAG=0
where t.INVENTORY_METHOD_ID = '-99999' and t.IS_TALLY = '1'
and t.TALLY_DATE between v_firstDay-1 and v_firstDay+1
and t.INVENTORY_DEPT_ID = v_deptId and t.hospital_id = v_hosId;
commit;
--统计药库入库药房数据
insert into T_TMP_REPORT_YFCHSLZZ(DRUG_ID,MAX_UNIT_ID,RECORD_FLAG,PRE_QUANTITY,QUANTITY,DRUG_UNIT_ID)
select t1.DRUG_ID,0,2,
SUM(case when t.APPROVAL_DATE<v_beginDate then t1.PURCHASE_QUANTITY else 0 end) PRE_QUANTITY,
SUM(case when t.APPROVAL_DATE<v_beginDate then 0 else t1.PURCHASE_QUANTITY end) QUANTITY,t1.MAX_PACKAGE_UNIT_ID
from T_PHARMACY_OUT_BACK_VOUCHER t
join T_PHARMACY_OUT_BACK_DETAIL t1 on t1.VOUCHER_ID = t.ID
join T_TMP_REPORT_YFCHSLZZ c on t1.DRUG_ID=c.DRUG_ID and c.RECORD_FLAG=0
where t.IS_APPROVAL='1' and t.IS_TALLY = '1' and t.TYPE in (1, 2)
and t.APPROVAL_DATE between v_firstDay and v_endDate+0.99999
and t.UNIT_ID = v_deptId and t.hospital_id = v_hosId
group by t1.DRUG_ID,t1.MAX_PACKAGE_UNIT_ID;
commit;
--统计药房移库调拨数据
insert into T_TMP_REPORT_YFCHSLZZ(DRUG_ID,MAX_UNIT_ID,RECORD_FLAG,PRE_QUANTITY,QUANTITY,DRUG_UNIT_ID)
with ect_trans_bill as (
select t1.DRUG_ID,decode(t.TO_DEPT_ID,v_deptId,2,4) RECORD_FLAG,
SUM(case when t.TALLY_DATE<v_beginDate then t1.QUANTITY else 0 end) PRE_QUANTITY,
SUM(case when t.TALLY_DATE<v_beginDate then 0 else t1.QUANTITY end) QUANTITY,t1.PACKAGE_UNIT
from T_DRUGSTORE_TRANSFER t
join T_DRUGSTORE_TRANSFER_DETAIL t1 on t1.RECORD_ID = t.ID
join T_TMP_REPORT_YFCHSLZZ c on t1.DRUG_ID=c.DRUG_ID and c.RECORD_FLAG=0
where t.TALLY_STATUS = '1' and t.TO_DEPT_ID!=t.FROM_DEPT_ID and (t.TO_DEPT_ID=v_deptId or t.FROM_DEPT_ID=v_deptId)
and t.TALLY_DATE between v_firstDay and v_endDate+0.99999
and t.hospital_id = v_hosId
group by t1.DRUG_ID,t1.PACKAGE_UNIT,decode(t.TO_DEPT_ID,v_deptId,2,4)
)
select a.DRUG_ID,0,a.RECORD_FLAG,a.PRE_QUANTITY,a.QUANTITY,
(select ID from T_PHARMACY_DRUG_PACKAGE where PACKAGE_UNIT=a.PACKAGE_UNIT and STATUS='1' and DRUG_ID=a.DRUG_ID and ROWNUM=1)
from ect_trans_bill a;
commit;
--统计药房盘点盈亏数据
insert into T_TMP_REPORT_YFCHSLZZ(DRUG_ID,MAX_UNIT_ID,RECORD_FLAG,PRE_QUANTITY,QUANTITY,DRUG_UNIT_ID)
select t1.DRUG_ID,0,3,
SUM(case when t.TALLY_DATE<v_beginDate then t1.PROFIT_COUNT else 0 end) PRE_QUANTITY,
SUM(case when t.TALLY_DATE<v_beginDate then 0 else t1.PROFIT_COUNT end) QUANTITY,t1.MAX_PACKAGE_UNIT_ID
from T_DRUGSTORE_INVENTORY_VOUCHER t
join T_DRUGSTORE_INVENTORY_DETAIL t1 on t1.VOUCHER_ID = t.ID
join T_TMP_REPORT_YFCHSLZZ c on t1.DRUG_ID=c.DRUG_ID and c.RECORD_FLAG=0
where t.IS_TALLY = '1' and t.INVENTORY_METHOD_ID != '-99999'
and t.TALLY_DATE between v_firstDay and v_endDate+0.99999
and t.INVENTORY_DEPT_ID = v_deptId and t.hospital_id = v_hosId
group by t1.DRUG_ID,t1.MAX_PACKAGE_UNIT_ID;
commit;
--统计药房发药数据(门诊发药)
insert into T_TMP_REPORT_YFCHSLZZ(DRUG_ID,MAX_UNIT_ID,RECORD_FLAG,PRE_QUANTITY,QUANTITY,DRUG_UNIT_ID)
select t1.DOCTOR_ORDER_ID,0,4,
-SUM(case when t.CREATE_DATE<v_beginDate then t1.SEND_COUNT else 0 end) PRE_QUANTITY,
SUM(case when t.CREATE_DATE<v_beginDate then 0 else t1.SEND_COUNT end) QUANTITY,e.DRUG_UNIT_ID
from T_DRUGSTORE_DRUG_SEND t
join T_DRUGSTORE_DRUG_SEND_DETAIL t1 on t1.SEND_ID = t.ID
join T_TMP_REPORT_YFCHSLZZ c on t1.DOCTOR_ORDER_ID=c.DRUG_ID and c.RECORD_FLAG=0
join T_OPD_DOCTOR_ORDER_WRITE e on t1.OPDER_WRITE_ID=e.ID and e.HOSPITAL_ID=t.HOSPITAL_ID
where t.CREATE_DATE between v_firstDay and v_endDate+0.99999
and t.DEPT_ID = v_deptId and t.hospital_id = v_hosId
group by t1.DOCTOR_ORDER_ID,e.DRUG_UNIT_ID;
commit;
--统计药房发药数据(门诊退药)此处省略...
--统计药房发药数据(住院发药)此处省略...
--统计药房发药数据(住院退药)此处省略...
--统计报损信息
insert into T_TMP_REPORT_YFCHSLZZ(DRUG_ID,MAX_UNIT_ID,RECORD_FLAG,PRE_QUANTITY,QUANTITY,DRUG_UNIT_ID)
select t1.DRUG_ID,0,5,
-SUM(case when t.tally_date<v_beginDate then t1.QUANTITY else 0 end) PRE_QUANTITY,
SUM(case when t.tally_date<v_beginDate then 0 else t1.QUANTITY end) QUANTITY,t1.MAX_PACKAGE_UNIT_ID
from t_drugstore_loss t
join t_drugstore_loss_detail t1 on t1.voucher_id = t.ID
join T_TMP_REPORT_YFCHSLZZ c on t1.DRUG_ID=c.DRUG_ID and c.RECORD_FLAG=0
where t.CREATE_DATE between v_firstDay and v_endDate+0.99999
and t.UNIT_ID = v_deptId and t.hospital_id = v_hosId
group by t1.DRUG_ID,t1.MAX_PACKAGE_UNIT_ID;
--更新数量为基本单位数量
merge into T_TMP_REPORT_YFCHSLZZ a
using T_PHARMACY_DRUG_PACKAGE b on (a.DRUG_UNIT_ID=b.ID and a.RECORD_FLAG>0)
when matched then update set a.RELATION=b.RELATION,a.PRE_QUANTITY=a.PRE_QUANTITY*b.RELATION,a.QUANTITY=a.QUANTITY*b.RELATION;
commit;
--查询汇总结果:记录类型0药品记录,1期初,2入库,3盘点盈亏,4出库,5报损
open v_result for
with ect_sum as (
select DRUG_ID,sum(PRE_QUANTITY) PRE_QUANTITY,
sum(case when RECORD_FLAG=2 then QUANTITY else 0 end) IN_QUANTITY,
sum(case when RECORD_FLAG=4 then QUANTITY else 0 end) OUT_QUANTITY,
sum(case when RECORD_FLAG=3 then QUANTITY else 0 end) INV_QUANTITY,
sum(case when RECORD_FLAG=5 then QUANTITY else 0 end) LOSS_QUANTITY
from T_TMP_REPORT_YFCHSLZZ
where RECORD_FLAG>0
group by DRUG_ID
)
select a.DRUG_ID ID,c.DRUG_CODE,c.DRUG_NAME,c.SPEC,b.DRUG_UNIT_ID,
(select PACKAGE_UNIT from T_PHARMACY_DRUG_PACKAGE where ID=b.DRUG_UNIT_ID) UNIT_NAME,
c.DRUG_TYPE_ID,d.name DRUG_TYPE_NAME,
ROUND(a.PRE_QUANTITY/b.RELATION,4) PRE_QUANTITY,
ROUND(a.IN_QUANTITY/b.RELATION,4) IN_QUANTITY,
ROUND(a.OUT_QUANTITY/b.RELATION,4) OUT_QUANTITY,
ROUND(a.INV_QUANTITY/b.RELATION,4) INV_QUANTITY,
ROUND(a.LOSS_QUANTITY/b.RELATION,4) LOSS_QUANTITY,
ROUND((a.PRE_QUANTITY+a.IN_QUANTITY-a.OUT_QUANTITY+a.INV_QUANTITY-a.LOSS_QUANTITY)/b.RELATION,4) FINAL_QUANTITY
from ect_sum a
join T_TMP_REPORT_YFCHSLZZ b on a.DRUG_ID=b.DRUG_ID and b.RECORD_FLAG=0
join T_PHARMACY_DRUG c on a.DRUG_ID=c.ID and c.HOSPITAL_ID=v_hosId
left join T_SYS_DICTITEM d on d.id=c.DRUG_TYPE_ID and d.GROUP_ID='drugTypeId'
order by DRUG_TYPE_NAME,DRUG_CODE;
end P_RPT_YFCHSLZZ;
/
第三步、java代码Mapper文件调用存储过程,返回实体代码此处不再展示,方法声明:void listInOutQuantityGL(Map<String,Object> param);
<resultMap id="InOutQuantityGLResultMap" type="cn.net.sunshine.hisManagement.drugStoreReport.bean.InOutQuantityGL">
<id column="ID" property="id"/>
<result column="DRUG_CODE" jdbcType="VARCHAR" property="drugCode"/>
<result column="DRUG_NAME" jdbcType="VARCHAR" property="drugName"/>
<result column="SPEC" jdbcType="VARCHAR" property="spec"/>
<result column="DRUG_UNIT_ID" jdbcType="DECIMAL" property="drugUnitId"/>
<result column="UNIT_NAME" jdbcType="VARCHAR" property="unitName"/>
<result column="DRUG_TYPE_ID" jdbcType="DECIMAL" property="drugTypeId"/>
<result column="DRUG_TYPE_NAME" jdbcType="VARCHAR" property="typeName"/>
<result column="PRE_QUANTITY" jdbcType="DECIMAL" property="preQuantity"/>
<result column="IN_QUANTITY" jdbcType="DECIMAL" property="inQuantity"/>
<result column="OUT_QUANTITY" jdbcType="DECIMAL" property="outQuantity"/>
<result column="INV_QUANTITY" jdbcType="DECIMAL" property="invQuantity"/>
<result column="LOSS_QUANTITY" jdbcType="DECIMAL" property="lossQuantity"/>
<result column="FINAL_QUANTITY" jdbcType="DECIMAL" property="finalQuantity"/>
</resultMap> <!--收发存数量汇总查询-->
<select id="listInOutQuantityGL" parameterType="java.util.Map" statementType="CALLABLE">
call P_RPT_YFCHSLZZ(
#{v_typeIds,mode=IN,jdbcType=VARCHAR},
#{v_drugId,mode=IN,jdbcType=VARCHAR},
#{v_deptId,mode=IN,jdbcType=DECIMAL},
#{v_hosId,mode=IN,jdbcType=DECIMAL},
#{v_disableDrug,mode=IN,jdbcType=DECIMAL},
#{v_beginDate,mode=IN,jdbcType=DATE},
#{v_endDate,mode=IN,jdbcType=DATE},
#{v_result,jdbcType=CURSOR,mode=OUT,javaType=ResultSet, resultMap=InOutQuantityGLResultMap}
)
</select>
第四步、java中Service层调用代码,这样就可以获取存储过程返回的结果集。
@Override
public List<InOutQuantityGL> listInOutQuantityGL(InOutQuantityGLQuery queryParam) {
Map<String,Object> param =new HashMap<String, Object>();
param.put("v_drugId",queryParam.getDrugId()==null?"":queryParam.getDrugId().toString());
if (queryParam.getDrugType()==null || queryParam.getDrugType().length<=0){
param.put("v_typeIds","");
}
else{
String typeIds = StringUtils.join(queryParam.getDrugType(),",");
param.put("v_typeIds",typeIds);
}
param.put("v_deptId",queryParam.getDeptId());
param.put("v_hosId",queryParam.getHosId());
param.put("v_disableDrug",queryParam.getIncludeDisable()?1:0);
param.put("v_beginDate",queryParam.getBeginDate());
param.put("v_endDate",queryParam.getEndDate());
drugStoreReportMapper.listInOutQuantityGL(param);
List<InOutQuantityGL> list = (List<InOutQuantityGL>)param.get("v_result");
Integer rowNo = 1;
for (InOutQuantityGL item:list){
item.setRowNo(rowNo);
rowNo++;
}
return list;
}
oracle使用存储过程返回游标实现报表查询的更多相关文章
- oracle ibatis 存储过程 返回游标 嵌套表
自己解决问题了 问题总结: 1.index by表不能存储在数据库中的type中,故选择嵌套表. 2.ibatis不支持oracle的复合数据类型的返回.(个人理解) 3.替代方案:用返回oracle ...
- java 调用oracle 分页存储过程 返回游标数据集
1.分页类 package org.zh.basic; /** * 页面类 * * @author keven * */ public class PageInfo { // 定义 private S ...
- PB中用oracle的存储过程返回记录集做数据源来生成数据窗口,PB会找不到此存储过程及不能正常识别存储过程的参数问题(转)
(转)在PB中用oracle的存储过程返回记录集做数据源来生成数据窗口 首先oracle的存储过程写法与MSSQL不一样,差别比较大. 如果是返回数据集的存储过程则需要利用oracle的包来定义游标. ...
- mybatis 调用存储过程 返回游标 实例
存储过程示例: create or replace procedure Fsp_Plan_CheckPrj(v_grantno varchar2, v_deptcode number, v_curso ...
- ibatis调存储过程返回游标
http://blog.sina.com.cn/s/blog_6f3ca78f01010pmj.html iBatic调用与JAVA调用很类似,只是JAVA把参数的注册放到了类里面,而iBatis把参 ...
- myabatis oracle 调用存储过程返回list结果集
Mapper.xml 配置 <resultMap type="emp" id="empMap"> <id property="emp ...
- sqlserver 存储过程返回游标的处理
创建表: create table tb1( id int , name ) ) ------------------------------------------------- 创建返回游标的存储 ...
- Oracle使用存储过程返回查询游标
如果报表逻辑非常复杂的话, 可以把报表逻辑放到存储过程里,加工一个全局临时表.前端查询的时候只查询临时表即可.只是第一次查询需要忍受加工的时间. --创建存储过程,返回SYS_REFCURSOR CR ...
- myBatIs.Net 调用Oracle 存储过程返回游标
找了好久,网上也没示例,全是java的,没办法,后来看到一个网上别人写的例子. http://www.myfirm.cn/blog/article/Control/13.html 上面照套还是出错,我 ...
- Oracle存储过程返回游标实例详解
复制代码 代码如下:CREATE OR REPLACE PROCEDURE PROCSENDEMAIL(P_TXT VARCHAR2, P_SUB VARCHAR2, P_SENDOR VARCHAR ...
随机推荐
- Python基础:Python可变对象和不可变对象
Python在heap中分配的对象分成两类:可变对象和不可变对象.所谓可变对象是指,对象的内容是可变的,例如list.而不可变的对象则相反,表示其内容不可变. 不可变对象:int,string,flo ...
- linux模拟HID USB设备及wireshark USB抓包配置
目录 1. 内核配置 2. 设备配置 附 wireshark USB抓包配置 笔者开发USB设备时的一些记录 1. 内核配置 内核启用USB Gadget,使用fs配置usb device信息. De ...
- [Cnblogs.Architecture][v20.5.1] 使用 AddLongToJsonConverter() 将 long 序列化为 string
场景 浏览器的 JSON 反序列化无法完整将 long 类型转换为 number,最后一位会被四舍五入. 因此需要将 long 类型转为 string 发送到前端. 适用版本 v20.5.1 使用方法 ...
- Vue实现记住账号密码功能
实现思路: 用户登录时若勾选"记住我"功能选项,则将登录名和密码(加密后)存入本地缓存,下次登录页面加载时自动获取保存好的账号和密码(需解密),回显到登录输入框中. 说到存入本地缓 ...
- LINUX通过STTY命令操作串口设备(LINUX串口操作命令)
stty(settty,设置tty)命令用于检查和修改当前注册的终端的通信参数 1.显示某个串口参数信息:stty -F /dev/ttySTM6 -a 2.设置某个串口参数信息: ...
- 【Amadeus原创】域用户完美执行应用程序
企业环境中,为了安全起见一般都没有赋予域用户或者企业的PC客户端用户管理员权限. 但偶尔会有个别的程序一定需要管理员身份才能执行,如财务某些程序或专业的应用程序.那么如何不赋予用户管理员权限及密码但又 ...
- R数据分析:网络分析的做法,原理和复现方法
对于复杂问题和现象行为的研究,尤其是他们之间还有复杂的交互影响(complex interplay)的时候,网络分析(备用名:psychological networks, network analy ...
- Teams 无法访问的问题
排除以下 login.partner.microsoftonline.cn; login.microsoftonline.com; microsoft.com; live.com; hotmail.c ...
- 夜莺 v8 第一个版本来了,开始做有意思的功能了
夜莺 v8 大版本已经启动开发,预计 25 年 7.8 月份发正式版,相比 v7 大概会做四五个大功能,每个功能做完了做稳定了都会提前放出来供大家体验,虽然以 beta 来命名,实际是稳定的,大家可以 ...
- 龙哥量化:通达信常用指标写法macd数值太小怎么办macd的数值是0.01怎么放大
1.先放公式 MACD 放大坐标系 1000倍 参数 12.26.9DIF:EMA(CLOSE*1000,12)-EMA(CLOSE*1000,26);DEA:EMA(DIF,9);MACD:(DIF ...