问题
I am using Oracle 11g XMLTABLE function to fetch data from the attached XML file. When I execute the code, I get 3 rows. I am retrieving the Products correctly generating one row for each Product corresponding to a Customer. The problem is that I'm not getting the rest of the Customer data, I' getting nulls for CustomerName, CustomerDOB, and CustomerEmail. For some reason the code that I am using, Oracle is not fetching 2 levels up. Please help! What am I doing wrong?
XML
<?xml version="1.0" encoding="iso-8859-1"?>
<USACustomers>
<NewYorkCustomers>
<Customer>
<CustomerData>
<CustomerName>John Stark</CustomerName>
<CustomerDOB>07/09/1973</CustomerDOB>
<CustomerEmail>j.stark@liquid.com</CustomerEmail>
</CustomerData>
<CustomerAddress>
<Address>400 Railroad Way</Address>
<City>Larchmont</City>
<State>NY</State>
<Zip>10542</Zip>
</CustomerAddress>
<CustomerProducts>
<CustomerProduct>
<PoductType>CTD</PoductType>
<ProductNumber>2050035302</ProductNumber>
</CustomerProduct>
<CustomerProduct>
<PoductType>REC</PoductType>
<ProductNumber>2050920400</ProductNumber>
</CustomerProduct>
</CustomerProducts>
</Customer>
<Customer>
<CustomerData>
<CustomerName>Maria Stark</CustomerName>
<CustomerDOB>07/09/1972</CustomerDOB>
<CustomerEmail>m.stark@liquid.com</CustomerEmail>
</CustomerData>
<CustomerAddress>
<Address>410 Railroad Way</Address>
<City>Larchmont</City>
<State>NY</State>
<Zip>10542</Zip>
</CustomerAddress>
<CustomerProducts>
<CustomerProduct>
<PoductType>REC</PoductType>
<ProductNumber>2050920400</ProductNumber>
</CustomerProduct>
</CustomerProducts>
</Customer>
</NewYorkCustomers>
</USACustomers>
CODE
SELECT
CustomerName,
CustomerDOB,
CustomerEmail,
PoductType
FROM XMLTABLE ( '/USACustomers/NewYorkCustomers/Customer/CustomerProducts/CustomerProduct'
PASSING xmltype (BFILENAME ('BACKUP', 'TEST.xml'), NLS_CHARSET_ID ('AL32UTF8'))
COLUMNS CustomerName VARCHAR2(50) PATH 'CustomerData/CustomerName',
CustomerDOB VARCHAR2(50) PATH 'CustomerData/CustomerDOB',
CustomerEmail VARCHAR2(50) PATH 'CustomerData/CustomerEmail',
PoductType VARCHAR2(50) PATH 'PoductType',
ProductNumber VARCHAR2(50) PATH 'ProductNumber');
回答1:
nest that, as you want to first extract customer data, and then iterate over each product.
select customername, customerdob, customeremail, PoductType, ProductNumber
from (select customername, customerdob, customeremail, products
from xmltable('/USACustomers/NewYorkCustomers/Customer'
PASSING xmltype (BFILENAME ('BACKUP', 'TEST.xml'), NLS_CHARSET_ID ('AL32UTF8'))
columns customername varchar2(50) path 'CustomerData/CustomerName',
customerdob varchar2(50) path 'CustomerData/CustomerDOB',
customeremail varchar2(50) path 'CustomerData/CustomerEmail',
products xmltype path 'CustomerProducts')) cust,
xmltable('/CustomerProducts/CustomerProduct'
passing cust.products
columns PoductType VARCHAR2(50) PATH 'PoductType',
ProductNumber VARCHAR2(50) PATH 'ProductNumber');
eg:
SQL> select customername, customerdob, customeremail, PoductType, ProductNumber
2 from (select customername, customerdob, customeremail, products
3 from mytable l,
4 xmltable('/USACustomers/NewYorkCustomers/Customer'
5 passing l.x
6 columns customername varchar2(50) path 'CustomerData/CustomerName',
7 customerdob varchar2(50) path 'CustomerData/CustomerDOB',
8 customeremail varchar2(50) path 'CustomerData/CustomerEmail',
9 products xmltype path 'CustomerProducts')) cust,
10 xmltable('/CustomerProducts/CustomerProduct'
11 passing cust.products
12 columns PoductType VARCHAR2(50) PATH 'PoductType',
13 ProductNumber VARCHAR2(50) PATH 'ProductNumber');
CUSTOMERNAME CUSTOMERDO CUSTOMEREMAIL PODUCTTYPE PRODUCTNUMBER
-------------------- ---------- -------------------- ---------- -------------
John Stark 07/09/1973 j.stark@liquid.com CTD 2050035302
John Stark 07/09/1973 j.stark@liquid.com REC 2050920400
Maria Stark 07/09/1972 m.stark@liquid.com REC 2050920400
回答2:
You can do it like this (with one xmltable() call:
SELECT
CustomerName,
CustomerDOB,
CustomerEmail,
PoductType
FROM XMLTABLE ('for $i in $custt/USACustomers/NewYorkCustomers/Customer,
$j in $i//CustomerProduct
return <deNormalizedCust>{$i//CustomerData}{$j}</deNormalizedCust>'
PASSING xmltype(BFILENAME ('BACKUP', 'TEST.xml'), NLS_CHARSET_ID ('AL32UTF8'))
as "custt"
COLUMNS CustomerName VARCHAR2(50) PATH '/deNormalizedCust/CustomerData/CustomerName',
CustomerDOB VARCHAR2(50) PATH '/deNormalizedCust/CustomerData/CustomerDOB',
CustomerEmail VARCHAR2(50) PATH '/deNormalizedCust/CustomerData/CustomerEmail',
PoductType VARCHAR2(50) PATH '/deNormalizedCust/CustomerProduct/PoductType',
ProductNumber VARCHAR2(50) PATH '/deNormalizedCust/CustomerProduct/ProductNumber');
Here is a sqlfiddle demo
来源:https://stackoverflow.com/questions/14341261/oracle-xmltable-function-not-fetching-data-correctly