Oracle嵌套循环运行异常(超出最大范围)问题排查
PL/SQL数据插入逻辑修复
非空due_date原有逻辑故障点
- 计数器
x定义在循环外层,处理完第一条记录后不会重置,后续记录的偏移量计算完全错误 - INSERT语句的SELECT子句未限制当前行,每次循环会插入所有due_date非空的记录,产生大量冗余错误数据
- 起始日期计算不符合规则:原逻辑未严格取sysdate的年月+opening_date的日作为起始值
- 截止判断使用
<会漏掉刚好等于due_date的月份,不符合「持续到due_date为止」的要求
修正后的非空due_date处理代码
DECLARE v_start_date DATE; v_curr_date DATE; BEGIN FOR rec IN (SELECT * FROM z_exp14_main WHERE due_date IS NOT NULL) LOOP -- 按规则生成起始日期:取系统时间的年、月,拼接开户日期的日 v_start_date := TO_DATE(TO_CHAR(SYSDATE, 'YYYYMM') || TO_CHAR(rec.opening_date, 'DD'), 'YYYYMMDD'); -- 兼容开户日大于当月最大天数的场景,取当月最后一天 v_start_date := LEAST(v_start_date, LAST_DAY(SYSDATE)); v_curr_date := v_start_date; WHILE v_curr_date <= rec.due_date LOOP -- 直接插入当前循环行数据,避免全表查询 INSERT INTO z_exp14_resualt VALUES (rec.dep_id, v_curr_date, rec.rate * rec.balance); v_curr_date := ADD_MONTHS(v_curr_date, 1); END LOOP; END LOOP; -- 统一提交事务,可根据数据量调整提交频率 COMMIT; END; /
原有正常逻辑(due_date为空)参考
declare i number := 1; BEGIN for i in 1..12 loop insert into z_exp14_resualt select dep_id,ADD_MONTHS(ADD_MONTHS(opening_date,trunc( months_between (sysdate,opening_date))),i),rate*balance from z_exp14_main WHERE due_date IS null; end loop; COMMIT; END; /
z_exp14_main样例表参考
| DEP_ID | DUE_DATE | BALANCE | RATE | OPENING_DATE |
|---|---|---|---|---|
| 20056634 | null | 283428 | 10 | 15-SEP-16 |
| 20056637 | null | 180222 | 10 | 07-NOV-14 |
| 20056639 | null | 58741 | 10 | 28-AUG-14 |
| 40000020 | 27-NOV-21 | 5000000 | 22 | 31-MAR-14 |
| 40000023 | 23-APR-21 | 63000000 | 22 | 25-AUG-18 |
内容的提问来源于stack exchange,提问作者Zakaro
相关产品推荐
相关产品推荐

