ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

ORACLE存储过程中使用游标+BULK COLLECT的应用

2021-11-17 11:06:11  阅读:203  来源: 互联网

标签:-- 游标 st BULK COLLECT NUMBER ow ID id


经过半天的折腾,编译通过调试结果正确,掌握此过程中的知识点,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;
/

 

标签:--,游标,st,BULK,COLLECT,NUMBER,ow,ID,id
来源: https://www.cnblogs.com/sdlz/p/15566193.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有