【问题标题】:Create Oracle XMLTYPE from CLOB specifying character set从指定字符集的 CLOB 创建 Oracle XMLTYPE
【发布时间】:2018-02-01 07:43:21
【问题描述】:

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

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

错误:

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

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

【问题讨论】:

  • 我正在查看此处的文档:docs.oracle.com/database/121/ARPLS/t_xml.htm#ARPLS71959,但我没有看到您提到的选项。你在哪里找到超载的?您确定它是针对 Oracle 的(而不是针对 Java 或其他谁知道的)?
  • 您的 CLOB 是纯 ASCII - 为什么需要指定任何字符集?
  • 查找 csid IN 编号参数,请参阅 docs.oracle.com/database/121/ARPLS/t_xml.htm#ARPLS71959。 ... 只是一个例子。 createXML 将使用包含无法使用数据库 NLS_CHARACTERSET 字符集解码的特殊字符的列执行。
  • 那么您必须提供BLOB 而不是CLOB。查看DBMS_LOB.CONVERTTOBLOB 将给定的 CLOB 转换为 BLOB。

标签: oracle character-encoding


【解决方案1】:

可以直接使用XMLType函数

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

【讨论】:

    【解决方案2】:

    我之所以费心传递字符集的原因是,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 可能是 &lt;node1&gt;&lt;node2&gt;the ´ character&lt;/node2&gt;&lt;/node1&gt;

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

    您可以在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';
    

    获取您的 ID。

    一些注意事项:

    我尝试使用字符串 N'&lt;node1&gt;&lt;node2&gt;the ´ character&lt;/node2&gt;&lt;/node1&gt;',但 Oracle 立即将 ´ 替换为 ¿。我没有设法直接输入´

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-01
      • 1970-01-01
      • 2020-11-10
      • 2015-03-01
      • 2020-11-23
      • 2012-04-25
      • 1970-01-01
      • 2019-12-07
      相关资源
      最近更新 更多