如何使用US7ASCII将包含汉字和UTF-8编码的XML文件导入Oracle数据库

如何使用US7ASCII将包含汉字和UTF-8编码的XML文件导入Oracle数据库,xml,oracle,plsql,utf-8,ascii,Xml,Oracle,Plsql,Utf 8,Ascii,我一直在努力将包含中文字符并以UTF-8编码的XML文件从外部各方导入到我们的Oracle数据库,该数据库使用US7ASCII编码。但是,下面的错误会持续提示: pkg_dxe.get_xmldata: ORA-31011: XML parsing failed ORA-19202: Error occurred in XML processing LPX-00200: could not convert from encoding UTF-8 to US-ASCII Error at line

我一直在努力将包含中文字符并以UTF-8编码的XML文件从外部各方导入到我们的Oracle数据库,该数据库使用US7ASCII编码。但是,下面的错误会持续提示:

pkg_dxe.get_xmldata: ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00200: could not convert from encoding UTF-8 to US-ASCII
Error at line 1
处理导入过程的PL\SQL代码:

v_xml := XMLType(bfilename('XMLDIR_IBISAPP', 'xmldata.xml'), nls_charset_id('UTF8'));
Select count(*) into v_cnt from XML_TAB_A;
If v_cnt > 0 then    
    update XML_TAB_A set 
        xml_data = v_xml, 
        timestamp = sysdate;
else
    Insert into XML_TAB_A(xml_data, timestamp) values (v_xml, sysdate);
end if;
XML示例:

<?xml version="1.0" standalone="yes" ?> 
<APPLICATION>
  <DXE_APPLICATION>
    <APP_TRAN_NO>20180621031622817</APP_TRAN_NO> 
  </DXE_APPLICATION>
  <DXE_CUSTOMER>
    <APP_TRAN_NO>20180621031622817</APP_TRAN_NO> 
    <SEQ>0</SEQ>  
    <CUST_TITLE>Mr.</CUST_TITLE> 
    <CUST_NAME>HELLO</CUST_NAME> 
    <CUST_GNAME>HELLO</CUST_GNAME> 
    <CUST_ONAME>hello</CUST_ONAME> 
    <CUST_NAME_CHN>陳大文</CUST_NAME_CHN>
  </DXE_CUSTOMER>
</APPLICATION>
导致错误的字段是Cust_Name_Chn,但我们不能排除其他字段也会提供中文字符

当XML包含中文字符时,有没有办法在不提示错误的情况下将其正确导入Oracle数据库?如果在本阶段导入后无法读取汉字,则可以接受


我已尝试使用CONVERT函数,但错误LPX-00200仍然存在。

没有US7ASCII数据库可供测试,但您可以通过getblobval方法转换xmltypes的字符集

