Oracle SQL - Extracting clob value from XML with repeating nodes - sql

I am attempting to run SQL on a table (called test_xml with a column xml_data [data type xmltype]). The column contains xml with repeating nodes (test_3). The following statement runs successfully when the node contains data of a non clob size:
SELECT
extractvalue (Value (wl), '*/test_3')
FROM test_xml
, TABLE (xmlsequence (extract (xml_data, '*/record'))) wl
but fails when test_3 node contains a lot of data:
ORA-01706: user function result value was too large
I amended my query:
SELECT
extractvalue(Value (wl), '*/test_3').getClobVal()
FROM test_xml
, TABLE (xmlsequence (extract (xml_data, '*/record'))) wl
but this fails with:
ORA-22806: not an object or REF

This was resolved via a response received on Oracle Forums:
See Forum Post
From Oracle release 11.2.0.2:
SELECT x.*
FROM test_xml t
, XMLTable(
'/*/record'
passing t.xml_data
columns
test_3 clob path 'test_3'
) x
;
My database version is 10.2.0.4 hence the following 'trick' is required:
SELECT dbms_xmlgen.convert(x.test_3.getClobVal(), 1) as test_3
FROM test_xml t
, XMLTable(
'/*/record'
passing t.xml_data
columns
test_3 xmltype path 'test_3/text()'
) x
;
Thanks go to odie_63 for this

Related

ORACLE SQL: How can I get the XML elements from within a column of XMLTYPE

