Question

I am trying to get the data from a Oracle View created on XML Type column.
e.g: Following is the XSD:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="MsrFact" type="MsrNode"/>
<xsd:complexType name="MsrNode">
<xsd:sequence>

<xsd:element name="shipTo" type="MsrValue"/>
<xsd:element name="billTo" type="MsrValue"/>
<xsd:element name="FormulaeItem"  type="MsrValue" maxOccurs="10"/>
</xsd:sequence>
</xsd:complexType> <xsd:complexType name="MsrValue">
<xsd:sequence>

<xsd:element name="name"   type="xsd:string"/>
<xsd:element name="street" type="xsd:integer"/>
</xsd:sequence>
</xsd:complexType> </xsd:schema>


Inserted xml is:

<MsrFact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MsrNode>

  <shipTo>
     <name>shipTo</name>
   </shipTo>

   <billTo>
     <name>billTo</name>
   </billTo>

  <FormulaeItem>
    <name>FormulaeItem1</name>
  </FormulaeItem>

  <FormulaeItem>
     <name>FormulaeItem2</name>
     <street>100</street>
  </FormulaeItem>

  <FormulaeItem>
     <name>FormulaeItem3</name>
   </FormulaeItem>
</MsrNode> </MsrFact>

Table: temptab( ogrid number(10), xdata xmltype);

VIEW: CREATE OR REPLACE VIEW
MsrFactView(orgid,shipTo,shipToR, billTo,billToR, FormulaeItem,FormulaeItemR)
AS SELECT ogrid,
extractValue(xdata, '/MsrFact/shipTo/name'),
extractValue(xdata, '/MsrFact/shipTo/street'),
extractValue(xdata, '/MsrFact/billTo/name'),
extractValue(xdata, '/MsrFact/billTo/street'),
extractValue(xdata, '/MsrFact/FormulaeItem/name'),
extractValue(xdata, '/MsrFact/FormulaeItem/street')
FROM temptab;

I cannot write a direct select query on this view as it gives the error
SQL Error: ORA-01427: single-row subquery returns more than one row
01427. 00000 - "single-row subquery returns more than one row"

Is there any way to get the data from this view? Thanks !

Was it helpful?

Solution

extractValue only extracts a single value from the give path, but as the FormulaeItem can be many, you can't use extractValue here. Besides, using extractValue is a old and not recommended way for querying XML. You should use the new XMLTable approach.

create or replace view MsrFactView as
select tt.ogrid,
st.name shiptoName, st.street shiptoStreeet,
bt.name billtoName ,bt.street billtoStreet,
fi.name formulaeitemname ,fi.street formulaeitemstreet
FROM
temptab tt,
XMLTABLE(
    '/MsrFact/MsrNode'
    passing tt.xdata
    columns
        shipto  XMLTYPE path '/MsrNode/shipTo'
        billto  XMLTYPE path '/MsrNode/billTo'
        formulaeitem XMLTYPE path '/MsrNode/FormulaeItem'
) nd,
XMLTable (
    '/shipTo'
    passing nd.shipto
    columns
    name varchar2(4000) path '/shipTo/name'
    street number path '/shipTo/street'
) st,
XMLTABLE (
    '/billTo'
    passing nd.billto
    columns
    name varchar2(4000) path '/billTo/name'
    street number path '/billTo/street'
) bt,
XMLTable (
    '/FormulaeItem'
    passing nd.formulaeitem
    columns
    name varchar2(4000) path '/FormulaeItem/name'
    street number path '/FormulaeItem/street'
) fi
/

One thing to remember though is that you won't get one row per one 'MsrNode', as you have 1-n FormulaeItem per MsrNode. Think of it as a SQL query joining 2 tables having a 1-n relationship. Just like in that case, you will get 'n' rows per every 1 row of the parent table.

So in your case, per every MsrNode, you will get as many rows in your view, as the count of FormulaeItems in that node.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top