Oracle JSON 与 XML 处理

Oracle JSON 与 XML 处理

适用版本:Oracle Database 12c / 18c / 19c / 21c / 23ai 文档版本:v1.0 / 2026-07


1. 概述

Oracle 12c+ 原生支持 JSON[1],XMLType 支持 XML[2]:


2. JSON 存储

2.1 12c(CLOB/VARCHAR2)

CREATE TABLE docs (
  id NUMBER PRIMARY KEY,
  data CLOB CHECK (data IS JSON)
);

INSERT INTO docs VALUES (
  1, 
  '{"name":"Alice","age":30,"city":"NYC"}'
);

2.2 21c+(原生 JSON 类型)

CREATE TABLE docs (
  id NUMBER PRIMARY KEY,
  data JSON
);

INSERT INTO docs VALUES (
  1, 
  '{"name":"Alice","age":30,"city":"NYC"}'
);

3. JSON 查询

3.1 简单点操作

-- 12c+
SELECT data.name FROM docs;
SELECT data.age FROM docs WHERE id = 1;

-- 路径
SELECT data.address.city FROM docs;

3.2 JSON_VALUE

SELECT JSON_VALUE(data, '$.name') AS name FROM docs;
SELECT JSON_VALUE(data, '$.age') AS age FROM docs;
SELECT JSON_VALUE(data, '$.address.city') AS city FROM docs;

3.3 JSON_QUERY

-- 返回 JSON 对象
SELECT JSON_QUERY(data, '$.address') FROM docs;

-- 数组
SELECT JSON_QUERY(data, '$.hobbies') FROM docs;
SELECT JSON_QUERY(data, '$.hobbies[0]') FROM docs;
SELECT JSON_QUERY(data, '$.hobbies[*]') FROM docs;

3.4 JSON_EXISTS

SELECT * FROM docs WHERE JSON_EXISTS(data, '$.name');
SELECT * FROM docs WHERE JSON_EXISTS(data, '$.age ? (@ > 25)');

4. JSON 生成

4.1 JSON_OBJECT

SELECT JSON_OBJECT(
  'id' VALUE employee_id,
  'name' VALUE last_name,
  'salary' VALUE salary
) AS emp_json
FROM employees;

4.2 JSON_ARRAY

SELECT JSON_ARRAY(
  'Alice', 'Bob', 'Charlie'
) FROM dual;

-- 表数据
SELECT JSON_ARRAYAGG(last_name) FROM employees WHERE dept_id = 10;
-- ["Alice","Bob","Charlie"]

4.3 JSON_OBJECTAGG

SELECT JSON_OBJECTAGG(key VALUE value) FROM ...

5. JSON 索引

5.1 内存索引

CREATE SEARCH INDEX idx_docs_json ON docs (data) FOR JSON;

5.2 函数索引

CREATE INDEX idx_docs_name ON docs (JSON_VALUE(data, '$.name'));

6. JSON 表

6.1 JSON_RELATIONAL(21c+)

-- JSON 数据当关系表查询
SELECT name, age FROM docs;

6.2 JSON_TABLE

SELECT jt.name, jt.age, jt.city
FROM docs, JSON_TABLE(data, '$' COLUMNS (
  name VARCHAR2(100) PATH '$.name',
  age NUMBER PATH '$.age',
  city VARCHAR2(50) PATH '$.city'
)) jt;

7. XML 处理

7.1 XMLType 存储

CREATE TABLE xml_docs (
  id NUMBER PRIMARY KEY,
  content XMLTYPE
);

INSERT INTO xml_docs VALUES (
  1, 
  XMLTYPE('<employee><name>Alice</name><age>30</age></employee>')
);

7.2 查询 XML

-- EXTRACT
SELECT EXTRACT(content, '/employee/name/text()').getStringVal()
FROM xml_docs;

-- XMLQuery
SELECT XMLQuery('/employee/name/text()' PASSING content RETURNING CONTENT)
FROM xml_docs;

-- XMLTable
SELECT xt.name, xt.age
FROM xml_docs, XMLTABLE('/employee' PASSING content COLUMNS (
  name VARCHAR2(100) PATH 'name',
  age NUMBER PATH 'age'
)) xt;

7.3 生成 XML

-- XMLELEMENT
SELECT XMLELEMENT("employee", 
  XMLFOREST(last_name AS name, salary AS sal)
) FROM employees;

-- XMLAGG
SELECT XMLAGG(XMLELEMENT("name", last_name) ORDER BY last_name)
FROM employees WHERE dept_id = 10;

8. 性能优化

8.1 JSON 索引

-- 搜索索引
CREATE SEARCH INDEX idx_json ON docs(data) FOR JSON;

-- 函数索引
CREATE INDEX idx_json_name ON docs(JSON_VALUE(data, '$.name'));

8.2 JSON_TABLE 替代多次查询

-- 一次解析
SELECT jt.name, jt.age, jt.city
FROM docs, JSON_TABLE(data, '$' COLUMNS (...)) jt;

9. 常见坑与排错

9.1 ORA-40441: JSON 语法错误

-- 检查 JSON 格式
-- 使用 JSON_VALID 验证(21c+)
SELECT JSON_VALID('{"name":"Alice"}') FROM dual;

9.2 性能差

-- 1. 加搜索索引
-- 2. 使用函数索引
-- 3. JSON_TABLE 批量解析

9.3 嵌套深

-- 路径表达式
$.address.city
$.hobbies[0]
$.friends[*].name

10. 最佳实践

  1. 21c+ 用 JSON 类型:原生
  2. 12c 用 CLOB + IS JSON:兼容
  3. 搜索索引提升:性能
  4. JSON_TABLE 批量解析:效率
  5. JSON_OBJECT 生成:标准
  6. JSON_VALUE 简单值:明确
  7. JSON_EXISTS 存在判断:高效
  8. XML 用 XMLType:原生
  9. XMLTable 关系化:查询
  10. 测试复杂 JSON:验证

11. 参考资料

[1] Oracle Database JSON Developer’s Guide 19c https://docs.oracle.com/en/database/oracle/oracle-database/19/adjsn/

[2] Oracle Database XML DB Developer’s Guide 19c https://docs.oracle.com/en/database/oracle/oracle-database/19/adxdb/