I have an multiple xml documents which look like this:
<farm>
<name>Johns Farm</name>
<size>50 hectares</size>
<employees>20</employees>
<fruits>
<fruit>Banana</fruit>
<fruit>Apple</fruit>
<fruit>Watermelon</fruit>
</fruits>
</farm>
I have got this in an oracle database like this:
CREATE TABLE FARM_XML_TABLE
(FARM_NUMBER NUMBER NOT NULL PRIMARY KEY, FARM_XML XMLTYPE NOT NULL)
XMLTYPE COLUMN FARM_XML STORE AS BINARY XML
XMLSCHEMA
"http://myproject.com/farmschema.xsd"
ELEMENT "farm";
The various farms are stored in the FARM_XML column. There is about 5 of them
How can I retrieve only the name and employee elements from the FARM_XML column of multiple farms in the form of an XML. I want the output to be like this:
<farm>
<name>Johns Farm</name>
<employees>20</employees>
</farm>
<farm>
<name>Harrys Farm</name>
<employees>10</employees>
</farm>
I have tried doing this, but the output isn't all the xml elements that I want.
SELECT extract(FARM_XML, 'farm/name').getStringVal()
FROM FARM_XML_TABLE;
Oracle Setup:
CREATE TABLE FARM_XML_TABLE(
FARM_NUMBER NUMBER PRIMARY KEY,
FARM_XML XMLTYPE NOT NULL
)
XMLTYPE COLUMN FARM_XML STORE AS BINARY XML;
INSERT INTO FARM_XML_TABLE VALUES(
1,
XMLtype( '<farm>
<name>Johns Farm</name>
<size>50 hectares</size>
<employees>20</employees>
<fruits>
<fruit>Banana</fruit>
<fruit>Apple</fruit>
<fruit>Watermelon</fruit>
</fruits>
</farm>' )
);
Query 1 - Rebuild the XML:
SELECT FARM_NUMBER,
XMLElement(
"farm",
XMLElement( "name", EXTRACTVALUE( farm_xml, '/farm/name' ) ),
XMLElement( "employees", EXTRACTVALUE( farm_xml, '/farm/employees' ) )
) AS xml
FROM FARM_XML_TABLE;
or (updated - simpler version):
SELECT FARM_NUMBER,
XMLElement(
"farm",
EXTRACT( farm_xml, '/farm/name' ),
EXTRACT( farm_xml, '/farm/employees' )
) AS xml
FROM FARM_XML_TABLE;
Query 2 - Delete non-matching elements from the existing XML:
SELECT FARM_NUMBER,
DELETEXML(
farm_xml,
'/farm/*[name()!=''name''][name()!=''employees'']'
) AS xml
FROM FARM_XML_TABLE;
Output:
(Both output the same)
FARM_NUMBER XML
----------- -------------------------------------------------------------
1 <farm><name>Johns Farm</name><employees>20</employees></farm>

Oracle Regex Replace on String Query

Query to fetches the sub xml from an xml saved in the CLOB column of my table is given as :
select REGEXP_REPLACE(xmltype(t.prov_request).extract('//SOAP_Domain_Msg/Body').getStringVal(),'<Body>|</Body>','') xml
from tbl_prov_comptel
There is "SO1_USERNAME" value="xxx" in the string returned by the above query.
What i want to achieve is to form a consolidated query and append something in the start of the expression above.
ie."SO1_USERNAME" value="qwexxx"
Oracle Setup:
CREATE TABLE tbl_prov_comptl ( prov_request CLOB );
INSERT INTO tbl_prov_comptl VALUES (
'<SOAP_Domain_Msg><Body><NS4:ModifyRequest xmlns:NS4="http://soa.comptel.com/2011/02/instantlink"><NS4:RequestParameters> <NS4:Parameter name="SO1_USERNAME" value="222671150"/></NS4:RequestParameters> </NS4:ModifyRequest></Body></SOAP_Domain_Msg>'
);
Query:
SELECT EXTRACTVALUE(
xml,
'//NS4:ModifyRequest/NS4:RequestParameters/NS4:Parameter[name="SO1_USERNAME"]/#value',
'xmlns:NS4="http://soa.comptel.com/2011/02/instantlink"'
) AS SO1_USERNAME,
x.xml.getStringVal() AS xml
FROM (
SELECT XMLType( prov_request ).extract( '//SOAP_Domain_Msg/Body/*' ) AS xml
FROM tbl_prov_comptl
) x;
Output:
SO1_USERNAME XML
------------ ------------------------------------------------------------------------------
222671150 <NS4:ModifyRequest xmlns:NS4="http://soa.comptel.com/2011/02/instantlink"><NS4
:RequestParameters> <NS4:Parameter name="SO1_USERNAME" value="222671150"/></NS
4:RequestParameters> </NS4:ModifyRequest>

How to extract data from LONG datatype field using only SQL (without using PL/SQL block)?

How to extract data from LONG datatype field using only SQL (without using PL/SQL)?
Getting error while concatenating with other columns-
ORA00932: inconsistent datatypes
DB: Oracle 8i enterprise edition
There is a trick using XML:
SELECT
long_column long_column_as_clob
FROM
XMLTABLE(
'ROWSET/ROW'
PASSING
XMLTYPE(
DBMS_XMLGEN.GETXML(
Q'{SELECT long_column FROM your_table}'
)
)
COLUMNS
long_column CLOB PATH 'LONG_COLUMN'
);

Select Data out of XML from a column in ORACLE database

I am trying to select various data out of XML that I have in an oracle Database. Then i can insert those items into another table for normal SQL queries (i.e. shreding the XML). So I have the XML data below in a column that is a Clob column in my oracle database. I used this example to do that.
XML Data
<?xml version="1.0" encoding="utf-8"?>
<CarParkDataImport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.transportdirect.info/carparking B:/CODE/carparks/CarParking.xsd" xmlns="http://www.transportdirect.info/carparking">
<CarPark>
<CarParkRef>3</CarParkRef>
<CarParkName>Nunnery Lane</CarParkName>
<Location>York</Location>
<Address>Nunnery Lane--York--North Yorkshire</Address>
<Postcode>YO23 1AA</Postcode>
<Telephone>01904551309</Telephone>
<MinCostPence>200</MinCostPence>
<IsParkAndRide>false</IsParkAndRide>
<StayType>Short</StayType>
</CarPark>
</CarParkDataImport>
I started with this query
select car.ref as car_ref
, car.loc as car_loc
from XML_DOCUMENTS
, xmltable('/CarParkDataImport/CarPark'
passing XML_DOCUMENTS.XMLDOC
columns
"ref" varchar2(30) path 'CarParkRef'
, "loc" varchar2(30) path 'Location'
) car
But i get the error message,
ORA-00932: inconsistent datatypes: expected - got CLOB
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*Cause:
*Action:
Error at Line: 5 Column: 24
So its expecting that column to be a XMLTYPE column, now i tried creating a table with this column and inserting the XML into that, but all the column said was (XMLTYPE), which I guess I have to register a schema for this to work, but the register schema complained about not being valid xml, so i gave up on that went back to the CLOB.
The second query using extract value seems to work, BUT brings back nulls
SELECT EXTRACTVALUE(xmltype(xmldoc), '/CarParkDataImport/CarPark/Location')
FROM xml_documents;
I have 9 rows of in the XMLDOC column and it states 9 rows found, but all null. Then i tried another solution suggested as below
with src as (select xmltype(to_clob(XMLDOC)) /*)*/ AS messagetext FROM xml_documents)
select car.REF as car_ref
, car.LOC as car_loc
from src s
, xmltable('/CarParkDataImport/CarPark'
passing S.messagetext
columns
"REF" varchar2(30) path 'CarParkRef'
, "LOC" varchar2(30) path 'Location'
) car
;
This appears to have the same effect where it runs and but brings nothing back.
What am I missing? Do I have to declare namespace and how? Is my paths mucked up, or should I try going back to loading into a XMLTYPE column?
xmltabe expects a xmltype data. So, convert your clob to xmltype. Also you have to declare xml namespace.
SQL> create table xml_documents(
xmldoc clob
);
Table created.
SQL> insert into xml_documents values(
'<?xml version="1.0" encoding="utf-8"?>
<CarParkDataImport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.transportdirect.info/carparking B:/CODE/carparks/CarParking.xsd" xmlns="http://www.transportdirect.info/carparking">
<CarPark>
<CarParkRef>3</CarParkRef>
<CarParkName>Nunnery Lane</CarParkName>
<Location>York</Location>
<Address>Nunnery Lane--York--North Yorkshire</Address>
<Postcode>YO23 1AA</Postcode>
<Telephone>01904551309</Telephone>
<MinCostPence>200</MinCostPence>
<IsParkAndRide>false</IsParkAndRide>
<StayType>Short</StayType>
</CarPark>
</CarParkDataImport>'
);
commit;
1 row created.
Commit complete.
SQL> select car.ref as car_ref
, car.loc as car_loc
from xml_documents
, xmltable(xmlnamespaces(default 'http://www.transportdirect.info/carparking'),'CarParkDataImport/CarPark'
passing xmltype(xml_documents.xmldoc)
columns
ref varchar2(30) path 'CarParkRef'
,loc varchar2(30) path 'Location'
) car;
CAR_REF CAR_LOC
------------------------------ ------------------------------
3 York

Query xml using extract over CLOB column in Oracle

We are storing the xml in oracle database. The column type is CLOB.
I could fetch data from the xml tag with below query. When i execute the query i am getting null.
XML in the column:
<input xmlns="http://google.com/testsystem"
xmlns:testsystem="http://test.com/testSystem"
xmlns:tns="http://google.com/testService/">
<ProcessData>
<reviewYear>2014-2015</reviewYear>
</ProcessData>
</input>
Table name : test_table
Column name : input_xml
Column type : CLOB
Query:
select extract(xmltype(input_xml),'//reviewYear/text()').getStringVal() as data
from test_table
where id = 1;
Result:
DATA
------------------------------------
you need to specify namespace, please, try next query
select extract(xmltype('<input xmlns="http://google.com/testsystem"
xmlns:testsystem="http://test.com/testSystem"
xmlns:tns="http://google.com/testService/">
<ProcessData>
<reviewYear>2014-2015</reviewYear>
</ProcessData>
</input>'),'/input/ProcessData/reviewYear/text()', 'xmlns="http://google.com/testsystem" xmlns:testsystem="http://test.com/testSystem" xmlns:tns="http://google.com/testService/"').getStringVal() as data
from dual
UPD.
for update try
select updatexml(xmltype('<input xmlns="http://google.com/testsystem"
xmlns:testsystem="http://test.com/testSystem"
xmlns:tns="http://google.com/testService/">
<ProcessData>
<reviewYear>2014-2015</reviewYear>
</ProcessData>
</input>'), '/input/ProcessData/reviewYear/text()', '2013-2014',
'xmlns="http://google.com/testsystem" xmlns:testsystem="http://test.com/testSystem" xmlns:tns="http://google.com/testService/"').getclobval() as data
from dual