Oracle XMLTABLE() 函数使用指南

在 Oracle 数据库中,XMLTABLE() 是最核心且功能强大的 XML 查询函数之一。它通过 XQuery 表达式将 XML 文档中的节点投影为一个虚拟的关系型二维表(包含行与列),使得开发者可以像操作普通数据表一样,对 XML 格式的数据进行标准的 SELECT、WHERE 过滤、GROUP BY 分组以及与其它物理表进行 JOIN 关联查询。


语法

Oracle XMLTABLE() 函数的典型语法结构如下:

XMLTABLE(
    [ <XMLnamespaces_clause>, ]
    <XQuery_string>
    PASSING <xml_instance>
    [ COLUMNS <column_name> <datatype> [ PATH <string_literal> ] [ DEFAULT <default_expr> ], ... ]
) [ AS ] alias

参数说明

  • XMLnamespaces_clause(可选):使用 XMLNAMESPACES('http://...' AS "ns") 声明 XML 命名空间,便于在 XPath 中匹配带有前缀的命名空间节点。
  • XQuery_string:必需。一个 XQuery 表达式字符串(例如 '/root/item'),用于指定哪些 XML 节点被切分映射为关系表中的“每一行”。
  • PASSING xml_instance:必需。指定作为输入源的 XMLType 实例,可以是表中的 XML 字段、绑定变量或由 XMLPARSE() 等函数生成的表达式。
  • COLUMNS 子句:定义虚拟表的列名、SQL 数据类型以及每个列对应的相对 XPath 提取路径:
    • column_name:输出的列名。
    • datatype:输出列的 SQL 数据类型(如 NUMBER, VARCHAR2, DATE)。
    • PATH 'xpath':从当前行节点出发提取数据的相对 XPath 路径。如果省略 PATH,默认以 column_name 区分匹配对应标签。
    • DEFAULT expr:当该 XML 节点缺失时的默认值。

使用示例

示例 1:将 XML 文档解析为行与列

假设我们有一组包含员工列表的 XML 文本,使用 XMLTABLE 将其展开为结构化表格:

SELECT 
    t.emp_id,
    t.emp_name,
    t.department,
    t.salary
FROM XMLTABLE(
    '/employees/employee'
    PASSING XMLPARSE(DOCUMENT '
        <employees>
            <employee id="1001">
                <name>张三</name>
                <department>基础架构部</department>
                <salary>18000</salary>
            </employee>
            <employee id="1002">
                <name>李四</name>
                <department>数据平台部</department>
                <salary>22000</salary>
            </employee>
        </employees>
    ')
    COLUMNS
        emp_id     NUMBER       PATH '@id',
        emp_name   VARCHAR2(50) PATH 'name',
        department VARCHAR2(50) PATH 'department',
        salary     NUMBER       PATH 'salary'
) t;

输出结果:

EMP_ID  EMP_NAME  DEPARTMENT    SALARY
------  --------  ------------  ------
  1001  张三      基础架构部     18000
  1002  李四      数据平台部     22000

示例 2:与物理业务表进行横向关联 (CROSS JOIN)

当数据库表中存储了包含明细列表的 XML 字段时,可以通过 XMLTABLE 实现行展开并与主表字段联合查询:

SELECT 
    o.order_no,
    o.customer_name,
    item.item_sku,
    item.item_qty
FROM orders o,
XMLTABLE(
    '/order/items/item'
    PASSING XMLPARSE(DOCUMENT o.order_detail_xml)
    COLUMNS
        item_sku VARCHAR2(30) PATH 'sku',
        item_qty NUMBER       PATH 'qty'
) item
WHERE o.order_date >= DATE '2026-01-01';

常见注意事项

  1. XPath 区分大小写: XML 对大小写非常敏感,XPath 路径中的标签名称(例如 name 和 Name)必须与 XML 标签严格一致,否则该列将解析出 NULL。
  2. 文本转 XMLType: 如果传入的是普通字符串字面量或 CLOB 列,务必配合 XMLPARSE() 进行显式封装,确保语法树解析正常。

相关 XML 函数与工具