从CLOB创建Oracle XMLTYPE指定字符集

时间:2017-08-23 15:57:06

标签: oracle character-encoding

我正在尝试从CLOB列创建XMLTYPE并明确指定字符集。我发现有一个重载的XMLTYPE.createXML函数接受字符集,但是当我执行传递其他参数时,我得到一个错误。为什么呢?

const obs1 = this.http.get(`${API_URL}/transitions`);
const obs2 = this.http.get(`${API_URL}/states`);
Observable.merge(obs1, obs2).subscribe()

错误:

  

ORA-06553:PLS-306:调用的参数的数量或类型错误   'CREATEXML'

我打扰传递字符集的原因是,CLOB列包含使用与数据库字符集不同的字符集编码的字符(例如,它不支持#180)。

2 个答案:

答案 0 :(得分:1)

  

我打扰传递字符集的原因是,CLOB列包含使用与数据库字符集不同的字符集编码的字符(例如,它不支持#180)。

这个我不明白。 #180;是简单的纯ASCII,它适用于任何条件。

简单地运行

SELECT
    XMLTYPE.createXML(TO_CLOB('<node1><node2>the &#180; character</node2></node1>'))
from dual;

甚至更短

SELECT
    XMLTYPE('<node1><node2>the &#180; character</node2></node1>')
from dual;

现在,让我们假设您的XML包含数据库字符集不支持的字符,在这种情况下,您的XML可能是<node1><node2>the ´ character</node2></node1>

首先,您无法存储(或使用)CLOB(或VARCHAR2)中数据库字符集不支持的任何字符 - 从不!您必须使用基于国家数据库字符集NCLOB(或NVARCHAR2),并且通常支持任何Unicode字符。

您可以在XMLTYPE.createXML()中指定字符集,但是必须将XML作为BLOB提供。你可以这样做:

DECLARE
    xmlString NCLOB := '<node1><node2>the '||NCHR(180)||' character</node2></node1>';
    xmlDoc XMLTYPE;     
    xmlBinary BLOB;

    lang_context INTEGER := DBMS_LOB.DEFAULT_LANG_CTX;
    dest_offset INTEGER := 1;
    src_offset INTEGER := 1;
    read_offset INTEGER := 1;
    warning INTEGER;

BEGIN

    DBMS_LOB.CREATETEMPORARY(xmlBinary, TRUE);
    DBMS_LOB.CONVERTTOBLOB(xmlBinary, xmlString, DBMS_LOB.LOBMAXSIZE, dest_offset, src_offset, 2000, lang_context, warning);
    xmlDoc := XMLTYPE.createXML(xmlBinary, 2000, NULL, 1, 1);
END;

2000是您的国家数据库字符集的csid。使用

SELECT PARAMETER, VALUE, NLS_CHARSET_ID(VALUE) 
FROM NLS_DATABASE_PARAMETERS
WHERE PARAMETER LIKE '%CHARACTERSET';

获取您的身份证。

一些注意事项:

我尝试使用字符串N'<node1><node2>the ´ character</node2></node1>',但Oracle立即用´替换¿。我无法直接输入´

几乎所有XML Functions返回VARCAHR2值(不是NVARCAHR2),大多数XMLTYPE成员函数也与CLOB一起使用(不是NCLOB )。如果您只是将XML文档作为XMLTYPE读取并存储在数据库中,那么它应该没问题,但是一旦您使用这些数据开始任何操作,您迟早会遇到转换错误。您应该考虑迁移数据库字符集,请参阅Character Set Migration和/或Oracle Database Migration Assistant for Unicode

答案 1 :(得分:0)

您可以直接使用XMLType功能

SELECT XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>'
  ||TO_CLOB ('<node1><node2>the &#180; character</node2></node1>')) myxml
FROM dual;