【问题标题】:Oracle Stored Proc inserting encoded dataOracle Stored Proc 插入编码数据
【发布时间】:2015-07-05 22:13:05
【问题描述】:

我正在研究为什么我们会在数据库中获取一些编码数据。

我发现我们正在使用的网格正在向传递给存储过程的 xml 数据添加一些 HTML 编码。

但是,我已经关闭了数据表中的 html 编码,并确认我们正在向数据库发送未编码的数据。但是,插入/更新数据的存储过程似乎仍在对单引号进行编码。

我在存储过程中没有看到任何说明它可以对数据进行编码的内容。是否有可能导致此问题的设置或其他可以与 xml 一起发送的内容。

CREATE OR REPLACE PROCEDURE spSample (ncoXml IN XMLTYPE)
IS

xml 使用 utf-8 编码发送。我猜这就是问题所在。

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

感谢您提供的任何帮助或建议。

【问题讨论】:

    标签: xml oracle stored-procedures utf-8 oracle11g


    【解决方案1】:

    您的过程参数是 XMLtype,它自动编码来自 predefined XML entities list 的单引号和双引号

    SQL> select xmltype('<test>6''4"</test>') from dual;
    
    XMLTYPE('<TEST>6''4"</TEST>')
    --------------------------------------------------------------------------------
    <test>6&apos;4&quot;</test>
    

    这与 HTML 无关;其他非 XML HTML entities 未编码。你看到的是正确的;实体应该在您的 XMLType 对象中进行编码。

    如果您想查看已解码的实体,可以使用已弃用的 extractvalue 函数:

    SQL> select extractvalue(xmltype('<test>6''4"</test>'), '/test') from dual;
    
    EXTRACTVALUE(XMLTYPE('<TEST>6''4"</TEST>'),'/TEST')
    --------------------------------------------------------------------------------
    6'4"
    

    或一个 XMLQuery,使用 XMLCast 进行解码,作为转换为纯字符串的一部分:

    SQL> select xmlcast(xmlquery('/test/text()' passing xmltype('<test>6''4"</test>')
      2  returning content) as varchar2(10)) from dual;
    
    XMLCAST(XM
    ----------
    6'4"
    

    根据您在程序中使用数据的方式,您可以使用extract() 将表单更改为xmlcast(xmlquery(...) as ...)。你不能在 PL/SQL 中本地调用它(据我所知),所以你需要一个上下文切换来从 dual 中进行选择;而且它似乎也不喜欢在命令中连接索引值 - 不太清楚为什么,但我不得不使用一个变量来保存构造的 XPath。

    作为一个例子,如果你有类似的东西 - 在你的真实案例中将值传递给你的过程 - 你仍然有编码的值:

    DECLARE
      ncoXml XMLType := XMLType(q'[<victims><victim index="1"><name>Peter O'Toole</name></victim></victims>]');
      victimIndex pls_integer := 1;
      victimName varchar2(200);
    BEGIN
      victimName := SUBSTR(ncoXml.EXTRACT('/victims/victim[@index="'
        || TO_CHAR(victimIndex) || '"]/name/text()').GETSTRINGVAL(), 1, 200);
      dbms_output.put_line(victimName);
    END;
    /
    
    Peter O&apos;Toole
    

    XMLCast 变体可能如下所示:

    DECLARE
      ncoXml XMLType := XMLType(q'[<victims><victim index="1"><name>Peter O'Toole</name></victim></victims>]');
      victimIndex pls_integer := 1;
      victimName varchar2(200);
      xPath varchar2(200);
    BEGIN
      xPath := '/victims/victim[@index="' || victimIndex || '"]/name/text()';
      select xmlcast(xmlquery(xPath passing ncoXml returning content) as varchar2(200))
      into victimName
      from dual;
      dbms_output.put_line(victimName);
    END;
    /
    
    Peter O'Toole
    

    【讨论】:

    • 感谢您的帮助。这就是我们从 XML 中检索名称的方式。受害者名称 := SUBSTR(ncoXml.EXTRACT('/victims/victim[' || TO_CHAR(victimIndex) || ']/name/text()').GETSTRINGVAL(), 1, 200);然后使用该变量名来更新/插入。我一直认为最好将未编码的数据存储在数据库中并在显示之前对其进行编码。
    • 有没有办法改变存储过程来存储未编码的数据?
    • 该过程如何存储数据——作为一个简单的插入到 XMLType 列中,作为一个 CLOB 列,从 XML 中提取数据并放入关系表中?如果它是一个 XMLType 列,那么存储编码实体是正确的,并且在查询/提取时需要对它们进行解码。否则,您可以在将 XML 数据转换为 CLOB 或关系列时对其进行解码。
    • 该字段是一个 varchar(200)
      他们这样做... BEGINvictimName := SUBSTR(ncoXml.EXTRACT('/victims/victim[' || TO_CHAR(victimIndex ) || ']/name/text()').GETSTRINGVAL(), 1, 200);其他人为空时的例外情况;结尾;

      然后做一个标准的插入/更新更低。
    • @frmrock164 - 然后他们可以在答案中使用XMLCast 选项来获取解码值,而不是extract? (或已弃用 extractValue)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-24
    • 1970-01-01
    • 1970-01-01
    • 2015-07-08
    相关资源
    最近更新 更多