Oracle SQL: 将PL/SQL中的JSON解析为table或数组

Oracle SQL: Parse JSON in PL/SQL to table or array

我需要将 JSON 解析为 table 或数组。因为这对我来说是全新的,所以我使用 Google 寻求帮助,但有些东西对我不起作用:/

我的 JSON 看起来像:

{
  "statusCode": 200,
  "isValid": true,
  "errors": [],
  "result": {
    "optimizationData": [
      {
        "name": "out",
        "content": "ID_LIMIT;TIME_STAMP_FROM;DIRECTION;ID_MODEL_CONSTRAINT\n1;202109222200;G;2_7_1_G\n1;202109232200;G;2_3_1_G\n2;202109222200;G;2_3_1_G\n3;202109222200;G;3_3_1_P\n"
      },
      {
        "name": "unit_out",
        "content": "ID_LIMIT;CODE_UNIT;TIME_STAMP_FROM;TIME_STAMP_TO;VARIABLE;VALUE\n1;BEL 2-02;202109222200;202109232200;RelaxationPlus;10\n1;BEL 2-05;202109222200;202109232200;RelaxationPlus;10\n2;WLO 1-01;202109222200;202109232200;RelaxationMinus;10\n"
      }
    ]
  }
}

从上面 JSON 我想创建如下 table (或数组)(名称的预期数据示例:“unit_out”):

ID_LIMIT CODE_UNIT TIME_STAMP_FROM TIME_STAMP_TO VARIABLE VALUE
1 BEL 2-02 202109222200 202109232200 RelaxationPlus 10
1 BEL 2-05 202109222200 202109232200 RelaxationPlus 10
2 WLO 1-01 202109222200 202109232200 RelaxationMinus 10

到目前为止,我已经尝试编写一个函数到 return“内容”值,但我得到了 ORA-30625(不允许对 null self 参数进行方法分派)

CREATE OR REPLACE FUNCTION parse_json (json IN VARCHAR2)
  RETURN VARCHAR2 IS
  json_obj_in  JSON_OBJECT_T;
  json_arr     JSON_ARRAY_T;
  json_elem    JSON_ELEMENT_T;
  json_obj     JSON_OBJECT_T;
  name         varchar2(32000);
  content      varchar2(32000);

BEGIN
  json_obj_in := JSON_OBJECT_T.parse(json);

  json_arr := json_obj_in.get_Array('result');

  FOR i IN 0 .. json_arr.get_size - 1 --NVL(json_arr.FIRST, 1) .. NVL(json_arr.LAST, 0)
  LOOP
    json_obj := JSON_OBJECT_T(json_arr.get(i));

    name := json_obj.get_Object('optimizationData').get_string('name');
    content := json_obj.get_Object('optimizationData').get_string('content');

  END LOOP;

  RETURN json_obj_in.to_string;
END;

我不确定哪里出了问题,或者我对这项任务的处理方法是否正确。

有人能帮忙吗?

谢谢

我给你留下了一个在 Oracle 12c 中对我有用的例子:

INSERT INTO table(param_id, name, label, parameterIndex, notNull, parameterTypeName, default_value, lov_query)
      SELECT param_id, name, label, parameterIndex, notNull, parameterTypeName, default_value, lov_query FROM JSON_TABLE(l_json,
      '$.parameters[*]' COLUMNS (
        param_id PATH '$.id', name PATH '$.name', 
        label PATH '$.label', 
        parameterIndex PATH '$.parameterIndex', 
        notNull PATH '$.notNull', 
        parameterTypeName PATH '$.parameterType.parameterTypeName', 
        default_value PATH '$.parameterAttributes.attributeSelectedOption.attributeValue',
        lov_query PATH '$.parameterQuery'
        ) );

我不知道这是否被认为是一种好的做法,如果我错了,有人会纠正我。这对我有用。

从 Oracle 12 开始,您可以在 SQL 查询中进行所有解析。您的主要问题不是 JSON 而是您的数据是字符串形式的,您需要将这些数据拆分成行然后转换成值并将这些值与 headers:

相关联
SELECT p.*
FROM   (
  SELECT l.lineno,
         kv.key,
         kv.value
  FROM   table_name t
         CROSS APPLY JSON_TABLE(
           t.value,
           '$.result.optimizationData[*]?(@.name == "unit_out")'
           COLUMNS
             content CLOB PATH '$.content'
         ) j
         CROSS JOIN LATERAL (
           SELECT LEVEL AS lineno,
                  REGEXP_SUBSTR(j.content, '.+', 1, 1 ) AS header,
                  REGEXP_SUBSTR(j.content, '.+', 1, LEVEL ) AS line
           FROM   DUAL
           WHERE  LEVEL > 1
           CONNECT BY LEVEL <= REGEXP_COUNT(j.content, '.+')
         ) l
         CROSS JOIN LATERAL (
           SELECT CAST(REGEXP_SUBSTR(header, '[^;]+', 1, LEVEL) AS VARCHAR2(4000))
                    AS key,
                  CAST(REGEXP_SUBSTR(line, '[^;]+', 1, LEVEL) AS VARCHAR2(4000))
                    AS value
           FROM   DUAL
           CONNECT BY LEVEL <= REGEXP_COUNT(header, '[^;]+')
         ) kv
) pt
PIVOT (
  MAX(value)
  FOR key IN (
    'ID_LIMIT'        AS id_limit,
    'CODE_UNIT'       AS code_limit,
    'TIME_STAMP_FROM' AS time_stamp_from,
    'TIME_STAMP_TO'   AS time_stamp_to,
    'VARIABLE'        AS variable,
    'VALUE'           AS value
  )
) p

其中,对于示例数据:

CREATE TABLE table_name (value BLOB CHECK (value IS JSON));

INSERT INTO table_name (value) VALUES (
'{
  "statusCode": 200,
  "isValid": true,
  "errors": [],
  "result": {
    "optimizationData": [
      {
        "name": "out",
        "content": "ID_LIMIT;TIME_STAMP_FROM;DIRECTION;ID_MODEL_CONSTRAINT\n1;202109222200;G;2_7_1_G\n1;202109232200;G;2_3_1_G\n2;202109222200;G;2_3_1_G\n3;202109222200;G;3_3_1_P\n"
      },
      {
        "name": "unit_out",
        "content": "ID_LIMIT;CODE_UNIT;TIME_STAMP_FROM;TIME_STAMP_TO;VARIABLE;VALUE\n1;BEL 2-02;202109222200;202109232200;RelaxationPlus;10\n1;BEL 2-05;202109222200;202109232200;RelaxationPlus;10\n2;WLO 1-01;202109222200;202109232200;RelaxationMinus;10\n"
      }
    ]
  }
}'
);

输出:

LINENO ID_LIMIT CODE_LIMIT TIME_STAMP_FROM TIME_STAMP_TO VARIABLE VALUE
2 1 BEL 2-02 202109222200 202109232200 RelaxationPlus 10
3 1 BEL 2-05 202109222200 202109232200 RelaxationPlus 10
4 2 WLO 1-01 202109222200 202109232200 RelaxationMinus 10

db<>fiddle here