在以后的 Oracle 版本中,您可以在 SELECT 语句的子查询分解 (WITH) 子句中包含函数。然后,您可以使用this answer:
WITH FUNCTION get_key(
pos IN PLS_INTEGER,
json IN CLOB
) RETURN VARCHAR2
AS
doc_keys JSON_KEY_LIST;
BEGIN
doc_keys := JSON_OBJECT_T.PARSE ( json ).GET_KEYS;
RETURN doc_keys( pos );
END get_key;
SELECT get_key( j.pos, t.value ) AS key,
j.value
FROM table_name t
CROSS APPLY JSON_TABLE(
t.value,
'$.*'
COLUMNS (
pos FOR ORDINALITY,
value PATH '$'
)
) j;
其中,对于样本数据:
CREATE TABLE table_name ( value VARCHAR2(4000) CHECK (value IS JSON) );
INSERT INTO table_name (value) VALUES ('{a:100, b:200, c:300}');
输出:
| KEY |
VALUE |
| a |
100 |
| b |
200 |
| c |
300 |
仅限内置函数,例如json_table,json_dataguide
您将与这些限制作斗争:
-
JSON_QUERY 只允许路径的文字值;您不能传递动态路径值。
-
JSON_TABLE 确实允许在 COLUMNS 子句中使用动态路径,但不会为这些动态路径返回值。
例如:
SELECT t.value AS json,
SUBSTR(p.path, 3) AS key,
JSON_QUERY(t.value, p.path) AS value
FROM table_name t
CROSS JOIN LATERAL(
SELECT JSON_DATAGUIDE(t.value) AS data
FROM DUAL
) d
CROSS JOIN LATERAL(
SELECT path
FROM JSON_TABLE(
d.data,
'$[*]'
COLUMNS(
path VARCHAR2(20) PATH '$."o:path"'
)
)
) p;
输出:
ORA-40454: path expression not a literal
和:
SELECT t.value AS json,
SUBSTR(p.path, 3) AS key,
v.val AS value
FROM table_name t
CROSS JOIN LATERAL(
SELECT JSON_DATAGUIDE(t.value) AS data
FROM DUAL
) d
CROSS JOIN LATERAL(
SELECT path
FROM JSON_TABLE(
d.data,
'$[*]'
COLUMNS(
path VARCHAR2(20) PATH '$."o:path"'
)
)
) p
CROSS JOIN LATERAL(
SELECT val
FROM JSON_TABLE(
t.value,
'$'
COLUMNS(
val VARCHAR2(20) PATH p.path
)
)
) v;
输出:
| JSON |
KEY |
VALUE |
| {"a":100, "b":200, "c":300} |
a |
<null> |
| {"a":100, "b":200, "c":300} |
b |
<null> |
| {"a":100, "b":200, "c":300} |
c |
<null> |
虽然查询有效,但它不会动态获取值。 (注意:如果您使用文字路径而不是动态路径,则该查询将起作用。)
db小提琴here