xmloracle-databaseoracle11gxmltypexmlindex

Structured XMLIndex giving error on creation


I have a table having one columns as XMLTYPE being stored with Object-Relational storage. Below is table ddl.

CREATE TABLE Orders ( Order_id number not null,
                  Order_status Varchar2(100),
                  Order_desc XMLType not null )
                  XMLTYPE Order_desc STORE AS OBJECT RELATIONAL
                  XMLSCHEMA "http://localhost/public/xsd/Orderstore.xsd"
                  ELEMENT "OrderVal";

I have successfully registered the schema to load XSD with XML DB. Below is the XML being loaded into the XMLTYPE column.

<?xml version="1.0" encoding="utf-8" ?>
<draftorders>
<OrderSumm>
   <Ordercod>OrderBookings</Ordercod>
</OrderSumm>
<Orderattrs>
 <Orderattr Ordername="HROrder">
    <OrderVals>
        <OrderVal>
             <listvalue>Order1</listvalue>
             <Orderattrs>
                  <Orderattr Ordername="Node1_Child1">
                     <OrderVals>
                         <OrderVal>
                              <listvalue><![CDATA[ Node1_Child1_OrderValue_1]]></listvalue>
                              <Orderattrs>
                                   <Orderattr Ordername="Node2_Child1">
                                        <OrderVals>
                                             <OrderVal>
                                                  <listvalue><![CDATA[ Node2_Child1_OrderValue_1]]></listvalue>
                                             </OrderVal>
                                        </OrderVals>
                                   </Orderattr>
                                   <Orderattr Ordername="Node2_Child2">
                                       <OrderVals>
                                            <OrderVal>
                                                  <listvalue><![CDATA[ Node2_Child2_OrderValue_1]]></listvalue>
                                            </OrderVal>
                                       </OrderVals>
                                   </Orderattr>
                              </Orderattrs>
                         </OrderVal>
                     </OrderVals>
                  </Orderattr>
             </Orderattrs>
        </OrderVal>
    </OrderVals>
 </Orderattr>
 </Orderattrs>
 </draftorders>

This XML contain around 2500 values for Node2 Orderattr. Am using the below query to print out all the Node2 values in one go using XMLTABLE.

SELECT ord.OrdName, ord.OrdVal
FROM Orders,  XMLTable('/OrderVal[1]/Orderattrs/Orderattr[1]/OrderVals/OrderVal[1]/Orderattrs/Orderattr'
                     PASSING Order_desc
                     COLUMNS "OrdName"   VARCHAR2(4000) PATH '@Ordername',
                             "OrdVal"    VARCHAR2(4000) PATH  'OrderVals/OrderVal[1]/listvalue') ord;

Output:-

Node2_Child1
Node2_Child1_OrderValue_1
Node2_Child2
Node2_Child2_OrderValue_1
......
Node2_Child2500
Node2_Child2500_OrderValue_1

Now I want to restrict my resultset to only first 25 Node2 Orderattr values and not the entire set. How should I go about restricting the resultset to only first 25 node values.

Able to get it using XMLTable.

I have tried below XMLQuery function to achieve the same above output, but receive truncated output.

SELECT XMLQuery(            '/OrderVal[1]/Orderattrs/Orderattr[1]/OrderVals/OrderVal[1]/Orderattrs/Orderattr/(@listname, OrderVals/OrderVal/listvalue/text())'
PASSING o.Order_desc RETURNING CONTENT)
FROM Orders o;

Output:- Node2_Child1Node2_Child1_OrderValue_1Node2_Child2Node2_Child2_OrderValue_1Node2_Child3Node2_Child3_OrderValue_1Node2_Child4Node2_Child4_OrderValue_1Node2_Child5Node2_Child5_OrderValue_1........Node2_Child25Node2_Child25_OrderValue_1

Thanks...


Solution

  • You need to add a condition with position() Xpath function to the end of a XQuery expression:

    ...
    XMLTable(
      '/OrderVal[1]/Orderattrs/Orderattr[1]/OrderVals/OrderVal[1]/Orderattrs/Orderattr[position() <= 25]'
    ...
    

    SQLFiddle test with your exapmle

    Update

    Question updated, so a little bit more about XMLQuery() function. First of all, this function return single XMLType, therefore to get individual elements you need to use ExtractValue() function:

    with params as (
      select XMLParse(content '
      <draftorders>
       <!-- EXAMPLE XML FROM QUESTION GOES HERE -->
     </draftorders>
      ')
      doc from dual
    )
    select 
      ExtractValue(xml_val, '/Orderattr/@Ordername') order_name,
      ExtractValue(xml_val, '/Orderattr/OrderVals/OrderVal[1]/listvalue') list_value
    from (
      SELECT 
        XMLQuery(
          '//OrderVal[1]/Orderattrs/Orderattr[1]/OrderVals/OrderVal[1]/Orderattrs/Orderattr[position() < 2]'
          PASSING doc returning content
        ) xml_val
      from 
        params
    );  
    

    SQLFiddle test for XMLQuery variant

    Second: if your XQuery return set of nodes then resulting XML not well-formed because there are no single root node.

    Last: In your variant with XMLQuery expression returns set of values, not XML. All value sequences in XQuery concatenated without separators, so you got what you got:

    Node2_Child1<![CDATA[ Node2_Child1_OrderValue_1]]>Node2_Child2<![CDATA[ Node2_Child2_OrderValue_1]]>
    

    and after evaluation this expression translated to just

    Node2_Child1Node2_Child1_OrderValue_1Node2_Child2Node2_Child2_OrderValue_1
    

    Oops... You mistyped @Ordername and changed it to @listname at least in question text, so this part returns empty string and if this expression evaluated without changes result would be like

    Node2_Child1_OrderValue_1Node2_Child2_OrderValue_1