Oracle Apex POS系统输入重复序列号时自动递增数量不重复入库问题
代码问题诊断
SELECT COUNT(*)语句不会触发NO_DATA_FOUND异常:无论是否存在匹配记录,COUNT(*)都会返回一行结果,无匹配时返回值为0,因此你代码中写的异常分支永远不会执行,当商品第一次扫描时,既不会进入更新逻辑,也不会执行异常里的插入逻辑,如果动态动作中还有其他默认插入逻辑,就会每次都生成新记录。- 绑定变量名不一致:查询和更新条件中使用的小票ID是
:P21_MASTER_ID,插入语句中用的小票ID是:P21_PTM_ID,如果两个变量值不匹配,会导致查询不到已存在的同商品记录,每次都执行插入,产生重复数据。 - 更新逻辑错误:
v_count是符合条件的记录行数,不是该商品的当前购买数量,直接将QUANTITY赋值为v_count+1不符合业务需求,正确逻辑应为原有商品数量自增1。 - 插入语句语法错误:插入值列表末尾多了一个多余的逗号,会触发语法报错。
最优修复方案
直接使用Oracle原生的MERGE语句实现「存在则更新、不存在则插入」的逻辑,无需自行编写异常判断,性能和可靠性更高,修复后代码如下:
MERGE INTO POS_TRANS_DETAIL ptd USING dual ON (ptd.PTM_ID = :P21_MASTER_ID AND ptd.serial_number = :P21_SERIAL_NUMBER) WHEN MATCHED THEN -- 已有相同商品,数量加1 UPDATE SET ptd.QUANTITY = ptd.QUANTITY + 1 WHEN NOT MATCHED THEN -- 无相同商品,插入新记录,初始数量为1 INSERT (TRANS_DETAIL_ID, PTM_ID, serial_number, COST_PRICE, QUANTITY) VALUES (TRANS_DETAIL_ID.nextval, :P21_MASTER_ID, :P21_SERIAL_NUMBER, :P21_COST_PRICE, 1);
额外优化建议
- 统一绑定变量:如果业务中小票ID的正确变量名是
:P21_PTM_ID,将上述代码中所有:P21_MASTER_ID替换为对应变量即可,保证全逻辑变量名一致。 - 增加数据库约束:给
POS_TRANS_DETAIL表添加(PTM_ID, serial_number)联合唯一约束,从数据库层面阻止重复记录生成,双重保障数据一致性。 - 清理冗余逻辑:检查动态动作配置,删除原有额外的自动插入记录逻辑,避免重复执行插入。
内容的提问来源于stack exchange,提问作者Omar Z. AL-Khatib
相关产品推荐
相关产品推荐

