DBMS_XMLGEN

当您需要将数据库中的数据以XML格式导出,用于数据交换或与外部系统集成时,可以使用DBMS_XMLGEN内置包。该包能将任意SQL查询的结果直接转换为一个包含XML数据的CLOB对象,简化了数据格式转换的过程。

功能简介

DBMS_XMLGEN内置包提供了一套函数和过程,用于将SQL查询结果生成为标准的XML文档。核心功能包括:

  • 直接转换:通过getXML函数,一行代码即可将一条SQL查询语句的结果转换为XML格式。

  • 上下文分步转换:您也可以先通过newContext创建一个查询上下文,然后使用getXML基于此上下文生成XML,最后通过closeContext释放资源。这种方式在处理复杂或分步逻辑时更加灵活。

  • 特殊字符转义:提供convert函数,用于处理XML中的特殊字符(如 <>&),确保生成的XML文档格式正确。

前提条件

支持的PolarDB PostgreSQL版(兼容Oracle)的版本如下:

  • Oracle语法兼容 2.0(内核小版本2.0.14.17.35.0及以上)

说明

您可在控制台查看内核小版本号,也可以通过SHOW polardb_version;语句查看。如未满足内核小版本要求,请升级内核小版本

注意事项

在使用DBMS_XMLGEN时,PolarDB PostgreSQL版(兼容Oracle)Oracle存在少量不兼容点:

  • 列名大小写:在PolarDB中,未用双引号引用的列名默认为小写,而Oracle默认为大写。这会导致getXML生成的XML标签名大小写不同。

    • 若下游系统不区分大小写,或能适配小写标签,则无需任何操作。

    • 若下游系统要求使用大写标签(如 /ROWSET/ROW/COLUMN_NAME),您可以在控制台将参数polar_dbms_xmlgen_upper_column_type_name的值设置为ON即可。

  • 列别名:如果getXML函数执行的查询是函数调用或者常量等场景,比如SELECT DBMS_XmlGen.getXML('SELECT my_function(1) FROM dual') FROM dual;

    • Oracle:返回的XML中列名为Unicode形式的MY_FUNCTION_x0028_1_x0029_

    • PolarDB:返回的XML中列名为my_function

    这种情况建议对函数调用增加别名来解决SELECT DBMS_XmlGen.getXML('SELECT my_function(1) AS column_name FROM dual') FROM dual;,在列带有别名时,PolarDBOracle的行为一致。

  • no_data_found异常场景:对于如下的函数,其中的SQL语句执行结果为0行,函数直接返回NULL,与Oracle兼容。但如果在getXML函数中调用这种函数SELECT DBMS_XmlGen.getXML('SELECT func_return_null FROM dual') FROM dual;,则结果可能与Oracle不兼容,不建议在该场景使用。

    CREATE OR REPLACE FUNCTION func_return_null RETURN int AS
        result int := 1;
    BEGIN
        -- 永远返回 0 行,触发 no_data_found 异常,直接返回 NULL
        SELECT 1 INTO result FROM dual WHERE 1 = 0;
        RETURN result;
    END;
    /

子程序总览

子程序

说明

convert(xmlData CLOB, flag)

XML转义处理,输入参数为CLOB类型。

convert(xmlData VARCHAR2, flag)

XML转义处理,输入参数为VARCHAR2类型

getXML(sqlQuery, dtdOrSchema)

根据指定的SQL获取XML文档。

newContext

根据指定的SQL创建新的上下文句柄。

getXML(ctx, dtdOrSchema)

根据上下文句柄获取XML文档,返回CLOB对象。

getXML(ctx, tmpclob, dtdOrSchema)

根据上下文句柄获取XML文档,填充到已有的CLOB变量tmpclob中。

closeContext

关闭上下文资源。

使用说明

数据准备

下述说明中的示例代码将基于以下employees表结构和数据。您可以在您的集群中执行以下SQL语句来创建并填充该表,以便进行测试。

-- 创建员工表
CREATE TABLE employees (
    "EMP_id" NUMBER,
    name VARCHAR2(50),
    dept VARCHAR2(30),
    "SALARY" NUMBER
);

-- 插入测试数据
INSERT INTO employees VALUES (1, '张三', '技术部', 15000);
INSERT INTO employees VALUES (2, '李四', '财务部', 12000);
INSERT INTO employees VALUES (3, '王五', '技术部', 18000);

