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
我需要将 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