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

结合json_arrayagg、json_object与json_table查询返回首行结果异常

Oracle 12c/19c: JSON Aggregation Result Corrupted When Adding Scalar Subquery Columns

你碰到的这个问题确实是Oracle 12.2.0.1和19c版本里的一个优化器Bug——当你在查询里同时保留v_f_1000和v_f_2这两个标量子查询列时,优化器会错误地复用聚合后的JSON结果,导致json_data列返回了不属于当前分组的内容,甚至用NO_QUERY_TRANSFORMATION提示还触发了ORA-600,这完全是Oracle内部逻辑的问题。

问题重现SQL

SELECT (SELECT v_f FROM json_table(R_P.json_data, '$[*]' columns (r_p_i NUMBER path '$.r_p_i', v_f path '$.v_f')) WHERE r_p_i = 1000 ) AS "v_f_1000",
(SELECT v_f FROM json_table(R_P.json_data, '$[*]' columns (r_p_i NUMBER path '$.r_p_i', v_f path '$.v_f')) WHERE r_p_i = 2 ) AS "v_f_2",
R_P.json_data, R_P.r_c, R_P.r_r
FROM (SELECT json_arrayagg(json_object(KEY 'r_p_i' value r_p_i, KEY 'v_f' value v_f, KEY 'u_i' value u_i ABSENT ON NULL) ORDER BY NULL) json_data, r_c, r_r
FROM (SELECT '26658' AS r_c, '00' AS r_r, 1000 AS r_p_i, 8.5 AS v_f, 'MM' AS u_i FROM dual UNION ALL
SELECT '26917' AS r_c, '00' AS r_r, 2 AS r_p_i, 10 AS v_f, 'R71' AS u_i FROM dual )
GROUP BY r_c, r_r ) R_P;

实际返回结果

v_f_1000v_f_2json_datar_cr_r
8.5null[{"r_p_i":1000,"v_f":8.5,"u_i":"MM"}]2665800
8.5null[{"r_p_i":1000,"v_f":8.5,"u_i":"MM"}]2691700

预期返回结果

v_f_1000v_f_2json_datar_cr_r
8.5null[{"r_p_i":1000,"v_f":8.5,"u_i":"MM"}]2665800
null10[{"r_p_i":2,"v_f":10,"u_i":"R71"}]2691700

临时解决方案

针对这个Bug,你可以尝试以下几种绕过方法:

  1. 改用JSON_VALUE直接提取值
    把外层的标量子查询替换为JSON_VALUE函数,利用JSON路径直接定位取值,能绕过优化器的错误转换逻辑:

    SELECT JSON_VALUE(R_P.json_data, '$[*]?(@.r_p_i == 1000).v_f') AS "v_f_1000",
           JSON_VALUE(R_P.json_data, '$[*]?(@.r_p_i == 2).v_f') AS "v_f_2",
           R_P.json_data, R_P.r_c, R_P.r_r
    FROM (SELECT json_arrayagg(json_object(KEY 'r_p_i' value r_p_i, KEY 'v_f' value v_f, KEY 'u_i' value u_i ABSENT ON NULL) ORDER BY NULL) json_data, r_c, r_r
          FROM (SELECT '26658' AS r_c, '00' AS r_r, 1000 AS r_p_i, 8.5 AS v_f, 'MM' AS u_i FROM dual UNION ALL
                SELECT '26917' AS r_c, '00' AS r_r, 2 AS r_p_i, 10 AS v_f, 'R71' AS u_i FROM dual )
          GROUP BY r_c, r_r ) R_P;
    
  2. 添加唯一标识干扰优化器复用
    如果必须保留json_table的写法,可以在聚合的JSON对象中添加一个依赖分组列的冗余字段,确保每个分组的JSON结构唯一,避免优化器错误复用结果:

    SELECT (SELECT v_f FROM json_table(R_P.json_data, '$[*]' columns (r_p_i NUMBER path '$.r_p_i', v_f path '$.v_f')) WHERE r_p_i = 1000 ) AS "v_f_1000",
           (SELECT v_f FROM json_table(R_P.json_data, '$[*]' columns (r_p_i NUMBER path '$.r_p_i', v_f path '$.v_f')) WHERE r_p_i = 2 ) AS "v_f_2",
           R_P.json_data, R_P.r_c, R_P.r_r
    FROM (SELECT json_arrayagg(json_object(KEY 'r_p_i' value r_p_i, KEY 'v_f' value v_f, KEY 'u_i' value u_i ABSENT ON NULL, KEY 'dummy' value r_c) ORDER BY NULL) json_data, r_c, r_r
          FROM (SELECT '26658' AS r_c, '00' AS r_r, 1000 AS r_p_i, 8.5 AS v_f, 'MM' AS u_i FROM dual UNION ALL
                SELECT '26917' AS r_c, '00' AS r_r, 2 AS r_p_i, 10 AS v_f, 'R71' AS u_i FROM dual )
          GROUP BY r_c, r_r ) R_P;
    
  3. 升级Oracle版本
    这个Bug在Oracle 21c及后续版本中已经被修复,如果业务允许,升级到更高版本可以彻底解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:17:43