如何重命名Oracle XMLTYPE生成的ROW和ROWSET节点并将其转换为varchar

时间:2014-10-01 09:24:31

标签: xml oracle plsql oracle11g xmltype

在我的存储过程中,我正在获取结果sys_refcursor RESULTSET。当我使用RESULTSET_XML := XMLTYPE(RESULTSET); RESULTSET_XML is of SYS.XMLTYPE类型将其转换为XMLTYPE时,我将其视为

    <?xml version="1.0"?>
    <ROWSET>
     <ROW>
      <DELIVERY_ORDER_ID>2</DELIVERY_ORDER_ID>
      <COMPARTMENT_ID>162</COMPARTMENT_ID>
     </ROW>
     <ROW>
      <DELIVERY_ORDER_ID>2</DELIVERY_ORDER_ID>
      <COMPARTMENT_ID>163</COMPARTMENT_ID>
     </ROW>
     <ROW>
      <DELIVERY_ORDER_ID>2</DELIVERY_ORDER_ID>
  <COMPARTMENT_ID>164</COMPARTMENT_ID>
 </ROW>
</ROWSET>

我通过使用RESULTSET_XML.getStringVal();将其转换为char来获得此结果 现在我想将此数据作为VARCHAR2发送到存储过程。但是存储过程需要以下面给出的格式作为VARCHAR2

的数据
 <DocumentElement>
        <Maingrid>
          <DELIVERY_ORDER_ID>2</DELIVERY_ORDER_ID>
          <COMPARTMENT_ID>162</COMPARTMENT_ID>
        </Maingrid>
       <Maingrid>
          <DELIVERY_ORDER_ID>2</DELIVERY_ORDER_ID>
          <COMPARTMENT_ID>163</COMPARTMENT_ID>
         </Maingrid>
        <Maingrid>
          <DELIVERY_ORDER_ID>2</DELIVERY_ORDER_ID>
          <COMPARTMENT_ID>164</COMPARTMENT_ID>
        </Maingrid>
        </DocumentElement>

有没有办法重命名这些标签并将其作为varchar2发送。我正在尝试链接中给出的解决方案 [[1]:How to rename an Oracle XMLTYPE node

但由于我有结果集,我无法使用它。

或者在select语句本身有一种方法我会得到上面格式的结果。我的oracle查询是

SELECT 
    P_DO_ID AS DELIVERY_ORDER_ID, COMPARTMENT_ID 
FROM 
    T_M_COMPARTMENT 
WHERE 
    VEHICLE_ID = V_TRAILER;

2 个答案:

答案 0 :(得分:3)

您可以使用the DBMS_XMLGEN package设置节点名称并生成XML对象。作为匿名块中的一个简单示例:

set serveroutput on;
declare
  v_trailer number := 42; -- local for demo
  ctx dbms_xmlgen.ctxhandle;
  resultset sys_refcursor;
  resultset_xml xmltype;
begin
  open resultset for
    select p_do_id as delivery_order_id,compartment_id 
    from t_m_compartment
    where vehicle_id = v_trailer;
  ctx := dbms_xmlgen.newcontext(resultset);
  dbms_xmlgen.setrowsettag(ctx, 'DocumentElement');
  dbms_xmlgen.setrowtag(ctx, 'Maingrid');

  resultset_xml := dbms_xmlgen.getxmltype(ctx);
  dbms_xmlgen.closecontext(ctx);
  close resultset;

  dbms_output.put_line(resultset_xml.getStringVal());
end;
/

我使用您的查询字符串来创建结果集,但是如果您正在调用另一个函数来获取它只是替换您现在使用的任何机制/调用而不是该分配。如果您在创建结果集的过程中执行查询(即,它不是来自对另一个函数的调用),您只需将查询文本传递给new_context而不是一个开放的引用光标;虽然你必须连接你的v_trailer值,所以ref光标整体上会更清晰。

我设置了一个虚拟表,看起来像你的样本,这得到输出:

<DocumentElement>
 <Maingrid>
  <DELIVERY_ORDER_ID>2</DELIVERY_ORDER_ID>
  <COMPARTMENT_ID>162</COMPARTMENT_ID>
 </Maingrid>
 <Maingrid>
  <DELIVERY_ORDER_ID>2</DELIVERY_ORDER_ID>
  <COMPARTMENT_ID>163</COMPARTMENT_ID>
 </Maingrid>
 <Maingrid>
  <DELIVERY_ORDER_ID>2</DELIVERY_ORDER_ID>
  <COMPARTMENT_ID>164</COMPARTMENT_ID>
 </Maingrid>
</DocumentElement>

getStringVal()为您提供CLOB,但您可以将其插入varchar2列,只要它始终小于4k(如果您在12c上,则为32k),或者将其传递给另一个程序,只要它小于32k。您可能最好将其作为CLOB或XMLType传递,以保持一致。

答案 1 :(得分:0)

另一种方法是定义一个ObjectType并从那里创建XML:

CREATE OR REPLACE TYPE "Maingrid" AS OBJECT 
   ("DELIVERY_ORDER_ID" NUMBER, "COMPARTMENT_ID" NUMBER);
/

SELECT XMLELEMENT("DocumentElement", 
    XMLAGG(XMLTYPE("Maingrid"(P_DO_ID, COMPARTMENT_ID)))).getClobVal() 
FROM T_M_COMPARTMENT 
WHERE VEHICLE_ID = V_TRAILER;