with x as
    (select xmltype('<?xml version="1.0" standalone="yes" ?> 
<APPLICATION>
  <DXE_APPLICATION>
    <APP_TRAN_NO>20180621031622817</APP_TRAN_NO> 
  </DXE_APPLICATION>
  <DXE_CUSTOMER>
    <APP_TRAN_NO>20180621031622817</APP_TRAN_NO> 
    <SEQ>0</SEQ>  
    <CUST_TITLE>Mr.</CUST_TITLE> 
    <CUST_NAME>HELLO</CUST_NAME> 
    <CUST_GNAME>HELLO</CUST_GNAME> 
    <CUST_ONAME>hello</CUST_ONAME> 
    <CUST_NAME_CHN>陳大文</CUST_NAME_CHN>
  </DXE_CUSTOMER>
</APPLICATION>') a from dual)
select xmltype(x.a.getblobval(NLS_CHARSET_ID('US7ASCII')),NLS_CHARSET_ID('US7ASCII')) y
from x x;
将名称行改为:

<CUST_NAME_CHN>&#x9673;&#x5927;&#x6587;</CUST_NAME_CHN>

您应该考虑将数据库迁移到UTF-8,请参阅。将数据库从US7ASCII迁移到AL32UTF8不会产生任何问题

说:

不支持NCHAR、NVARCHAR和NCLOB–Oracle XML DB不支持 支持在任何情况下使用SQL数据类型NCHAR、NVARCHAR2和NCLOB 其中:

在XML模式中使用SQLType注释将XML元素或属性映射到这些数据类型

使用SQL/XML函数XMLElement、XMLAttributes和XMLForest从这些数据类型生成XML数据

在SQL/XML函数XMLQuery和XMLTable中,使用XQuery函数ora:view deprecated、fn:doc和fn:collection on tables 包含具有这些数据类型的列的

处理、存储或生成包含多字节的XML数据 字符,Oracle强烈建议您使用AL32UTF8作为 数据库字符集

可以将普通数据存储为NCLOB:


但是,您不能使用任何函数。

我找到了一种解决方案,可以将XML文件读入Clob,然后将其转换回XMLType,以避免提示编码错误

file := bfilename('XMLDIR_IBISAPP', 'xmldata.xml');
dbms_lob.createTemporary(contents, true, dbms_lob.session);
dbms_lob.fileopen(file, dbms_lob.file_readonly);
dbms_lob.loadClobfromFile(contents, file, dbms_lob.getLength(file), dest_offset, src_offset, nls_charset_id('AL32UTF8'), lang_context, conv_warning);
dbms_lob.fileclose(file);

v_xml := XMLTYPE.createXML(contents);

Update xml_tab_a set 
        xml_data = v_xml, 
        timestamp = sysdate;

谢谢如何在代码中实现getblobval方法?因为我直接从目录文件读取XML数据,代码如下:v_XML:=XMLTypebfilename'XMLDIR_IBISAPP',xmldata.XML',nls_charset_id'UTF8';我认为这行不通,因为GETBLOBVAL是XMLTYPE的成员函数。在给定的条件下,不可能创建可以应用GetBlobVal的XMLTYPE实例。您应该使用nls_charset_id'AL32UTF8'。Oracle字符集UTF8为。对于中文字符,这可能是相关的,因为你可能会使用字符以外的感谢很多。我发现了一个与您非常相似的解决方案,但要将XML文件读入Clob,然后使用函数将其转换回XMLTYPE,然后将汉字转换为???不提示错误,这将转换陳大文 到这是你的意图吗?是的。在这一阶段,只要避免了错误就可以了。将数据库转换为使用Unicode是不可能的,因为我们有一些依赖于当前环境运行的子系统。由于我们目前只有1个包含中文字符的数据字段,这似乎是临时解决方案。是否有任何可能的方法可以读取US7ASCII数据库中的汉字?谢谢。数据库有两个字符集。NLS_字符集(在您的案例中为US7ASCII)和NLS_NCHAR_字符集(通常支持所有Unicode字符)。NLS_字符集用于CLOB、VARCHAR2和XMLTYPE,在这里您不能描述任何汉字!但是,您可以使用NCLOB、NVARCHAR2,它使用NLS\u NCHAR\u CHARACTERSET并能够处理任何角色。这就是我作为答案提供的解决方案。谢谢,我从来没有想过。我将尝试用这种方法编辑我的代码。非常感谢你的帮助。
file := bfilename('XMLDIR_IBISAPP', 'xmldata.xml');
dbms_lob.createTemporary(contents, true, dbms_lob.session);
dbms_lob.fileopen(file, dbms_lob.file_readonly);
dbms_lob.loadClobfromFile(contents, file, dbms_lob.getLength(file), dest_offset, src_offset, nls_charset_id('AL32UTF8'), lang_context, conv_warning);
dbms_lob.fileclose(file);

v_xml := XMLTYPE.createXML(contents);

Update xml_tab_a set 
        xml_data = v_xml, 
        timestamp = sysdate;