ORACLE存储过程中使用游标+BULK COLLECT的应用
经过半天的折腾,编译通过调试结果正确,掌握此过程中的知识点,oracle存储过程编写就应用到了90%。
CREATE OR REPLACE PROCEDURE JUNAN.P_IPT_QUOTN_INS (
--住院医嘱发药申请药品划价过程
writeId IN INT, --医嘱记录id
applyId IN INT, --发药申请id
operateId IN INT, --操作员id
exprdate IN INT, --减少库存时批次:0不控制效期,1控制效期
amount OUT NUMBER, --划价后得到的药品金额
mess OUT VARCHAR2 --OK为执行成功
)
IS
--本组变量保存医嘱信息
ow_drugId VARCHAR2(30); --药品id
ow_drugName VARCHAR2(120); --药品名称
ow_drugTypeId VARCHAR2(30); --药品类别id
ow_unitName VARCHAR2(30); --药品单位名称
ow_unitId NUMBER(12,0); --药品包装单位id
ow_count NUMBER(12,4); --药品数量
ow_baseCount NUMBER(12,4); --按基本单位算的药品数量
ow_status VARCHAR2(4); --医嘱状态
ow_deptId NUMBER(12,0); --药房id
ow_hosId NUMBER(12,0); --医院id
ow_relation NUMBER(12,6); --药品包装单位换算比
--本组变量保存临时库存批次信息
st_rowid ROWID; --库存批次表行系统rowid
st_id INT; --库存游标保存变量 库存记录id
st_unitId INT; --库存包装单位id
st_relation NUMBER(22,6); --换算比
st_count NUMBER(22,4); --库存数量
st_price NUMBER(22,6); --药房包装单位的零售价格
st_cost_price NUMBER(22,6); --药房包装单位的成本价格
--其他变量
per_quantity NUMBER(22,4) :=0; --每次库存循环处理数量
per_basequantity NUMBER(22,4) :=0; --每次库存循环处理基本单位数量
per_amount NUMBER(22,2) :=0; --每次库存循环处理金额
total_quantity NUMBER(22,4) :=0; --累计数量
total_amount NUMBER(22,2) :=0; --累计金额
operateName VARCHAR2(60); --操作员姓名
--库存处理游标
CURSOR cur_stock IS
SELECT ROWID AS ROW_ID FROM T_DRUGSTORE_DRUG_STOCK_TEMP T
WHERE T.STATUS = '1' AND T.BATCH_INVALID = '1'
AND (CASE WHEN exprdate=1 THEN T.EXPIRATION_DATE ELSE TO_DATE('9999-12-31','YYYY-MM-dd') END) >= trunc(sysdate)
AND T.QUANTITY > 0 AND T.DEPT_ID=ow_deptId AND T.DRUG_ID =ow_drugId
order by EXPIRATION_DATE;
TYPE TP_TABLE_STOCK IS TABLE OF CUR_STOCK%ROWTYPE; --声明游标行类型的数据集类型
cllo_stock TP_TABLE_STOCK; --集合类型变量
BEGIN
mess:='';
--取得医嘱信息
BEGIN
SELECT DOCTOR_ORDER_ID,DOCTOR_ORDER_NAME,DRUG_COUNT,DRUG_COUNT_UNIT,DRUG_UNIT_ID,ORDER_STATUS_ID,EXECUTIVE_SECTION_ID,HOSPITAL_ID
INTO ow_drugId,ow_drugName,ow_count,ow_unitName,ow_unitId,ow_status,ow_deptId,ow_hosId
FROM T_IPT_DOCTOR_ORDER_WRITE WHERE DOCTOR_ORDER_TYPE_ID='drug' AND id=writeId FOR UPDATE NOWAIT;
EXCEPTION WHEN NO_DATA_FOUND THEN
mess:='住院医嘱记录不存在!';
RETURN;
END;
--取得医嘱药品包装单位换算比,药品类别id
BEGIN
SELECT a.RELATION,b.DRUG_TYPE_ID INTO ow_relation,ow_drugTypeId from T_PHARMACY_DRUG_PACKAGE a
INNER JOIN T_PHARMACY_DRUG b ON b.ID=A.DRUG_ID
WHERE ROWNUM=1 and a.STATUS='1' and a.ID=ow_unitId;
EXCEPTION WHEN NO_DATA_FOUND THEN
mess:='查询药品包装单位换算比无数据!';
RETURN;
END;
IF ow_relation IS NULL THEN
mess:='药品包装单位换算比为null!';
RETURN;
END IF;
--取操作员信息
BEGIN
SELECT name INTO operateName FROM T_SYS_OPERATOR WHERE id=operateId;
EXCEPTION WHEN NO_DATA_FOUND THEN
mess:='操作员记录不存在!';
RETURN;
END;
--换算医嘱药品数量为基本单位数量
ow_baseCount:=ROUND(ow_count*ow_relation,4);
--打开动态游标,将临时库存中本药品有效批次库存的行id保存用于后续扣减处理
open cur_stock;
LOOP
--遍历库存记录进行库存处理
FETCH CUR_STOCK BULK COLLECT INTO cllo_stock LIMIT 200;
EXIT WHEN cllo_stock.COUNT=0;
FOR i IN cllo_stock.FIRST..cllo_stock.LAST
LOOP
st_rowid:=cllo_stock(i).ROW_ID;
--取得当前id批次库存信息并锁定
BEGIN
SELECT ID,NEW_MAX_PACKAGE_UNIT_ID,RELATION,QUANTITY,DRUGSTORE_RETAIL_PRICE,ROUND(PURCHASE_PRICE/RELATION_MAX,6)
INTO st_id,st_unitId,st_relation,st_count,st_price,st_cost_price
FROM T_DRUGSTORE_DRUG_STOCK_TEMP WHERE QUANTITY > 0 AND ROWID=st_rowid FOR UPDATE;
EXCEPTION WHEN NO_DATA_FOUND THEN
CONTINUE;
END;
--计算本批次扣减库存数量:批次库存小于等于待出库数量时取本批结余数,否则用待出库数
per_basequantity:=(CASE WHEN st_count<=ow_baseCount THEN st_count ELSE ow_baseCount END);
per_quantity:=ROUND(per_basequantity/ow_relation,4); --计算医嘱保装单位的数量
--计算销售金额
PER_AMOUNT:=ROUND(per_basequantity/st_relation*st_price,2);
--更新本批次结存数量
UPDATE T_DRUGSTORE_DRUG_STOCK_TEMP SET QUANTITY=QUANTITY-per_basequantity,UPDATE_OPER=operateId,UPDATE_DATE=SYSDATE
WHERE QUANTITY>=per_basequantity AND ROWID=st_rowid;
IF SQL%ROWCOUNT<1 THEN
mess:='扣减临时库存更新了0行,库存记录id:'||st_id;
GOTO ExitMidway;
END IF;
--写入药品划价记录
st_cost_price:=st_cost_price*ow_relation/st_relation; --计算成本单据,防止医嘱单位和药房单位不一致
INSERT INTO T_IPT_QUOTN (
ID, HOSPITAL_ID, DEPT_ID, ORDER_WRITE_ID, APPLY_ID,STOCK_ID, DRUG_ID, UNIT_NAME,
QUANTITY,BASE_QUANTITY, PRICE, AMOUNT,
COST_PRICE,COST_AMOUNT,RETURN_QUANTITY,CREATE_TIME,CREATE_OPER)
VALUES (SEQ_IPT_QUOTN.NEXTVAL,OW_HOSID,OW_DEPTID,writeId,applyId,ST_ID,OW_DRUGID,OW_UNITNAME,
per_quantity,per_basequantity,ROUND(PER_AMOUNT/per_quantity,4),PER_AMOUNT,
st_cost_price,ROUND(per_quantity*st_cost_price,2),0,SYSDATE,operateName);
--更新累计出库数量和金额,待出库基本单位数量
TOTAL_QUANTITY:=TOTAL_QUANTITY+per_basequantity;
TOTAL_AMOUNT:=TOTAL_AMOUNT+PER_AMOUNT;
ow_baseCount:=ow_baseCount-per_basequantity;
--库存数量足额扣减退出循环
EXIT WHEN ow_baseCount=0;
END LOOP;
EXIT WHEN ow_baseCount=0;
END LOOP;
CLOSE CUR_STOCK;
--循环结束判断待出库数量如果为非零,则说明不足出库
IF ow_baseCount!=0 THEN
mess:='临时库存不足,待扣减基本单位数量:'||ow_baseCount;
RETURN;
END IF;
--更新医嘱药品费用金额
UPDATE T_IPT_DOCTOR_ORDER_WRITE SET SUM_PRICE=TOTAL_AMOUNT,
PRICE=(CASE WHEN DRUG_COUNT=0 THEN 0 ELSE ROUND(TOTAL_AMOUNT/DRUG_COUNT,4) END),UPDATE_DATE=SYSDATE
WHERE id=writeId;
amount:=TOTAL_AMOUNT;
mess:='OK';
RETURN;
<<ExitMidway>>
CLOSE CUR_STOCK;
RETURN;
EXCEPTION
WHEN NO_DATA_FOUND THEN
mess:='查询记录数据为空!';
WHEN OTHERS THEN
mess := SUBSTR(SQLERRM,1,2000);
END P_IPT_QUOTN_INS;
/
ORACLE存储过程中使用游标+BULK COLLECT的应用的更多相关文章
- oracle存储过程中循环游标,变量的引用
创建出错时使用: show errors查看具体的错误提示 一. 存储过程中的一个循环及变量引用示例: create or replace procedure my_proiscursor cur i ...
- Oracle数据库之FORALL与BULK COLLECT语句
Oracle数据库之FORALL与BULK COLLECT语句 我们再来看一下PL/SQL块的执行过程:当PL/SQL运行时引擎处理一块代码时,它使用PL/SQL引擎来执行过程化的代码,而将SQL语句 ...
- Oracle存储过程中异常Exception的捕捉和处理
Oracle存储过程中异常的捕捉和处理 CREATE OR REPLACE Procedure Proc_error_process ( v_IN in Varchar2, v_OUT Out Var ...
- ORACLE存储过程中%TYPE和%ROWTYPE的区别
ORACLE存储过程中%TYPE和%ROWTYPE的区别 在存储过程中%TYPE和%ROWTYPE常用来在PL/SQL中定义变量 因为 t_emp emp%rowtype ;这个语句的意思是 定义一个 ...
- Oracle存储过程中跳出循环的写法
注:本文来源于: < Oracle存储过程中跳出循环的写法 > Oracle存储过程中跳出循环的写法 记录exit和return的用法 1:exit用来跳出循环 loop IF V_ ...
- Oracle存储过程中异步调用的实际操作步骤
本文标签:Oracle存储过程 我们都知道在Oracle数据库的实际应用的过程中,我们经常把相关的业务处理逻辑,放在Oracle存储过程中,客户端以通过ADO来进行相关的调用 .而有些相关的业务逻辑 ...
- java 实现往oracle存储过程中传递array数组类型的参数
注:本文来源于 < java 实现往oracle存储过程中传递array数组类型的参数 >最近项目中遇到通过往存储过程传递数组参数的问题, 浪费了N多个小时,终于有点头绪. 具体的代码 ...
- oracle存储过程中使用execute immediate执行sql报ora-01031权限不足的问题
oracle存储过程中使用execute immediate执行sql报ora-01031权限不足的问题 学习了:http://blog.csdn.net/royzhang7/article/deta ...
- oracle存储过程中%type的含义
转: oracle存储过程中%type的含义 2018-11-07 11:43:56 lizhi_ma 阅读数 1361更多 分类专栏: 数据库 版权声明:本文为博主原创文章,遵循CC 4.0 B ...
- 在ORACLE存储过程中创建临时表
在ORACLE存储过程中创建临时表 存储过程里不能直接使用DDL语句,所以只能使用动态SQL语句来执行 --ON COMMIT DELETE ROWS 说明临时表是事务指定,每次提交后ORACLE将截 ...
随机推荐
- KindleVocab 教程,Kindle导出查词记录成文本文档,Kindle导出查询单词记录导入Anki
程序功能 因本人使用Kindle Mate导出觉得复杂,特意写了个自用的导出程序(有linux版本和win两个版本). 所以 KindleVocab 只有一个作用:导出Kindle查询过的生词和生词所 ...
- Sickos1.1 详细靶机思路 实操笔记
Sickos1.1 详细靶机思路 实操笔记 免责声明 本博客提供的所有信息仅供学习和研究目的,旨在提高读者的网络安全意识和技术能力.请在合法合规的前提下使用本文中提供的任何技术.方法或工具.如果您选择 ...
- Python:pygame游戏编程之旅二(自由移动的小球)
本节实现一个在窗口中自由运动的小球程序,做了详细注释,不多做解释了. 代码: # -*- coding:utf-8 -*- import sys import pygame from pygame.l ...
- java swing 学习
JSplitPane固定分割比例和禁止拖动分割条 有知友问JSplitPane的问题,在写代码的时候不想让分割条拖动,结果找不到方法,百度了 居然也找不到... 后来在一个犄角旮旯里发现了 ,, 就 ...
- 从零开始的Python世界生活——基础篇(Python字典)
从零开始的Python世界生活--基础篇(Python字典) 1.Python字典是什么? Python字典是python中非常重要的非常灵活和强大的内置数据结构,用于存储键值对(key-valu ...
- whisper v3 finetune 中文乱码问题的解决方案
最近学习了一下whisper的微调,主要是参考了github上的夜雨飘零大神项目.但是在操作中遇到了微调中文的时候出现了乱码的情况.以下是我这边对于微调过程中中文出现乱码情况的解决方案. 出现情况如下 ...
- React使用useRef调用子组件方法
前情 公司前端主技术栈是react系,最近在提取组件的时候想到vue可以通过ref获取子组件,再调用子组件的方法,于是想在react中实现同样效果. 实现原理 父组件调用useRef获取ref对象,再 ...
- 【Amadeus原创】Docker安装wikijs wiki系统
拉取mysql8的镜像并运行 docker pull mysql docker run -d -v /data/mysql/data:/var/lib/mysql -v /data/mysql/con ...
- GraphQL Part VIII: 使用一对多查询
今天,我们引入两个新的实体来处理客户与订单.客户与订单之间是一对多的关系,一个客户可以拥有一个或者多个订单,反过来,一个订单只能被某个客户所拥有. 可以按照 Engity Framework 的约定配 ...
- ChatGPT接口测试用例生成的流程
通常,使用ChatGPT生成接口测试用例的流程可以分为以下关键步骤. 收集接口信息 收集接口的相关文档和信息,如接口名称.请求方法.请求参数.返回结果等.这些是ChatGPT生成测试用例需要的输入信息 ...