Export sql query results to xml data file in oracle - sql

I have an SQL query which returns two columns with data like this:.
State Name
------- ---------
Online Terminal1
Offline Terminal2
Online Terminal3
Online Terminal4
Now I want to create an XML file with a SQL query runs. XML file structure must be like this:
<?xml version="1.0" encoding="utf-8" ?>
<Terminallist name="xml data">
<Value id="0">
<Terminal>Terminal1</Terminal>
<State>Online</State>
</Value>
<Value id="1">
<Terminal>Terminal2</Terminal>
<State>Offline</State>
</Value>
<Value id="2">
<Terminal>Terminal3</Terminal>
<State>Online</State>
</Value>
<Value id="3">
<Terminal>Terminal4</Terminal>
<State>Online</State>
</Value>
</Terminallist>
I want to save XML file to a directory like this c:/file.xml.

Answer:-
Table name: temptable
Data in table :
Query :-
SELECT XMLElement("Terminallist ", XMLAttributes('xml data' AS "name"),XMLAgg(XMLElement("value ", XMLAttributes(rownum AS "id"),XMLForest(Terminal,state))))
FROM temptable ;
output :-
<Terminallist name = "xml data">
<value id = "1">
<TERMINAL>Terminal2</TERMINAL>
<STATE>Offline</STATE>
</value>
<value id = "2">
<TERMINAL>Terminal3</TERMINAL>
<STATE>Online</STATE>
</value>
<value id = "3">
<TERMINAL>Terminal4</TERMINAL>
<STATE>Online</STATE>
</value>
</Terminallist>
Thanks
Narendar

This solution uses a WITH clause to generate the ID as you want, starting from 0. Using the analytic row_number() function provides a guaranteed sort order in the result set.
NB: XMLRoot() is deprecated as part of the XML/SQL standard but generates the version header you asked for. Find out more.
with cte as (
select row_number() over (order by name) - 1 as id
, name
, state
from terminals
)
SELECT xmlroot (
XMLElement(
"Terminallist",
XMLAttributes( 'xml data' as "name"),
XMLAgg(XMLElement("Value",
XMLAttributes(cte.id as "id"),
XMLElement("Terminal",cte.name),
XMLElement("State",cte.state)
)
)
)
, version '1.0' )
FROM cte
order by cte.id
/
Here is the output:
<?xml version="1.0"?>
<Terminallist name="xml data">
<Value id="0">
<Terminal>Terminal1</Terminal>
<State>Online</State>
</Value>
<Value id="1">
<Terminal>Terminal2</Terminal>
<State>Offline</State>
</Value>
<Value id="2">
<Terminal>Terminal3</Terminal>
<State>Online</State>
</Value>
<Value id="3">
<Terminal>Terminal4</Terminal>
<State>Online</State>
</Value>
</Terminallist>
As for writing the output to a file, that depends on how you want to call the SQL. Use SPOOL if you're running it from SQL*Plus and want to save it to a local file. If running from PL/SQL you'll need to use UTL_FILE and write to a directory on the database server.

Using the Oracle XE database as source data I'm able to export the employees table as XML as follows...
SELECT SYS_XMLAGG(
SYS_XMLGEN(
XMLFOREST(employee_id, first_name, last_name, email, phone, hire_date, manager_id, job_title)
)
) FROM employees;
The XML will look like...
<?xml version="1.0"?>
<ROWSET>
<ROW>
<EMPLOYEE_ID>107</EMPLOYEE_ID>
<FIRST_NAME>Summer</FIRST_NAME>
<LAST_NAME>Payne</LAST_NAME>
<EMAIL>summer.payne#example.com</EMAIL>
<PHONE>515.123.8181</PHONE>
<HIRE_DATE>2016-06-07</HIRE_DATE>
<MANAGER_ID>106</MANAGER_ID>
<JOB_TITLE>Public Accountant</JOB_TITLE>
</ROW>
<ROW>
<EMPLOYEE_ID>...
The CSV list of column names for XMLForest can be obtained thus...
SELECT LISTAGG(column_name, ',') FROM user_tab_columns WHERE table_name = 'EMPLOYEES';
Luck.

Related

Delete Empty tag from xmltype oracle

