Oracle 19C中如何比较JSON_OBJECT_T?JSON_EQUAL报错解决
在Oracle 19C PL/SQL中比较JSON_OBJECT_T对象的方法
Oracle 19C并未内置JSON_EQUAL函数,这是你遇到PLS-00201错误的原因。以下是几种可行的实现方案,包含高效的内置函数用法和自定义比较逻辑:
一、高效方案:使用DBMS_JSON.COMPARE内置函数
Oracle 12.2及以上版本(含19C)提供了DBMS_JSON包,其中的COMPARE函数可用于比较JSON数据的内容相等性,会忽略JSON对象的键顺序,完全符合JSON规范的相等判定逻辑,且性能远高于自定义函数。
实现代码
CREATE OR REPLACE FUNCTION json_obj_equal(p_obj1 JSON_OBJECT_T, p_obj2 JSON_OBJECT_T) RETURN BOOLEAN IS BEGIN -- COMPARE返回0表示两个JSON内容完全相等 RETURN DBMS_JSON.COMPARE(p_obj1.to_clob(), p_obj2.to_clob()) = 0; EXCEPTION WHEN OTHERS THEN -- 出现异常时判定为不相等 RETURN FALSE; END; /
使用示例
DECLARE rec1 JSON_OBJECT_T := JSON_OBJECT_T('{"id":1,"name":"Alice"}'); api_rec JSON_OBJECT_T := JSON_OBJECT_T('{"name":"Alice","id":1}'); -- 键顺序不同 BEGIN IF json_obj_equal(rec1, api_rec) THEN DBMS_OUTPUT.PUT_LINE('两个JSON对象相等'); ELSE DBMS_OUTPUT.PUT_LINE('两个JSON对象不相等'); END IF; END; /
输出结果为两个JSON对象相等,符合预期。
二、自定义递归比较函数(处理复杂嵌套场景)
如果你的JSON对象包含嵌套的对象或数组,且需要更精细的控制逻辑,可以自定义递归函数遍历键值对进行比较:
1. 对象比较函数
CREATE OR REPLACE FUNCTION json_obj_equal(p_obj1 JSON_OBJECT_T, p_obj2 JSON_OBJECT_T) RETURN BOOLEAN IS l_keys1 JSON_KEY_LIST; BEGIN -- 先比较键的数量 IF p_obj1.get_size() != p_obj2.get_size() THEN RETURN FALSE; END IF; l_keys1 := p_obj1.get_keys(); -- 遍历每个键,逐一比较对应值 FOR i IN 1..l_keys1.COUNT LOOP -- 检查键是否存在于另一个对象 IF NOT p_obj2.has(l_keys1(i)) THEN RETURN FALSE; END IF; DECLARE l_val1 JSON_ELEMENT_T := p_obj1.get(l_keys1(i)); l_val2 JSON_ELEMENT_T := p_obj2.get(l_keys1(i)); BEGIN -- 嵌套对象递归比较 IF l_val1.is_object() AND l_val2.is_object() THEN IF NOT json_obj_equal(JSON_OBJECT_T(l_val1), JSON_OBJECT_T(l_val2)) THEN RETURN FALSE; END IF; -- 嵌套数组递归比较 ELSIF l_val1.is_array() AND l_val2.is_array() THEN IF NOT json_arr_equal(JSON_ARRAY_T(l_val1), JSON_ARRAY_T(l_val2)) THEN RETURN FALSE; END IF; -- 基础类型直接比较字符串形式 ELSIF l_val1.to_string() != l_val2.to_string() THEN RETURN FALSE; END IF; END; END LOOP; RETURN TRUE; EXCEPTION WHEN OTHERS THEN RETURN FALSE; END; /
2. 数组比较辅助函数
CREATE OR REPLACE FUNCTION json_arr_equal(p_arr1 JSON_ARRAY_T, p_arr2 JSON_ARRAY_T) RETURN BOOLEAN IS BEGIN -- 先比较数组长度 IF p_arr1.get_size() != p_arr2.get_size() THEN RETURN FALSE; END IF; -- 遍历数组元素逐一比较 FOR i IN 0..p_arr1.get_size()-1 LOOP DECLARE l_elem1 JSON_ELEMENT_T := p_arr1.get(i); l_elem2 JSON_ELEMENT_T := p_arr2.get(i); BEGIN IF l_elem1.is_object() AND l_elem2.is_object() THEN IF NOT json_obj_equal(JSON_OBJECT_T(l_elem1), JSON_OBJECT_T(l_elem2)) THEN RETURN FALSE; END IF; ELSIF l_elem1.is_array() AND l_elem2.is_array() THEN IF NOT json_arr_equal(JSON_ARRAY_T(l_elem1), JSON_ARRAY_T(l_elem2)) THEN RETURN FALSE; END IF; ELSIF l_elem1.to_string() != l_elem2.to_string() THEN RETURN FALSE; END IF; END; END LOOP; RETURN TRUE; EXCEPTION WHEN OTHERS THEN RETURN FALSE; END; /
三、方案选择建议
- 优先使用
DBMS_JSON.COMPARE:内置函数性能最优,且自动处理键顺序、嵌套结构等问题,适合绝大多数场景。 - 自定义函数仅用于特殊需求:比如需要忽略某些特定键、自定义值比较逻辑等场景。
- 避免直接比较字符串:除非能确保两个JSON对象的键顺序完全一致,否则字符串比较会误判键顺序不同但内容相同的JSON对象。
内容的提问来源于stack exchange,提问作者Nishan Karki
相关产品推荐
相关产品推荐

