Select Data out of XML from a column in ORACLE database - sql

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

Related

Using JSON_TABLE on ORACLE DB

create table JSON_TAB (JSON_VAL CLOB);
-- tried to add the constraint like this CONSTRAINT JTE_CK check (JSON_VAL is json) butt says it expects null so I didn't create it for now.
I am trying to execute the statement
SELECT JT.Ime, JT.Broj, JT.Pozicija
FROM JSON_TAB JTE,
JSON_TABLE (JTE.JSON_VAL, '$.players[*]'
COLUMNS (Ime VARCHAR2(20) PATH '$.name',
Broj NUMBER PATH '$.number',
Pozicija VARCHAR2 PATH '$.position')) JT ;
and receiving an error SQL command not properly ended.
JSON_VAL is a CLOB!
Is it a problem with syntax, data type or something else?
I took the example from youtube tutorial and entered it manually.
ORACLE version is 12.1.0.2.0.

How to read a field Oracle containing XML

A table exists in the environment of production with the following structure:
CREATE TABLE gold_dwh_reload (
msisdn NUMBER(13,0) NOT NULL,
recharge_date TIMESTAMP(6) NOT NULL,
impacted_balances VARCHAR2(4000) NULL,
lc_state VARCHAR2(5) NOT NULL)
TABLESPACE sopfun_tab
NOCOMPRESS
/
A normal consultation would the following result by example:
MSISDN RECHARGE_DATE IMPACTED_BALANCES LC_STATE
584124723950 29.04.15 13:23:38.000 <balance><name>B_LPP_Bs_Main</name><label></label><before>697.21429</before><after>797.21429</after><amount>100</amount><start></start><end></end><unit>Bs</unit></balance><balance><name>B_LPP_KB_National</name><label>PA_Adjustment</label><before>0</before><after>10240</after><amount>10240</amount><start>29042015000000</start><end>29052015000000</end><unit>Kbytes</unit></balance><balance><name>B_LSP_Bs_Promotions</name><label>PA_Adjustment</label><before>0</before><after>25</after><amount>25</amount><start>29042015000000</start><end>29052015000000</end><unit>Bs</unit></balance> ACT
But i need to break the IMPACTED_BALANCES field in columns. Anyone know how I do it?
This is typically done using XMLTable
select
msisdn, recharge_date,
x_name, x_label, x_before, x_after, x_amount,
to_date(x_start, 'DDMMYYYYHH24MISS') x_start,
to_date(x_end, 'DDMMYYYYHH24MISS') x_end,
x_unit,
lc_state
from gold_dwh_reload
cross join
xmltable('/balances/balance'
passing xmltype('<balances>'||impacted_balances||'</balances>')
columns
x_name path '/balance/name',
x_label path '/balance/label',
x_before number path '/balance/before',
x_after number path '/balance/after',
x_amount number path '/balance/amount',
x_start path '/balance/start',
x_end path '/balance/end',
x_unit path '/balance/unit'
);
Here's a SQL Fiddle.
Mixing SQL and XML is powerful but creates many potential type safety issues. A single invalid date, number, or XML file will crash the whole query. The string in your example is not valid XML, that's why I concatenated another tag to the beginning and end.

Insert xml into XmlType field

I have this table in Oracle 11g:
create table tmp_test_xml (
name_xml varchar2(4000),
file_xml xmltype
);
At this link oracle binding xmltype, I have read that for a correct insert into a field XMLType I must to use the "Xmltype binding" as this insert:
insert into tmp_test_xml values (
'file.xml',
xmltype(
'<?xml version="1.0" encoding="UTF-8"?>
<list_book>
<book>1</book>
<book>2</book>
<book>3</book>
</list_book>'
)
);
But, if I try to lunch this insert without the binding in XMLType, work very fine:
insert into tmp_test_xml values (
'file.xml',
'<?xml version="1.0" encoding="UTF-8"?>
<list_book>
<book>1</book>
<book>2</book>
<book>3</book>
</list_book>'
);
Now, is facoltative use binding or not? What is the correct insert?
Why the second insert works?
Oracle tries to do job for you, so if your datatype doesn't match column datatype, it attempts to convert data into correct data type.
Since you have correct xml string in your insert statement, database did conversion to xmltype for you.
And I'm not sure, but I doubt there were a word must use XMLType binding.
But you might want use it, if you need to have more control when creating XML from string.
Check XMLType constructors to get an idea.

Updating a CLOB XML in Oracle

I have a CLOB column which contains a large amount of XML. I want to add a new attribute in that XML, like this attribute :
<name>me</name>
I tried using UpdateXML but I'm not getting it right.
CLOB is converted to XMLType using XMLType() and XMLType is converted to CLOB using to_clob. The following is an example.
create table table_with_clob (myclob clob);
insert into table_with_clob values ('<mytag><subtag>hello world</subtag></mytag>');
UPDATE table_with_clob SET myclob =
to_clob(INSERTCHILDXML(xmltype(myclob),
'/mytag', 'subtag',
XMLType('<subtag>another</subtag>')));
select * from table_with_clob;
Output
myclob
------
<mytag><subtag>hello world</subtag><subtag>another</subtag></mytag>
Though I think this is not very efficient and you might better convert the column to XMLType and the operate with it.

Oracle SQL - Extracting clob value from XML with repeating nodes

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