直接从SQL查询生成XML

使用getXML函数直接将查询语句转换为XML。

函数

DBMS_XMLGEN.GETXML (
    sqlQuery     IN VARCHAR2,
    dtdOrSchema  IN number := NONE)
RETURN CLOB;

参数说明

  • sqlQuery:指定的SQL语句。

  • dtdOrSchema:暂不支持设置。

示例

SELECT DBMS_XmlGen.getXML('SELECT * FROM employees') FROM dual;

返回结果如下:

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <EMP_id>1</EMP_id>
  <name>张三</name>
  <dept>技术部</dept>
  <SALARY>15000</SALARY>
 </ROW>
 <ROW>
  <EMP_id>2</EMP_id>
  <name>李四</name>
  <dept>财务部</dept>
  <SALARY>12000</SALARY>
 </ROW>
 <ROW>
  <EMP_id>3</EMP_id>
  <name>王五</name>
  <dept>技术部</dept>
  <SALARY>18000</SALARY>
 </ROW>
</ROWSET>

基于上下文句柄生成XML

对于更复杂的逻辑,您可以分步操作:创建上下文、生成XML、关闭上下文。

  1. 创建上下文:使用newContext函数,根据SQL查询创建一个上下文句柄。

  2. 获取XML:将句柄传入getXML函数或过程来获取XML结果。

  3. 关闭上下文:使用closeContext函数释放句柄和相关资源。

函数

-- 创建上下文句柄
DBMS_XMLGEN.NEWCONTEXT (
    query     IN VARCHAR2)
RETURN ctxHandle;

-- 从句柄获取XML (返回CLOB)
DBMS_XMLGEN.GETXML (
    ctx          IN ctxHandle,
    dtdOrSchema  IN number := NONE)
RETURN CLOB;

-- 从句柄获取XML (填充到已有的CLOB变量)
DBMS_XMLGEN.GETXML (
    ctx          IN ctxHandle,
    tmpclob      IN OUT NCOPY CLOB,
    dtdOrSchema  IN number := NONE);

-- 关闭上下文
DBMS_XMLGEN.CLOSECONTEXT (
    ctx  IN ctxHandle);

示例

DECLARE
    xml_result CLOB;
    handle DBMS_XMLGEN.ctxHandle;
BEGIN
    handle := DBMS_XMLGEN.NEWCONTEXT('SELECT * FROM employees');
    DBMS_OUTPUT.PUT_LINE(handle);
    xml_result := DBMS_XMLGEN.GETXML(handle);
    DBMS_OUTPUT.PUT_LINE(xml_result);
END;
/

DECLARE
    xml_result CLOB := '<dummy></dummy>';
    handle DBMS_XMLGEN.ctxHandle;
BEGIN
    handle := DBMS_XMLGEN.NEWCONTEXT('SELECT * FROM employees');
    DBMS_OUTPUT.PUT_LINE(handle);
    DBMS_XMLGEN.GETXML(handle, xml_result);
    DBMS_OUTPUT.PUT_LINE(xml_result);
END;
/

XML特殊字符进行转义

使用convert函数可以对字符串进行XML实体编码或解码,以处理特殊字符。

原始字符

转义后字符

&

&amp;

<

&lt;

>

&gt;

"

&quot;

'

&apos;

函数

-- 输入参数为VARCHAR2类型
DBMS_XMLGEN.CONVERT (
    xmlData IN VARCHAR2,
    flag    IN NUMBER := ENTITY_ENCODE)
RETURN VARCHAR2;

-- 输入参数为CLOB类型
DBMS_XMLGEN.CONVERT (
    xmlData IN CLOB,
    flag    IN NUMBER := ENTITY_ENCODE)
RETURN CLOB;

参数说明

  • xmlData:需要处理的字符串。

  • flag:转换模式。

    • ENTITY_ENCODE0(默认):对特殊字符进行编码。

    • ENTITY_DECODE1: 对特殊字符进行解码。

示例

-- 将特殊字符转义 (默认模式)
SELECT DBMS_XMLGEN.CONVERT('<>&"''') FROM dual;
-- 返回: &lt;&gt;&amp;&quot;&apos;

-- 将已转义的字符串解码回原始字符
SELECT DBMS_XMLGEN.CONVERT('&lt;&gt;&amp;&quot;&apos;', 1) FROM dual;
-- 返回: <>&"'