i want try to delete the empty tag from xmltype. I Have generate the below xml from oracle type. In the collection few elements does not have values so i generated with empty tag.
Can any one please help me out:
Actual output:
<MESSAGE>
<LOCATIONS>
<LOCATION_ID>9999</LOCATION_ID>
<LOC_TYPE>S</LOC_TYPE>
<NAME>Test Location</NAME>
<PHONE_NUM>08 </PHONE_NUM>
<LAST_MODIFIED_BY/>
<LAST_MODIFIED_DATE/>
<POS_CODE/>
</LOCATIONS>
</MESSAGE>
Expected output:
<MESSAGE>
<LOCATIONS>
<LOCATION_ID>9999</LOCATION_ID>
<LOC_TYPE>S</LOC_TYPE>
<NAME>Test Location</NAME>
<PHONE_NUM>08 </PHONE_NUM>
</LOCATIONS>
</MESSAGE>
Use DELETEXML and look for the XPath //*[not(text())][not(*)] to find elements that contain no text and no children:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name ( xml ) AS
SELECT XMLTYPE( '<MESSAGE>
<LOCATIONS>
<LOCATION_ID>9999</LOCATION_ID>
<LOC_TYPE>S</LOC_TYPE>
<NAME>Test Location</NAME>
<PHONE_NUM>08 </PHONE_NUM>
<LAST_MODIFIED_BY/>
<LAST_MODIFIED_DATE/>
<POS_CODE/>
</LOCATIONS>
</MESSAGE>' ) FROM DUAL;
Query 1:
SELECT DELETEXML(
xml,
'//*[not(text())][not(*)]'
).getStringVal()
FROM table_name
Results:
| DELETEXML(XML,'//*[NOT(TEXT())][NOT(*)]').GETSTRINGVAL() |
|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| <MESSAGE><LOCATIONS><LOCATION_ID>9999</LOCATION_ID><LOC_TYPE>S</LOC_TYPE><NAME>Test Location</NAME><PHONE_NUM>08 </PHONE_NUM></LOCATIONS></MESSAGE> |
SELECT
deletexml(xml_data, '//*[not(text())][not(*)]').getstringval()
FROM
(
SELECT
xmltype('<MESSAGE>
<LOCATIONS>
<LOCATION_ID>9999</LOCATION_ID>
<LOC_TYPE>S</LOC_TYPE>
<NAME>Test Location</NAME>
<PHONE_NUM>08 </PHONE_NUM>
<LAST_MODIFIED_BY/>
<LAST_MODIFIED_DATE/>
<POS_CODE/>
</LOCATIONS>
</MESSAGE>'
) xml_data
FROM
dual
)
this is working fine thanks

Save XML with attribute to Table in SQL Server

Hi I have XML data with attribute as input for SQL, i need this to be inserted in my table.
XML Data is
<?xml version="1.0" encoding="ISO-8859-1"?>
<MESSAGEACK>
<GUID GUID="kfafb30" SUBMITDATE="2015-10-15 11:30:29" ID="1">
<ERROR SEQ="1" CODE="28681" />
</GUID>
<GUID GUID="kfafb3" SUBMITDATE="2015-10-15 11:30:29" ID="1">
<ERROR SEQ="2" CODE="286381" />
</GUID>
</MESSAGEACK>
I want this to be inserted in below Format
GUID SUBMIT DATE ID ERROR SEQ CODE
kfafb3 2015-10-15 11:30:29 1 1 28681
kfafb3 2015-10-15 11:30:29 1 1 2868
please help.
Look into XPath and xml Data Type Methods in MSDN. This is one possible way :
declare #xml As XML = '...you XML string here...'
INSERT INTO YourTable
SELECT
guid.value('#GUID', 'varchar(100)') as 'GUID'
,guid.value('#SUBMITDATE', 'datetime') as 'SUBMIT DATE'
,guid.value('#ID', 'int') as 'ID'
,guid.value('ERROR[1]/#SEQ', 'int') as 'SEQ'
,guid.value('ERROR[1]/#CODE', 'int') as 'CODE'
FROM #xml.nodes('/MESSAGEACK/GUID') as x(guid)
Result :
just paste this into an empty query window and execute. Adapt to your needs:
DECLARE #xml XML=
'<?xml version="1.0" encoding="ISO-8859-1"?>
<MESSAGEACK>
<GUID GUID="kfafb30" SUBMITDATE="2015-10-15 11:30:29" ID="1">
<ERROR SEQ="1" CODE="28681" />
</GUID>
<GUID GUID="kfafb3" SUBMITDATE="2015-10-15 11:30:29" ID="1">
<ERROR SEQ="2" CODE="286381" />
</GUID>
</MESSAGEACK>';
SELECT Msg.Node.value('#GUID','varchar(max)') AS [GUID] --The value is no GUID, if the original values are, you could use uniqueidentifier instead of varchar(max)
,Msg.Node.value('#SUBMITDATE','datetime') AS SUBMITDATE
,Msg.Node.value('#ID','int') AS ID
,Msg.Node.value('(ERROR/#SEQ)[1]','int') AS [ERROR SEQ]
,Msg.Node.value('(ERROR/#CODE)[1]','int') AS CODE
FROM #xml.nodes('/MESSAGEACK/GUID') AS Msg(Node)

Parse XML with multilevel nesting in SQL

I'm trying to Parse some XML having multiple nesting levels in SQL. The problem I hit into here is how to write my query generic enough for it to Parse the XML below without having to hard-code the node path e:g
EXEC sp_xml_preparedocument #handle OUTPUT, #xml
INSERT #Root(ID)
SELECT *
FROM OPENXML(#handle, '/Root')
WITH (ID VARCHAR(100))
INSERT #ConditionSet(Operator)
SELECT *
FROM OPENXML(#handle, '/Root/ConditionSet')
WITH (Operator VARCHAR(100))
INSERT #ConditionSet(Operator)
SELECT *
FROM OPENXML(#handle, '/Root/ConditionSet/ConditionSet')
WITH (Operator VARCHAR(100))
INSERT #ConditionSet(Operator)
SELECT *
FROM OPENXML(#handle, '/Root/ConditionSet/ConditionSet/ConditionSet')
WITH (Operator VARCHAR(100))
Is there a better way to Parse the following XML in SQL and represent all data in tabular form?
<?xml version="1.0"?>
-<Root ID="414141" Source="AudienceBuilder">
-<ConditionSet Operator="I">
-<Condition Operator="E" ID="74373">
-<Relationship ID="56756">
<Relationship ID="67868"/>
</Relationship>
-<Value>
<![CDATA[ABC]]>
</Value>
</Condition>
-<ConditionSet Operator="O">
-<Condition Operator="E" ID="6566">
-<Relationship ID="7658">
<Relationship ID="6547"/>
</Relationship>
-<Value>
<![CDATA[DEF]]>
</Value>
</Condition>
-<Condition Operator="E" ID="96967">
-<Relationship ID="3884">
<Relationship ID="9954"/>
</Relationship>
-<Value>
<![CDATA[GHI]]>
</Value>
</Condition>
-<ConditionSet Operator="A">
-<Condition Operator="E" ID="31654">
-<Relationship ID="57894">
<Relationship ID="8532"/>
</Relationship>
-<Value>
<![CDATA[JKL]]>
</Value>
</Condition>
-<Condition Operator="E" ID="65636">
-<Relationship ID="843">
<Relationship ID="7473"/>
</Relationship>
-<Value>
<![CDATA[MNO]]>
</Value>
</Condition>
</ConditionSet>
</ConditionSet>
</ConditionSet>
</Root>
Any inputs/recommendations are highly appreciated :)
Thank you
Zeaous
Assuming you have your XML in a SQL Server variable called #XML, you can use the native XQuery support in SQL Server 2005 and newer to do this much more elegantly and efficiently:
DECLARE #XML XML = '...(your XML here).....'
SELECT
RootID = #xml.value('(/Root/#ID)[1]', 'int'),
ConditionSetOperator = XC.value('#Operator', 'varchar(50)'),
ConditionID = XC2.value('#ID', 'int'),
ConditionOperator = XC2.value('#Operator', 'varchar(50)')
FROM
#Xml.nodes('//ConditionSet') AS XT(XC)
CROSS APPLY
xc.nodes('Condition') AS XT2(XC2)
This gives me an output of
With XQuery operators like .nodes() or .value(), you can easily "shred" an XML document into relational data and store that as needed.
The first call to #xml.nodes('//ConditionSet') will get a "pseudo" table for each matching node - so each <ConditionSet> node will be returned in the "pseudo" table XT as column XC, and then I can easily grab attributes (or XML elements) from that XML fragment using XQuery methods like .value().
Or I can even grab the list of sub-nodes <Condition> for each of those <ConditionSet> nodes - using the CROSS APPLY with a second call to .nodes()

How can I query a value in SQL Server TEXT column that contains XML (not xml column type)

I have table DOCUMENTS with:
DOCUMENTS
____________________
DOCUMENTID int
USERID int
CONTENT text
I have following XML stored in TEXT column with name CONTENT in a SQL Server database
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IDMSDocument>
<DocumentContent>
<Attribute Name="Number" GUID="{FFFFFFFF-0000-0000-0000-000000000001}">
<IDMSType>3060</IDMSType>
<Value Type="Integer">
<Value>122</Value>
</Value>
</Attribute>
<Attribute Name="Date" GUID="{FFFFFFFF-0000-0000-0000-000000000002}">
<IDMSType>3061</IDMSType>
<Value Type="DateTime">
<Date>10-09-2014</Date>
</Value>
</Attribute>
<Attribute Name="Публикуване" GUID="{CA646F55-5229-4FC5-AA27-494B25023F4E}">
<IDMSType>3062</IDMSType>
<Value Type="String">
<Value>Да</Value>
</Value>
</Attribute>
<Attribute Name="Дата" GUID="{AC0465B0-4FB4-49E2-B4FA-70901068FD9B}">
<IDMSType>3063</IDMSType>
<Value Type="DateTime">
<Date>01-10-2014</Date>
</Value>
</Attribute>
<Attribute Name="Предмет на поръчка" GUID="{04A4EC72-6F33-461F-98DD-D8D271997788}">
<IDMSType>3065</IDMSType>
<Value Type="String">
<Value>Избор на консултанти</Value>
</Value>
</Attribute>
</DocumentContent>
</IDMSDocument>
I find a way how to query dingle XML attribute in a single row from table, with heavy conversion :
DECLARE #strContent NVARCHAR(MAX);
DECLARE #xmlContent XML;
SET #strContent = (select content from DOCUMENTS where DocumentID=24);
SET #xmlContent = CAST(REPLACE(CAST(#strContent AS NVARCHAR(MAX)),'utf-8','utf-16') AS XML)
SELECT #xmlContent.query('/IDMSDocument/DocumentContent/Attribute[5]/Value/Value')
where #xmlContent.value('(/IDMSDocument/DocumentContent/Attribute[5]/Value/Value)[1]', 'nvarchar(max)') like '%search%'
I need to make query like "select all rows in table that in fifth attribute in XML have value 'search' "
For me the general problem is that column type is not XML, but I have text column with stored xml inside. when I try cast, query, value directly server return that I can use it Only with XML column.
I would be very grateful if someone suggest how to do this!
Thanks!
Kamen
SQL Server doesn't allow inline XML conversion to have functions applied, i.e.: no CAST(...).query(), use a CTE to handle the conversion:
;WITH cte AS (
SELECT DocumentID, UserID, CAST(Content AS XML) AS XMLContent
FROM Documents
)
SELECT XMLContent.query('/IDMSDocument/DocumentContent/Attribute[5]/Value/Value')
FROM cte
WHERE XMLContent.value('(/IDMSDocument/DocumentContent/Attribute[5]/Value/Value)[1]', 'nvarchar(max)') like '%search%'
One thing though: I saw Unicode (Russian?) characters in the Content column. It may be better to use utf-16 in your XML and ntext for column type.
text and ntext are also on the way out. If this is new code, use nvarchar(max)

Oracle 10 xmltype extract where clause

I'm trying to extract a given set of values from an xmlfield blob data type.
The Xml structure looks like
<?xml version="1.0" encoding="UTF-8"?>
<ItemParameters type="**XYZ" version="000000000">
<Attribute name="Item ID" elementaryType="Numeric">
<Value value="12"></Value>
</Attribute>
<Attribute name="A" elementaryType="B">
<Value value="50"></Value>
</Attribute>
</ItemParameters>
<Scales>
</Scales>
where I'd like to check if attribute name = A and elementryType = B and extract the value beneeth in this case 50.
I tried doing like
select xmltype (dynamic_data).EXTRACT ('//ItemParameters/Attribute/Value()').getVal ()
Which is not working