Oracle PL/SQL匿名块执行成功但数据未更新问题求助
问题原因
- 第一,更新逻辑放置位置错误:你当前场景中刚好匹配到1条符合条件的行,
SELECT INTO语句会正常执行不会触发任何异常,而你把更新操作写在了TOO_MANY_ROWS(匹配行数≥2)的异常分支里,正常匹配到1条数据的场景下没有任何更新/插入操作执行,当然不会修改holiday字段。 - 第二,事务提交逻辑不全:你只在
NO_DATA_FOUND的插入分支加了COMMIT,就算更新逻辑执行了,也没有提交事务,非自动提交模式下修改只会保存在当前会话的临时空间,不会持久化到数据库,关闭会话后变更会自动回滚。 - 第三,更新语句条件不完整:原匹配条件包含
emp_pk_id='32',但UPDATE语句的WHERE条件少了这个限制,后续逻辑修正后可能会误改其他同emp_id、同att_date但emp_pk_id不同的行。
修正后的PL/SQL块
DECLARE c_emp_id att_log.emp_id%type; BEGIN SELECT emp_id INTO c_emp_id FROM att_log WHERE emp_id='19.1.0121' AND emp_pk_id='32' AND att_date='2021-10-01'; -- 匹配到1条数据时执行更新,放到正常执行分支,不是异常分支 UPDATE att_log SET holiday = 'H', updated_at = '2021-08-22' WHERE emp_id='19.1.0121' AND emp_pk_id='32' -- 补全匹配条件 AND att_date='2021-10-01'; COMMIT; -- 统一提交事务 EXCEPTION WHEN TOO_MANY_ROWS THEN -- 存在多条匹配数据的场景处理逻辑 UPDATE att_log SET holiday = 'H', updated_at = '2021-08-22' WHERE emp_id='19.1.0121' AND emp_pk_id='32' AND att_date='2021-10-01'; COMMIT; WHEN NO_DATA_FOUND THEN INSERT INTO att_log (emp_id, emp_pk_id, att_date, holiday,login_time, logout_time) VALUES ('19.1.0121', '32', '2021-10-01','H','',''); COMMIT; END; /
更推荐的实现方案
Oracle原生提供MERGE语句专门处理这种「存在则更新、不存在则插入」的Upsert场景,逻辑更清晰,也不需要手动处理异常:
MERGE INTO att_log t USING dual ON (t.emp_id = '19.1.0121' AND t.emp_pk_id = '32' AND t.att_date = '2021-10-01') WHEN MATCHED THEN UPDATE SET t.holiday = 'H', t.updated_at = '2021-08-22' WHEN NOT MATCHED THEN INSERT (emp_id, emp_pk_id, att_date, holiday, login_time, logout_time) VALUES ('19.1.0121', '32', '2021-10-01', 'H', '', ''); COMMIT; /
内容的提问来源于stack exchange,提问作者w3learners
相关产品推荐
相关产品推荐

