Oracle 12c基于表数据生成指定结构JSON的技术求助
Oracle 12c生成指定格式JSON的解决方案
环境与基础数据
使用Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit,已创建temp_Table表并插入数据:
CREATE TABLE temp_Table ( "OVRPK_CNTNR_ID" CHAR(20) NOT NULL ENABLE, "ITEM_DISTB_Q" NUMBER(3) NOT NULL ENABLE, "SSP_Q" NUMBER(6,0) NOT NULL ENABLE, "BRKPK_CNTNR_ID" CHAR(20) ); INSERT INTO temp_Table (OVRPK_CNTNR_ID, ITEM_DISTB_Q, SSP_Q, BRKPK_CNTNR_ID ) VALUES('92000000356873110552', 6,8,'93058901021076000085'); INSERT INTO temp_Table (OVRPK_CNTNR_ID,ITEM_DISTB_Q,SSP_Q, BRKPK_CNTNR_ID ) VALUES('92000000356873110552',8, 10,'93058901021117700080'); INSERT INTO temp_Table (OVRPK_CNTNR_ID,ITEM_DISTB_Q,SSP_Q, BRKPK_CNTNR_ID ) VALUES('92000000356873110552', 10,2,'93058901022276900083'); INSERT INTO temp_Table (OVRPK_CNTNR_ID,ITEM_DISTB_Q,SSP_Q, BRKPK_CNTNR_ID ) VALUES('92000000334160826089', 3,4,'000000000083465239'); INSERT INTO temp_Table (OVRPK_CNTNR_ID,ITEM_DISTB_Q,SSP_Q, BRKPK_CNTNR_ID ) VALUES('92000000334160826089', 3,4,'000000000083438160');
原实现的问题
原编写的触发器和createJson函数存在语法错误,且未正确匹配期望的JSON结构:
-- 原触发器 AFTER INSERT OR DELETE OR UPDATE OF OVRPK_CNTNR_ID, ITEM_DISTB_Q, SSP_Q, BRKPK_CNTNR_ID ON temp_Table FOR EACH ROW DECLARE json_message CLOB := ''; BEGIN /* * pick OVRPK_CNTNR_ID from triggers row and send it to function createJson() return json object, example : 92000000356873110552 */ json_message = CALL FUNCTION createJson(:NEW.OVRPK_CNTNR_ID); END; -- 原createJson函数 CREATE OR REPLACE FUNCTION createJson(ovrpk_container_id IN char) BEGIN SELECT json_query( json_objectagg(OVRPK_CNTNR_ID value json_array( json_object("break_pack_container_id" VALUE BRKPK_CNTNR_ID, "ssp_quantity" VALUE SSP_Q, "item_distribution_quantity" VALUE ITEM_DISTB_Q)))), '$' returning VARCHAR2(4000) pretty ) AS "Result JSON" FROM temp_Table END;
期望的JSON输出格式
{ "Over_pack_container_id":"92000000356873110552", "type": "OVER_PACK", "sub_containers": [ { "break_pack_container_id": "93058901021076000085", "ssp_quantity": 8, "item_distribution_quantity": 6 }, { "break_pack_container_id": "93058901021117700080", "ssp_quantity": 10, "item_distribution_quantity": 8 }, { "break_pack_container_id": "93058901022276900083", "ssp_quantity": 2, "item_distribution_quantity": 10 } ] }
修正后的可行实现
Oracle 12.1.0.2支持JSON_OBJECT、JSON_ARRAYAGG等JSON构造函数,以下是修正后的代码:
1. 修正后的createJson函数
CREATE OR REPLACE FUNCTION createJson(p_ovrpk_container_id IN CHAR) RETURN CLOB IS v_json CLOB; BEGIN SELECT JSON_OBJECT( 'Over_pack_container_id' VALUE t."OVRPK_CNTNR_ID", 'type' VALUE 'OVER_PACK', 'sub_containers' VALUE JSON_ARRAYAGG( JSON_OBJECT( 'break_pack_container_id' VALUE t."BRKPK_CNTNR_ID", 'ssp_quantity' VALUE t."SSP_Q", 'item_distribution_quantity' VALUE t."ITEM_DISTB_Q" ) ) FORMAT JSON ) INTO v_json FROM temp_Table t WHERE t."OVRPK_CNTNR_ID" = p_ovrpk_container_id GROUP BY t."OVRPK_CNTNR_ID"; RETURN v_json; END; /
说明:
- 用
JSON_OBJECT构造外层对象,严格匹配预期的键名 - 通过
JSON_ARRAYAGG聚合同一容器ID下的子数据,生成数组结构 - 指定返回类型为
CLOB,避免VARCHAR2的长度限制 - 增加
GROUP BY确保按容器ID聚合数据
2. 修正后的触发器
CREATE OR REPLACE TRIGGER temp_table_after_change AFTER INSERT OR DELETE OR UPDATE OF OVRPK_CNTNR_ID, ITEM_DISTB_Q, SSP_Q, BRKPK_CNTNR_ID ON temp_Table FOR EACH ROW DECLARE json_message CLOB := ''; BEGIN -- 插入/更新时取新值,删除时取旧值 IF INSERTING OR UPDATING THEN json_message := createJson(:NEW."OVRPK_CNTNR_ID"); ELSE json_message := createJson(:OLD."OVRPK_CNTNR_ID"); END IF; -- 此处可替换为实际业务逻辑,比如输出日志、调用外部接口等 DBMS_OUTPUT.PUT_LINE(json_message); END; /
说明:
- 补全触发器名称,符合Oracle语法规范
- 修正函数调用方式,直接赋值而非错误的
CALL FUNCTION语法 - 处理删除场景,使用
:OLD获取被删除的容器ID - 添加
DBMS_OUTPUT示例,方便验证结果
验证结果
触发触发器操作后,将生成与预期格式完全一致的JSON内容。例如,对92000000356873110552相关数据进行增删改时,输出的JSON结构完全匹配需求。
内容的提问来源于stack exchange,提问作者Madu Biradar
相关产品推荐
相关产品推荐

