经过半天的折腾,编译通过调试结果正确,掌握此过程中的知识点,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的应用的更多相关文章

  1. oracle存储过程中循环游标,变量的引用

    创建出错时使用: show errors查看具体的错误提示 一. 存储过程中的一个循环及变量引用示例: create or replace procedure my_proiscursor cur i ...

  2. Oracle数据库之FORALL与BULK COLLECT语句

    Oracle数据库之FORALL与BULK COLLECT语句 我们再来看一下PL/SQL块的执行过程:当PL/SQL运行时引擎处理一块代码时,它使用PL/SQL引擎来执行过程化的代码,而将SQL语句 ...

  3. Oracle存储过程中异常Exception的捕捉和处理

    Oracle存储过程中异常的捕捉和处理 CREATE OR REPLACE Procedure Proc_error_process ( v_IN in Varchar2, v_OUT Out Var ...

  4. ORACLE存储过程中%TYPE和%ROWTYPE的区别

    ORACLE存储过程中%TYPE和%ROWTYPE的区别 在存储过程中%TYPE和%ROWTYPE常用来在PL/SQL中定义变量 因为 t_emp emp%rowtype ;这个语句的意思是 定义一个 ...

  5. Oracle存储过程中跳出循环的写法

    注:本文来源于: <  Oracle存储过程中跳出循环的写法   > Oracle存储过程中跳出循环的写法 记录exit和return的用法 1:exit用来跳出循环 loop IF V_ ...

  6. Oracle存储过程中异步调用的实际操作步骤

    本文标签:Oracle存储过程 我们都知道在Oracle数据库的实际应用的过程中,我们经常把相关的业务处理逻辑,放在Oracle存储过程中,客户端以通过ADO来进行相关的调用  .而有些相关的业务逻辑 ...

  7. java 实现往oracle存储过程中传递array数组类型的参数

    注:本文来源于 <  java 实现往oracle存储过程中传递array数组类型的参数  >最近项目中遇到通过往存储过程传递数组参数的问题, 浪费了N多个小时,终于有点头绪. 具体的代码 ...

  8. oracle存储过程中使用execute immediate执行sql报ora-01031权限不足的问题

    oracle存储过程中使用execute immediate执行sql报ora-01031权限不足的问题 学习了:http://blog.csdn.net/royzhang7/article/deta ...

  9. oracle存储过程中%type的含义

    转: oracle存储过程中%type的含义 2018-11-07 11:43:56 lizhi_ma 阅读数 1361更多 分类专栏: 数据库   版权声明:本文为博主原创文章,遵循CC 4.0 B ...

  10. 在ORACLE存储过程中创建临时表

    在ORACLE存储过程中创建临时表 存储过程里不能直接使用DDL语句,所以只能使用动态SQL语句来执行 --ON COMMIT DELETE ROWS 说明临时表是事务指定,每次提交后ORACLE将截 ...

随机推荐

  1. Python 爬虫必备杀器,xpath 解析 HTML

    最近工作上写了个爬虫,要爬取国家标准网上的一些信息,这自然离不了 Python,而在解析 HTML 方面,xpath 则可当仁不让的成为兵器谱第一. 你可能之前听说或用过其它的解析方式,像 Beaut ...

  2. 基于surging的木舟平台如何分布式接入设备

    一.概述 上篇文章介绍了木舟通过基于木舟平台浅谈surging 的热点KEY的解决方法,那么此篇文章将介绍基于surging的木舟平台如何分布式接入设备. 木舟 (Kayak) 是什么? 木舟(Kay ...

  3. manim边做边学--曲面

    Surface类是Manim中专为创建和操控复杂的三维表面而打造的. 在实际应用中,无论是创建数学教学中的几何模型,还是模拟物理现象中的曲面变化,甚至是构建复杂的动画场景中的三维元素,Surface类 ...

  4. vue ssr error: TypeError: Cannot read property 'replace' of undefined

    在开发vue ssr应用时, yarn build  yarn start 之后启动正常: info Server running at: http://0.0.0.0:6606 在访问页面时,发现页 ...

  5. E. Photoshoot for Gorillas

    题意 给定一个整数 \(T\),代表共有\(T\)组测试用例,对于每组测试用例: 给定四个整数 \(n,m,k和w(1 \leq n,m \leq 2 * 10^5, 1 \leq w \leq n ...

  6. PM-从后微服务谈架构演进

    2022 年,关于微服务发生了几件有趣的事情. 其一,正式掌管 Twitter 不久的 Elon Musk 对 Twitter 的开发团队 "批判" 了一番.他表示自己为 Twit ...

  7. Mysql8忽略大小写的解决方案

    ​一.删除服务器数据文件 由于8.0没法设置参数后重启(失败),所以必须删掉老库,重新启动才行. 切记::本步骤要删掉老库所有资料,如果是数据库当前有用,请做好备份,再进行操作. systemctl ...

  8. 使用 ASP.NET Core 5 Web API 创建可发现的 HTTP API

    使用 ASP.NET Core 5 Web API 创建可发现的 HTTP API https://devblogs.microsoft.com/aspnet/creating-discoverabl ...

  9. 巧用mask属性创建一个纯CSS图标库

    说明 mask 是CSS中的一个属性,它允许开发者在元素上设置图像作为遮罩层.这个属性的强大之处,在于它可以接受多种类型的值,包括关键字值.图像值.渐变色,甚至可以设置多个属性值. SVG(Scala ...

  10. Nginx make报错处理

    https://blog.csdn.net/zhengdong12345/article/details/130669711 make报错:fatal error:sys/sysctl.h:No su ...