在库存处理的业务中有这么一个场景,一张处方划价单进行库存扣减处理,如果此单据同一商品有两行以上,同时扣减同一行库存记录,使用MERGE INTO批量更新是就会报错:ORA-30926 无法在源表中获得稳定的行。
库存表T_DRUGSTORE_DRUG_STOCK_TEMP 的记录
处方划价单T_OPD_QUOTN的记录(待出库信息),注意:这里 1、2行的同时要扣减了库存表中ID是93498记录的库存。
以上情况使用以下语句会因为批量更新时被更新的表记录出现了一对多行匹配导致异常错误
在扣减库存前要确保匹配行不能出现一对多,以下实现这里主要四点作为了解
1、使用 COUNT(distinct STOCK_ID) 求得单据药品涉及到的库存记录数。
2、MERGE INTO中的USING子查询使用了分组在库存扣减前对出库记录按照药品库存的ID进行分组求和待出库数量。
3、更新库存的时候使用 WHERE a.QUANTITY>=b.BASE_QUANTITY 仅更新库存足够的记录,后面通过 SQL%ROWCOUNT!=tn_rowcount 验证是否期待的库存记录都被更新了。
4、这样处理批量更新比逐行循环更新处理高效。
--取得出库单药品品种数和待出库总数量
SELECT COUNT(distinct STOCK_ID) AS rowcount,NVL(SUM(QUANTITY),0) AS quantity
INTO tn_rowcount,tn_quantity
FROM T_OPD_QUOTN WHERE HOSPITAL_ID=ow_hosid AND ORDER_WRITE_ID=writeId;
IF ow_count!=tn_quantity THEN
mess:='医嘱药品数量'||ow_count||'与划价单数量合计'||tn_quantity||'不符!';
RETURN;
END IF;
--进行库存扣减处理,更新划价单对应批次结存数量
MERGE INTO T_DRUGSTORE_DRUG_STOCK_TEMP a
USING (SELECT STOCK_ID,sum(BASE_QUANTITY) as BASE_QUANTITY FROM T_OPD_QUOTN
WHERE HOSPITAL_ID=ow_hosid AND ORDER_WRITE_ID=writeId GROUP BY STOCK_ID) b ON (a.ID=b.STOCK_ID)
WHEN MATCHED THEN UPDATE SET a.QUANTITY=a.QUANTITY-b.BASE_QUANTITY,UPDATE_OPER=operateId,UPDATE_DATE=SYSDATE WHERE a.QUANTITY>=b.BASE_QUANTITY;
IF SQL%ROWCOUNT!=tn_rowcount THEN
mess:='临时库存更新'||SQL%ROWCOUNT||'行,与划价记录行'||tn_rowcount||'不符,操作无效!';
RETURN;
END IF;