SQL Parse xml column data - sql

I have very little experience with SQL Server. Here is what I am trying to accomplish:
I have a table with many rows. Every row contains a column named "Config". The data stored in the Config column is of the xml type. The xml structure looks like this:
<root>
<path1>
<path2>
<path3>true</path3>
</path2>
</path1>
</root>
I am trying to go through every row in the table and find the percentage of true to false values of <path3>.
I looked at some SQL documentation and tried to use the value() function I am having difficulties extracting the XML data from the column:
select Config.value('(/root/path1/path2/path3)[1]','nvarchar(max)') from [MyDB].[dbo].[MyTable]
Here is the result of my query:
I would like to query and extract data from the XML "Config" column of my table and aggregate that data into columns.

You need to specify namespaces in the query when xml is built with namespaces. For example
CREATE TABLE tbl (Config xml);
INSERT INTO tbl (Config)
VALUES ('<root xmlns="abc">
<path1>
<path2>
<path3>true</path3>
</path2>
</path1>
</root>') ;
Then
with xmlnamespaces (DEFAULT 'abc')
select Config.value('(/root/path1/path2/path3)[1]','nvarchar(max)') path3Txt
from tbl;
or explicit specification
with xmlnamespaces ('abc' as x)
select Config.value('(/x:root/x:path1/x:path2/x:path3)[1]','nvarchar(max)') path3Txt
from tbl;

You would need to use CROSS APPLY. Check it out.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY, [Config] XML);
INSERT INTO #tbl
VALUES (N'<root>
<path1>
<path2>
<path3>true</path3>
</path2>
</path1>
</root>')
, (N'<root>
<path1>
<path2>
<path3>false</path3>
</path2>
</path1>
</root>');
-- DDL and sample data population, end
;WITH rs AS
(
SELECT ID
, col.value('(./text())[1]','VARCHAR(20)') AS Result
FROM #tbl tbl
CROSS APPLY tbl.[Config].nodes('/root/path1/path2/path3') AS tab(col)
)
SELECT * FROM rs;

Related

Xquery to return rows with restricted nodes

I have a table where a column contains XML data. Now i want to retrieve those xml data with restriction of nodes. Kindly see the following example for more explanation on my scenario,
declare #table table (id int, xmlfield xml) insert into #table select 1,'<Root xmlns="">
<Sample>
<Issue>
<Level>one</Level>
<Descp>First Example</Descp>
</Issue>
<Issue>
<Level>two</Level>
<Descp>Second Example</Descp>
</Issue>
</Sample> </Root>'
select * from #table
Now i need the following result set
Id XMLfield
1 first example
ie, for the selected level,i need the decription for it. More clearly, the node should be restricted for <level>one</level>
(need: What is the description for level one ?)
thanks in advance
Have a look at the xml Data Type Methods
select id,
xmlfield.value('(//Issue[Level = "one"]/Descp/text())[1]', 'varchar(100)') as XMLField
from #table
The XQuery you're looking for is
//Issue[Level = "one"]/Descp/data()

How to read column values from xmlstring using forxml clause

In our database table, columns are stored as an xml string, which is shown below.
<DocumentElement>
<PartInfo>
<ID>0</ID>
<PartNo>0</PartNo>
<SerialNo>1</SerialNo>
<Parameter>0</Parameter>
<InstalledDate>2013-01-15T00:00:00+05:30</InstalledDate>
<InstalledTill>2013-01-25T00:00:00+05:30</InstalledTill>
</PartInfo>
</DocumentElement>
I want to get column values of this string. For example I have to get the value 2013-01-15T00:00:00+05 of Installed Date column. How can I obtain this using forxml clause?
Assuming SQL-Server you can use something like this:
DECLARE #T TABLE (X XML);
INSERT #T VALUES ('<DocumentElement>
<PartInfo>
<ID>0</ID>
<PartNo>0</PartNo>
<SerialNo>1</SerialNo>
<Parameter>0</Parameter>
<InstalledDate>2013-01-15T00:00:00+05:30</InstalledDate>
<InstalledTill>2013-01-25T00:00:00+05:30</InstalledTill>
</PartInfo>
</DocumentElement>');
SELECT InstalledDate = X.value('/DocumentElement[1]/PartInfo[1]/InstalledDate[1]', 'DATETIME')
FROM #T;
If you could have multiple PartInfo nodes within DocumentElement then you'll need to use CROSS APPLY .. nodes to get all the InstalledDates
SELECT InstalledDate = PartInfo.value('InstalledDate[1]', 'DATETIME')
FROM #T
CROSS APPLY X.nodes('/DocumentElement/PartInfo') p (PartInfo);

Select SQL Query to get xml node values from ntext column?

I want to get one xml node value from NTEXT column which contains xml based on where clause quering on another xml node value.
RDBMS Type: Microsoft SQL Server T-SQL
Here: I want to get Code node value based on StoreId where clause value. How do I get it?
Input: 100
Output:ABCDE
For example:
<root>
<StoreProfile>
<General>
<StoreId>100</StoreId>
<Code>ABCDE</Code>
</General>
</StoreProfile>
</root>
If you are using SQL Server 2005 or 2008 you can use XQuery like so:
For more on XQuery see XQuery Language Reference
DECLARE #storeId INT
SET #storeId = 100
CREATE TABLE #TestTable
(
xmlColumn NTEXT
)
INSERT INTO #TestTable (xmlColumn) Values('<root><StoreProfile><General><StoreId>100</StoreId><Code>ABCDE</Code></General></StoreProfile></root>')
INSERT INTO #TestTable (xmlColumn) Values('<root><StoreProfile><General><StoreId>200</StoreId><Code>FGHIJ</Code></General></StoreProfile></root>')
SELECT
StoreProfile.value('Code[1]', 'nvarchar(10)') as Code
FROM #TestTable
CROSS APPLY (SELECT CAST(xmlColumn AS XML)) AS A(B)
CROSS APPLY A.B.nodes('//root/StoreProfile/General[StoreId = sql:variable("#storeId")]') AS StoreProfiles(StoreProfile)
DROP TABLE #TestTable

selecting from sql

<suggestions>
<suggestion>
<description>plate.</description>
</suggestion>
<suggestion>
<description>snack.</description>
</suggestion>
</suggestions>
DECLARE #Suggestions TABLE (
[Description] VARCHAR(800)
)
I have above xml in a XML type varible in my stored procedure
how can i insert each text between description tags
in to the table #Suggestions
Try this:
DECLARE #input XML = '<suggestions>
<suggestion>
<description>plate.</description>
</suggestion>
<suggestion>
<description>snack.</description>
</suggestion>
</suggestions>'
DECLARE #Suggestions TABLE ([Description] VARCHAR(800))
INSERT INTO #Suggestions
SELECT
Sugg.value('(description)[1]', 'varchar(800)')
FROM
#input.nodes('/suggestions/suggestion') AS Tbl(Sugg)
SELECT * FROM #Suggestions
The #input.nodes() expression basically turns each <suggestion> node into a row in the "pseudo" table called Tbl(Sugg). From those "rows" (each basically another XML fragment), you then select out the value you're interested in - here the contents of the <description> XML element inside that XML fragment.
You can use LINQ-to-XML to get all suggestions, then you can insert that data into the table.

how to get values inside an xml column, when it's of type nvarchar

My question is similar to this one: Choose a XML node in SQL Server based on max value of a child element
except that my column is NOT of type XML, it's of type nvarchar(max).
I want to extract the XML node values from a column that looks like this:
<Data>
<el1>1234</el1>
<el2>Something</el2>
</Data>
How can I extract the values '1234' and 'Something' ?
doing a convert and using the col.nodes is not working.
CONVERT(XML, table1.col1).value('(/Data/el1)[1]','int') as 'xcol1',
After that, I would like to do a compare value of el1 (1234) with another column, and update update el1 as is. Right now I'm trying to just rebuild the XML when passing the update:
ie
Update table set col1 ='<Data><el1>'+#col2+'</el1><el2>???</el2>
You've got to tell SQL Server the number of the node you're after, like:
(/Data/el1)[1]
^^^
Full example:
declare #t table (id int, col1 varchar(max))
insert #t values (1, '<Data><el1>1234</el1><el2>Something</el2></Data>')
select CAST(col1 as xml).value('(/Data/el1)[1]', 'int')
from #t
-->
1234
SQL Server provides a modify function to change XML columns. But I think you can only use it on columns with the xml type. Here's an example:
declare #q table (id int, col1 xml)
insert #q values (1, '<Data><el1>1234</el1><el2>Something</el2></Data>')
update #q
set col1.modify('replace value of (/Data/el1/text())[1] with "5678"')
select *
from #q
-->
<Data><el1>5678</el1><el2>Something</el2></Data>
At the end of the day, SQL Server's XML support makes simple things very hard. If you value maintainability, you're better off processing XML on the client side.