当您需要将数据库中的数据以XML格式导出,用于数据交换或与外部系统集成时,可以使用DBMS_XMLGEN
内置包。该包能将任意SQL查询的结果直接转换为一个包含XML数据的CLOB对象,简化了数据格式转换的过程。
功能简介
DBMS_XMLGEN
内置包提供了一套函数和过程,用于将SQL查询结果生成为标准的XML文档。核心功能包括:
前提条件
支持的PolarDB PostgreSQL版(兼容Oracle)的版本如下:
Oracle语法兼容 2.0(内核小版本2.0.14.17.35.0及以上)
注意事项
在使用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;
,在列带有别名时,PolarDB与Oracle的行为一致。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; /
子程序总览
子程序 | 说明 |
| XML转义处理,输入参数为 |
| XML转义处理,输入参数为 |
| 根据指定的SQL获取XML文档。 |
| 根据指定的SQL创建新的上下文句柄。 |
| 根据上下文句柄获取XML文档,返回 |
| 根据上下文句柄获取XML文档,填充到已有的 |
| 关闭上下文资源。 |
使用说明
数据准备
下述说明中的示例代码将基于以下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、关闭上下文。
创建上下文:使用
newContext
函数,根据SQL查询创建一个上下文句柄。获取XML:将句柄传入
getXML
函数或过程来获取XML结果。关闭上下文:使用
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实体编码或解码,以处理特殊字符。
原始字符 | 转义后字符 |
|
|
|
|
|
|
|
|
|
|
函数
-- 输入参数为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_ENCODE
或0
(默认):对特殊字符进行编码。ENTITY_DECODE
或1
: 对特殊字符进行解码。
示例
-- 将特殊字符转义 (默认模式)
SELECT DBMS_XMLGEN.CONVERT('<>&"''') FROM dual;
-- 返回: <>&"'
-- 将已转义的字符串解码回原始字符
SELECT DBMS_XMLGEN.CONVERT('<>&"'', 1) FROM dual;
-- 返回: <>&"'