首页 文章

将Oracle存储过程从使用DBMS_XMLSave转换为DBMS_XMLStore

提问于
浏览
0

我继承了一个在后端使用Oracle数据库的应用程序 . 该数据库最初使用的是完整版Oracle,但我们已将其移至Oracle XE . Oracle XE似乎不支持Oracle XML SQL实用程序(包括DBMS_XMLSave),或者至少我无法弄清楚如何安装它 .

根据这个链接(http://ellebaek.wordpress.com/2011/01/27/converting-between-oracle-data-and-xml/):

与DBMS_XMLQUERY类似,DBMS_XMLSAVE是用Java实现的,因此Oracle Database Express不支持它 .

数据库中的存储过程使用DBMS_XMLSave,但是从此链接(https://forums.oracle.com/forums/thread.jspa?threadID=530048)看来,DBMS_XMLSave已被DBMS_XMLStore替换:

DBMS_XMLSTORE PL / SQL包是在Oracle数据库10g第1版中引入的 . 该包基于XML文档的内容对数据库内的关系表或对象表执行DML操作 . 请注意,在Oracle Database 10g之前,此功能存在于另一个名为DBMS_XMLSAVE的PL / SQL包中 .

我在链接中尝试了解决方案:

CREATE OR REPLACE PUBLIC SYNONYM DBMS_XMLSAVE FOR DBMS_XMLSTORE;
GRANT EXECUTE ON DBMS_XMLSAVE TO PUBLIC;

这确实修复了很大一部分错误,但是我留下了一些问题:

DBMS_XMLSave.setDateFormat(v_insCtx, 'MM/dd/yyyy');
DBMS_XMLSave.setBatchSize(v_updCtx, -1);
DBMS_XMLSave.setDateFormat(v_updCtx, 'MM/dd/yyyy');

DBMS_XMLStore似乎不支持这些方法 . 四处搜索我认为我找到了解决setDateFormat问题的方法 . 根据此链接(http://ellebaek.wordpress.com/2011/01/27/converting-between-oracle-data-and-xml/),DBMS_XMLStore对日期/时间值使用NLS设置 . 此链接(http://www.tiplib.com/231/nls-parameter-session-logon-trigger)指出可以在存储过程中更改NLS设置,如下所示:

BEGIN
    DBMS_SESSION.SET_NLS('NLS_DATE_FORMAT','YYYYMMDD');
    COMMIT;
END;

所以我希望我可以像这样替换setDateFormat行:

-DBMS_XMLSave.setDateFormat(v_insCtx, 'MM/dd/yyyy');  -- remove
+DBMS_SESSION.SET_NLS('NLS_DATE_FORMAT','MM/dd/yyyy');  -- insert

我无法找到setBatchSize的替代品 .

所以我的问题是:

  • 我是以正确的方式接近这个,还是有更好的方法?

  • DBMS_XMLSave.setDateFormat(v_insCtx,'MM / dd / yyyy') - > DBMS_SESSION.SET_NLS('NLS_DATE_FORMAT','MM / dd / yyyy')会改变吗?

  • 是否有setBatchSize的替代品?是否有必要替换setBatchSize?

一般来说,如果有人问过上面问题2的问题,我会告诉他们尝试并告诉我,但我目前无法获得编译的代码,而且我没有已知的工作基线 . 我可以删除问题行,它可能会产生一些结果,但我不清楚结果是否正确 . 从这里删除问题行并尝试检查结果将是我的方法 .

原始代码如下:

procedure insert_xml(p_xmlDoc in clob, p_tableName in varchar2) is
        v_insCtx DBMS_XMLSave.ctxType;
        v_rows number;
    begin
      v_insCtx := DBMS_XMLSave.newContext(p_tableName); -- get the context handle
      DBMS_XMLSave.setDateFormat(v_insCtx, 'MM/dd/yyyy'); -- set date format
      v_rows := DBMS_XMLSave.insertXML(v_insCtx, p_xmlDoc); -- this inserts the document
      DBMS_XMLSave.closeContext(v_insCtx); -- this closes the handle
    exception
      when OTHERS then
        raise_application_error(-20001,'An error was encountered. - '||SQLCODE||' -ERROR- '||SQLERRM);
    end insert_xml;

    procedure update_xml(p_xmlDoc in clob, p_tableName in varchar2, p_key in varchar2) is
            v_updCtx DBMS_XMLSave.ctxType;
            v_rows number;
        begin
            v_updCtx := DBMS_XMLSave.newContext(p_tableName); -- get the context
            DBMS_XMLSave.setBatchSize(v_updCtx, -1);
            DBMS_XMLSave.setDateFormat(v_updCtx, 'MM/dd/yyyy'); -- set date format
            DBMS_XMLSave.clearUpdateColumnList(v_updCtx); -- clear the update settings..
            DBMS_XMLSave.setKeyColumn(v_updCtx, p_key); -- set EMPNO as key column
            v_rows := DBMS_XMLSave.updateXML(v_updCtx, p_xmlDoc); -- update the table.
            DBMS_XMLSave.closeContext(v_updCtx); -- close the context..!
      exception
        when OTHERS then
          raise_application_error(-20001,'An error was encountered. - '||SQLCODE||' -ERROR- '||SQLERRM);
        end update_xml;

谢谢你的协助 .

1 回答

  • 0

    我已经半回答了这个问题 . 当我尝试:

    DBMS_SESSION.SET_NLS('NLS_DATE_FORMAT','MM/DD/YYYY');
    

    我发现我遇到了这些错误:

    ORA-31011: XML parsing failed
    ORA-19202: Error occurred in XML processing
    LPX-00222: error received from SAX callback function
    ORA-01843: not a valid month
    

    挖掘后我发现:

    EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT = "MM/DD/YYYY"';
    

    这似乎让日期处理没有抱怨,我认为它已经解决了问题,但我不是100%肯定在这个阶段 .

    我没有替换DBMS_XMLSave.setBatchSize();我不确定这是否会影响性能 .

    我没有直接修改代码,而是使用公共同义词,它目前看起来像这样:

    procedure insert_xml(p_xmlDoc in clob, p_tableName in varchar2) is
            v_insCtx DBMS_XMLStore.ctxType;
            v_rows number;
        begin
            v_insCtx := DBMS_XMLStore.newContext(p_tableName); -- get the context handle
            EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT = "MM/DD/YYYY"';
            v_rows := DBMS_XMLStore.insertXML(v_insCtx, p_xmlDoc); -- this inserts the document
            DBMS_XMLStore.closeContext(v_insCtx); -- this closes the handle
        exception
            when OTHERS then
              raise_application_error(-20001,'An error was encountered. - '||SQLCODE||' -ERROR- '||SQLERRM);
        end insert_xml;
        procedure update_xml(p_xmlDoc in clob, p_tableName in varchar2, p_key in varchar2) is
            v_updCtx DBMS_XMLStore.ctxType;
            v_rows number;
        begin
            v_updCtx := DBMS_XMLStore.newContext(p_tableName); -- get the context
            EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT = "MM/DD/YYYY"';
            DBMS_XMLStore.clearUpdateColumnList(v_updCtx); -- clear the update settings..
            DBMS_XMLStore.setKeyColumn(v_updCtx, p_key); -- set EMPNO as key column
            v_rows := DBMS_XMLStore.updateXML(v_updCtx, p_xmlDoc); -- update the table.
            DBMS_XMLStore.closeContext(v_updCtx); -- close the context..!
        exception
            when OTHERS then
              raise_application_error(-20001,'An error was encountered. - '||SQLCODE||' -ERROR- '||SQLERRM);
            end update_xml;
    

相关问题