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.
Related
I need to update two values within XML data that is stored in a ntext column. I have a copy of the database to test with, and I haven't been successful with the information I have found.
Here is a sample the XML that I need to update:
<?xml version="1.0" encoding="utf-16"?>
<cmnReportExportParameters xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DSNs>
<ReportDSN>
<Name>Name</Name>
<Database>DBName</Database>
<Server />
<User>user</User>
<Password>removed </Password>
<DevelopmentName>DBName</DevelopmentName>
</ReportDSN>
</DSNs>
</cmnReportExportParameters>
I need to update the "user" and "password" fields within this XML data. This is part of a legacy CMS application, and I am simply supporting the system (I'm not the developer).
I can cast the data successfully select Name, Parameters, CAST(parameters as xml) from tablename
Any guidance is appreciated.
This is far from ideal, but this is the only way I can think to do it. As your column is the wrong data type (ntext) you can't use the modify XQUERY command. Thus, you have to insert your data into a temporary table, update it, and then reinsert it. This is not going to be great for performance, but it works. As I said before, fixing the data type will make this far easier:
CREATE TABLE [sample] (YourIDCol int IDENTITY(1,1),
NotXML ntext);
INSERT INTO [sample] (NotXML)
VALUES (
N'<?xml version="1.0" encoding="utf-16"?>
<cmnReportExportParameters xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DSNs>
<ReportDSN>
<Name>Name</Name>
<Database>DBName</Database>
<Server />
<User>user</User>
<Password>removed </Password>
<DevelopmentName>DBName</DevelopmentName>
</ReportDSN>
</DSNs>
</cmnReportExportParameters>');
GO
CREATE TABLE #UpdateXML (ID int, ActualXML xml);
INSERT INTO #UpdateXML (ID,ActualXML)
SELECT YourIDCol,
TRY_CONVERT(xml,NotXML)
FROM [sample]
WHERE TRY_CONVERT(xml,NotXML) IS NOT NULL
AND YourIDCol = 1; --if you need it
UPDATE #UpdateXML
SET ActualXML.modify('replace value of (cmnReportExportParameters/DSNs/ReportDSN/User/text())[1] with ("NewUsername")');
UPDATE #UpdateXML
SET ActualXML.modify('replace value of (cmnReportExportParameters/DSNs/ReportDSN/Password/text())[1] with ("NewPassword")');
UPDATE S
SET NotXML = CONVERT(ntext,CONVERT(nvarchar(MAX),U.ActualXML)) --yuck
FROM [sample] S
JOIN #UpdateXML U ON S.YourIDCol = U.ID;
SELECT *
FROM [sample];
DROP TABLE #UpdateXML;
GO
DROP TABLE [sample];
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
I have following XML stored in a XML column in a SQL Server database table.
<?xml version="1.0" encoding="UTF-8" ?>
<ns0:Root>
<ns0:Result>
<ns0:AStatus>Aaa</ns0:AStatus>
<ns0:BStatus>Bbb</ns0:BStatus>
</ns0:Result>
</ns0:Root>
I'd like to get value "Aaa", by firing SQL query.
Your XML data is incomplete - it uses a namespace prefix ns0 without defining it anywhere... I've added some arbitrary, totally made-up XML namespace here in my sample - you need to check what that XML namespace actually is in your case and adapt the sample accordingly!
Try this:
DECLARE #InputTable TABLE (ID INT NOT NULL, XmlData XML)
INSERT INTO #InputTable(ID, XmlData) VALUES(42, '<?xml version="1.0" encoding="UTF-8" ?>
<ns0:Root xmlns:ns0="urn:some-sample-xml-namespace">
<ns0:Result>
<ns0:AStatus>Aaa</ns0:AStatus>
<ns0:BStatus>Bbb</ns0:BStatus>
</ns0:Result>
</ns0:Root>')
-- define the XML namespace to use
;WITH XMLNAMESPACES('urn:some-sample-xml-namespace' AS x)
SELECT
ID,
XC.value('(x:AStatus)[1]', 'varchar(50)')
FROM
#inputtable
CROSS APPLY
-- get a "pseudo" table of nodes <ns0:Root>/<ns0:Result>
XmlData.nodes('x:Root/x:Result') AS XT(XC)
Basically, you need to have a definition for your XML namespace prefix - and in the SELECT against this XML data, you need to have the same XML namespace (even though - as shown - the prefix assigned to that namespace can be different - but the namespace must match!).
This then selects the data from the table, and for the XML data, it uses the .nodes() XQuery function to get a list of XML element that match this XPath expression - and it gets these nodes as a in-memory pseudo table XT with a single XML column XC from which you can then again fetch values (like reaching into the first <ns:AStatus> element).
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.
Some of the columns that I am trying to load into Oracle via SQL Loader from an XML file are null. For example may have several filled but ocassionally it has some nulls.
How can I tell the SQL*Loader that some of the data will be null, or how can I deal with nulls?
Like jonearles suggested. I use XMLTABLE to insert XML data into relational tables. First put the XML data into a Oracle tables XMLTYPE column:
DROP TABLE XMLTEST;
CREATE TABLE XMLTEST
( XML_COL XMLTYPE);
DECLARE
poXML CLOB;
BEGIN
-- Store the Purchase Order XML in the CLOB variable
poXML := '<?xml version="1.0"?>
<zalen>
<zaal zaal_id="1">
<alt_id>88</alt_id>
<display_naam>01 West 430</display_naam>
<alt_db>exp_BB</alt_db>
</zaal>
<zaal zaal_id="2">
<alt_id>170</alt_id>
<display_naam>02 Midden 010</display_naam>
<alt_db>exp_BB</alt_db>
</zaal>
<zaal zaal_id="3">
<alt_id>173</alt_id>
<display_naam>02 Midden 110</display_naam>
<alt_db>exp_BB</alt_db>
</zaal>
<zaal zaal_id="4">
<syl_id>F491B0A119DABE76B2F6B2C0A3E902F6</syl_id>
<alt_id>183</alt_id>
<display_naam>02 Oost 010</display_naam>
<alt_db>exp_BB</alt_db>
</zaal>
<zaal zaal_id="5">
<alt_id>172</alt_id>
<display_naam>02 Oost 300</display_naam>
<alt_db>exp_BB</alt_db>
</zaal>
.
.
.
<zaal zaal_id="126">
<syl_id>F491B0A119DABE76B2F6B2C0A3E901E3</syl_id>
<alt_id>129</alt_id>
<display_naam>HB.02.140</display_naam>
<alt_db>exp_EE</alt_db>
</zaal>
</zalen>';
INSERT INTO xmltest (xml_col) VALUES (XMLTYPE(poXML));
END;
/
Use XMLTable function to create (or insert into) the table:
drop table zalen;
create table zalen as
select xt.zaal_id
, xt.alt_id
, xt.syl_id
, xt.alt_db
, xt.display_naam
from xmltest xts
, XMLTable('zalen/zaal' PASSING xts.xml_col
columns zaal_id INTEGER PATH '#zaal_id'
,alt_id INTEGER PATH 'alt_id'
,syl_id VARCHAR2(100) PATH 'syl_id'
,display_naam VARCHAR2(100)PATH 'display_naam'
,alt_db VARCHAR2(100)PATH 'alt_db') xt;
You may want to rethink the way you're loading and transforming files. I assume this is related to your other question, in which case it looks like you're building your own XML parser. Oracle provides some tools to help you do this.
First, just to load the file, you can either use SQL*Loader to load the data as an XMLType, or you can use something like DBMS_XSLPROCESSOR.READ2CLOB to read the file as a CLOB and then convert it to an XMLType.
After it's loaded as an XMLType, you can use a PL/SQL procedure that uses XPath to iterate through the values and insert them into the table.
And there are probably some other ways to do it.
I'm sure none of these ideas are nearly as easy as what you were hoping for. Processing XML correctly is much more complicated than what SQL*Loader is typically used for - loading delimited files.