Oracle中如何用游标实现两张同结构表的累加更新及新数据插入
Oracle 跨表更新插入Cursor实现方案
你场景中的目标表(表A)对应你代码中的central_ave,源表(表B)对应disp_ave,主键为nombreComun,需要累加的字段为encuentros,如果是你举例的通用表结构,替换对应表名、字段名即可使用。
正确Cursor实现代码
DECLARE -- 定义变量存储源表遍历数据 v_nombreCientifico VARCHAR2(50); v_nombreComun VARCHAR2(50); v_color VARCHAR2(50); v_fotografia VARCHAR2(255); v_envergadura FLOAT; v_encuentros INT; -- 计数变量用于判断主键是否存在 v_exists_flag INT; -- 游标遍历源表所有待同步数据 CURSOR cur_source IS SELECT nombreCientifico, nombreComun, color, fotografia, envergadura, encuentros FROM disp_ave; BEGIN OPEN cur_source; LOOP -- 读取游标数据到变量 FETCH cur_source INTO v_nombreCientifico, v_nombreComun, v_color, v_fotografia, v_envergadura, v_encuentros; EXIT WHEN cur_source%NOTFOUND; -- 校验目标表是否存在对应主键记录 SELECT COUNT(1) INTO v_exists_flag FROM central_ave WHERE nombreComun = v_nombreComun; IF v_exists_flag > 0 THEN -- 存在则累加更新对应字段 UPDATE central_ave SET encuentros = encuentros + v_encuentros WHERE nombreComun = v_nombreComun; ELSE -- 不存在则插入整条记录 INSERT INTO central_ave(nombreCientifico, nombreComun, color, fotografia, envergadura, encuentros) VALUES(v_nombreCientifico, v_nombreComun, v_color, v_fotografia, v_envergadura, v_encuentros); END IF; END LOOP; CLOSE cur_source; -- 事务提交,测试阶段可先注释确认数据正确再打开 COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; END; /
更高性能的原生替代方案
Oracle 提供的MERGE语句原生支持「存在更新、不存在插入」的逻辑,无需游标遍历,执行效率和代码简洁度都更高,推荐优先使用:
MERGE INTO central_ave a USING disp_ave b ON (a.nombreComun = b.nombreComun) WHEN MATCHED THEN UPDATE SET a.encuentros = a.encuentros + b.encuentros WHEN NOT MATCHED THEN INSERT(nombreCientifico, nombreComun, color, fotografia, envergadura, encuentros) VALUES(b.nombreCientifico, b.nombreComun, b.color, b.fotografia, b.envergadura, b.encuentros); COMMIT; /
原有代码的问题梳理
- 游标过滤条件
WHERE nombreComun = disp_ave.nombreComun恒成立,无实际过滤作用 UPDATE语句写在FETCH取数之前,且多余分号、未加更新条件,会导致全表被错误更新- 变量未做命名区分,容易和表字段产生命名冲突
- 缺少主键存在性判断逻辑,无插入分支
- 存在多余的
END IF语句,没有对应的起始IF块
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

