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

Oracle 12.1 JSON_TABLE查询报ORA-40441错误无法加载全部JSON记录

问题解决方法

一、定位出错记录

你当前代码无法捕获错误的核心原因是:ORA-40441属于JSON解析阶段抛出的错误,发生在游标遍历JSON_TABLE结果的环节,还没进入循环内的异常捕获逻辑,所以错误直接中断了整个流程,无法定位到具体问题行。

可以用以下两种方法快速定位错误:

  • 直接用Oracle内置IS_JSON函数筛选非法JSON行:
SELECT ROWID, jsonfile 
FROM json_access_addresses 
WHERE IS_JSON(jsonfile) = 0;

该查询返回的所有行都是存在JSON语法错误的CLOB记录,你可以导出这些记录核对格式,比如你给出的示例JSON里两个数组对象之间缺少逗号,就属于这类典型语法错误。

  • 若需要定位数组内单条非法节点,可通过分批遍历缩小范围,每次处理100~1000行原始记录,哪一批报错就继续拆分排查,直到找到具体问题行。

二、实现全量加载

修改原有逻辑,改成逐行解析原始CLOB,单独捕获每一行的解析错误,错误行存入专门的错误表后跳过,不影响整体加载流程:

  1. 先创建错误记录表,用于存储解析失败的行信息:
CREATE TABLE json_parse_errors (
    err_time TIMESTAMP DEFAULT SYSTIMESTAMP,
    source_rowid ROWID,
    error_msg VARCHAR2(4000)
);
  1. 修改后的PL/SQL加载代码如下:
SET SERVEROUTPUT ON SIZE UNLIMITED;
DECLARE
    -- 遍历原始JSON表的所有行,不提前做JSON解析
    CURSOR c_raw IS SELECT ROWID rid, jsonfile FROM json_access_addresses;
    v_success_cnt NUMBER := 0;
    v_err_msg VARCHAR2(4000);
BEGIN
    -- 清空目标表和错误表,TRUNCATE比DELETE效率更高
    EXECUTE IMMEDIATE 'TRUNCATE TABLE dawa_access_addresses';
    EXECUTE IMMEDIATE 'TRUNCATE TABLE json_parse_errors';

    FOR rec_raw IN c_raw LOOP
        BEGIN
            -- 单独解析当前行的JSON内容,插入目标表
            INSERT INTO dawa_access_addresses(STATUS, SOURCE, CREATED, CHANGED, INFORCE, MUNICIPALITY_CODE, STREET_CODE, STREET_NO, ZIP_CODE, X_COORDINATE, Y_COORDINATE, PROPERTY_ID, ACCURACY, ADDRESS_CHANGE_DATE, ELEVATION, ADDITIONAL_CITY_NAME_ID, ID, ADDITIONAL_CITY_NAME, CADASTRE_ID, STREET_NO_SOURCE, TECHNICAL_STANDARD, TEXT_DIRECTION, ESDHREFERENCE, JOURNAL_NUMBER, ACCESS_POINT_ID, STREET_POINT_ID, NAMED_STREET_ID)
            SELECT STATUS, SOURCE, CREATED, CHANGED, INFORCE,
                   MUNICIPALITY_CODE, STREET_CODE, STREET_NO, ZIP_CODE, X_COORDINATE, Y_COORDINATE, 
                   PROPERTY_ID, ACCURACY, ADDRESS_CHANGE_DATE, ELEVATION, ADDITIONAL_CITY_NAME_ID,
                   ID_1, ADDITIONAL_CITY_NAME, CADASTRE_ID, STREET_NO_SOURCE, TECHNICAL_STANDARD, TEXT_DIRECTION,
                   ESDHREFERENCE, JOURNAL_NUMBER, NAMED_STREET_ID,
                   ACCESS_POINT_ID, STREET_POINT_ID
            FROM JSON_TABLE(rec_raw.jsonfile, '$.adgangsadresser[*]' 
                COLUMNS (
                STATUS      NUMBER PATH '$.status',  
                SOURCE VARCHAR2(64) PATH '$.kilde',
                CREATED VARCHAR2(32) PATH '$.oprettet',
                CHANGED VARCHAR2(32) PATH '$.aendret',
                INFORCE VARCHAR2(32) PATH '$.ikrafttraedelsesdato',
                MUNICIPALITY_CODE VARCHAR2(4) PATH '$.kommunekode',
                STREET_CODE VARCHAR2(4) PATH '$.vejkode',
                STREET_NO VARCHAR2(16) PATH '$.husnr',
                ZIP_CODE VARCHAR2(4) PATH '$.postnr',
                X_COORDINATE VARCHAR2(16) PATH '$.etrs89koordinat_oest',
                Y_COORDINATE VARCHAR2(16) PATH '$.etrs89koordinat_nord',
                PROPERTY_ID VARCHAR2(16) PATH '$.esrejendomsnr',
                ACCURACY VARCHAR2(4) PATH '$.noejagtighed',
                ADDRESS_CHANGE_DATE VARCHAR2(32) PATH '$.adressepunktaendringsdato',
                ELEVATION      VARCHAR2(16) PATH '$.hoejde',  
                ADDITIONAL_CITY_NAME_ID VARCHAR2(64) PATH '$.supplerendebynavn_dagi_id',
                ID_1 VARCHAR2(64) PATH '$.id',
                ADDITIONAL_CITY_NAME VARCHAR2(256) PATH '$.supplerendebynavn',
                CADASTRE_ID VARCHAR2(64) PATH '$.matrikelnr',
                STREET_NO_SOURCE VARCHAR2(16) PATH '$.husnummerkilde',
                TECHNICAL_STANDARD VARCHAR2(16) PATH '$.tekniskstandard',
                TEXT_DIRECTION VARCHAR2(16) PATH '$.tekstretning',
                ESDHREFERENCE VARCHAR2(64) PATH '$.esdhreference',
                JOURNAL_NUMBER VARCHAR2(64) PATH '$.journalnummer',
                ACCESS_POINT_ID VARCHAR2(64) PATH '$.adgangspunktid',
                STREET_POINT_ID VARCHAR2(64) PATH '$.vejpunkt_id',
                NAMED_STREET_ID VARCHAR2(64) PATH '$.navngivenvej_id'
                )
            );
            v_success_cnt := v_success_cnt + SQL%ROWCOUNT;
        EXCEPTION
            WHEN OTHERS THEN
                v_err_msg := SQLERRM;
                -- 错误行存入错误表,不中断流程
                INSERT INTO json_parse_errors(source_rowid, error_msg) VALUES(rec_raw.rid, v_err_msg);
                DBMS_OUTPUT.PUT_LINE('解析失败行ROWID:'||rec_raw.rid||',错误信息:'||v_err_msg);
        END;
        COMMIT;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('成功加载总条数:'||v_success_cnt);
    DBMS_OUTPUT.PUT_LINE('解析失败总行数:'||(SELECT COUNT(*) FROM json_parse_errors));
END;
/

补充说明

如果是Oracle 12.1版本JSON解析容错性低导致的问题,可升级到12.2及以上版本,更高版本支持ON ERROR NULL这类容错参数,可跳过单个错误节点,不会导致整行解析失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 00:06:02