You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle:如何使用WHILE循环捕获FORALL SAVE EXCEPTIONS异常

用WHILE循环替代FOR循环遍历SQL%BULK_EXCEPTIONS捕获批量加载错误

以下是可直接运行的PL/SQL代码,通过WHILE循环遍历SQL%BULK_EXCEPTIONS来捕获批量操作中的错误记录:

-- 创建测试表(若已存在则跳过)
CREATE TABLE test_bulk_load (
    id NUMBER PRIMARY KEY,
    name VARCHAR2(50) NOT NULL
);

DECLARE
    -- 定义与表结构匹配的集合类型
    TYPE t_load_data IS TABLE OF test_bulk_load%ROWTYPE;
    v_load_data t_load_data := t_load_data();
    
    -- 异常遍历计数器
    v_exception_idx NUMBER := 1;
BEGIN
    -- 初始化测试数据,包含重复主键(触发唯一约束错误)和空name(触发非空约束错误)
    v_load_data.EXTEND(4);
    v_load_data(1).id := 1;
    v_load_data(1).name := 'Valid Record 1';
    v_load_data(2).id := 1; -- 重复主键,会报错
    v_load_data(2).name := 'Duplicate ID';
    v_load_data(3).id := 3;
    v_load_data(3).name := NULL; -- 空name,会报错
    v_load_data(4).id := 4;
    v_load_data(4).name := 'Valid Record 2';

    -- 批量插入,启用SAVE EXCEPTIONS捕获错误
    FORALL i IN v_load_data.FIRST..v_load_data.LAST SAVE EXCEPTIONS
        INSERT INTO test_bulk_load VALUES v_load_data(i);
        
    COMMIT;
    DBMS_OUTPUT.PUT_LINE('批量插入完成,无错误');
EXCEPTION
    WHEN OTHERS THEN
        -- 用WHILE循环遍历所有捕获到的异常
        WHILE v_exception_idx <= SQL%BULK_EXCEPTIONS.COUNT LOOP
            -- 获取错误对应的原集合索引、错误码和错误信息
            DBMS_OUTPUT.PUT_LINE('错误序号: ' || v_exception_idx);
            DBMS_OUTPUT.PUT_LINE('原数据索引: ' || SQL%BULK_EXCEPTIONS(v_exception_idx).ERROR_INDEX);
            DBMS_OUTPUT.PUT_LINE('Oracle错误码: ' || SQL%BULK_EXCEPTIONS(v_exception_idx).ERROR_CODE);
            DBMS_OUTPUT.PUT_LINE('错误信息: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(v_exception_idx).ERROR_CODE));
            DBMS_OUTPUT.PUT_LINE('--------------------------');
            
            -- 计数器自增,进入下一个异常
            v_exception_idx := v_exception_idx + 1;
        END LOOP;
        
        -- 回滚未提交的有效数据(可选,根据业务需求调整)
        ROLLBACK;
END;
/

关键说明:

  1. SQL%BULK_EXCEPTIONS是一个关联数组,索引从1开始,COUNT属性记录捕获到的异常总数
  2. 初始化计数器v_exception_idx为1,循环条件设置为v_exception_idx <= SQL%BULK_EXCEPTIONS.COUNT,确保遍历所有异常
  3. 每次循环中,通过SQL%BULK_EXCEPTIONS(v_exception_idx).ERROR_INDEX获取出错数据在原集合中的位置,ERROR_CODE获取Oracle错误码
  4. 使用SQLERRM(-错误码)可以将错误码转换为可读的错误信息(注意需要加负号)

内容的提问来源于stack exchange,提问作者Narasimhan M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 13:46:00