How to display XML column data - sql

I have a table column consist with the XML files. I want to read XML data and display it.
I come up with the following code. But it read only one row in the column
want to display other XML data also
declare #xml xml
select #xml = event_data_XML from #temp
SELECT * FROM (
SELECT
CAST(f.x.query('data(#name)') as varchar(150)) as data_name,
CAST(f.x.query('data(value)') as varchar(150)) as data_value
FROM #xml.nodes('/event') as t(n)
CROSS APPLY t.n.nodes('data') as f(x)) X
PIVOT (MAX(data_value) FOR data_name IN (NTDomainName, DatabaseName, ServerName)) as pvt
Output should be like this(NTDomainName, DatabaseName, ServerName are xml data)

There are a bunch of ways you could do this. I'll show you a way I think you'd find easiest.
To start, here's a table with a little test data:
CREATE TABLE dbo.stuff (
id int identity (1,1) primary key
, event_data_xml xml
, create_date datetime default(getdate())
, is_active bit default(1)
);
INSERT INTO dbo.stuff (event_data_xml)
VALUES ('<event name="thing" package="as">something</event>')
INSERT INTO dbo.stuff (event_data_xml)
VALUES ('<event name="otherthing" package="as">something else</event>')
---All records
SELECT * FROM dbo.[stuff];
Make sense so far? Here's the query I'd use if I wanted to mix XML data and column data:
---Parsed up
SELECT event_data_xml.value('/event[1]', 'nvarchar(max)') AS [parsed element #text]
, event_data_xml.value('/event[1]/#name', 'nvarchar(max)') AS [parsed attribute value]
, create_date --column from table
FROM dbo.stuff
WHERE is_active = 1;
Using the value() function on the XML column passing in an xpath to what I want to display and SQL Server data type for how I want it returned.
Just make sure you're selecting a single value with your xpath expression.

Related

Incorrect Results in my SQL select Query when parsing XML text column

Hi all I have a table that holds my business Id's and it is varchar(255) data type
I also have a separate table that stores an XML structured document in a text data type column when the business gets approved by a lender (it stores the companys information etc).
I am trying to return all business ID's that are NOT approved by a lender, the only way i can know this is if the business ID does not exist in the XML.
I cannot join on any tables as i do not have any relational data, but i am trying to subquery it.
Any ideas? here is what i have
Select bus_id
From dbo.tbl_business
Where bus_id Not In (
Select Cast(company_xml_info As Varchar(Max))
From tbl_company_reports
Where Cast(company_xml_info As Varchar(Max)) Is Not Null
And company_xml_info Like '%Business id="' + bus_id + '"%'
And company_xml_info Is Not Null
And company_xml_current_status = 'Approved'
)
Here is an example mark of something similar you can do. This should run fine in SQL Management Studio 2008 and up:
DECLARE #Data TABLE (BusinessId VARCHAR(8))
INSERT INTO #Data (BusinessId) VALUES ('A68'),('A69'),('A70');
DECLARE #CompanyXml TABLE (company_xml_info VARCHAR(MAX));
INSERT INTO #CompanyXml (company_xml_info ) VALUES ('<CompanyInfo>
<Businesses>
<Business id="A68">
<Businessceo>Test</Businessceo>
</Business>
</Businesses>
</CompanyInfo>')
,('<CompanyInfo>
<Businesses>
<Business id="A70">
<Businessceo>Test2</Businessceo>
</Business>
</Businesses>
</CompanyInfo>')
--Data as is
Select *
From #Data
--example of your code as is
SELECT *
From #CompanyXml
--exclusionary listing
SELECT *
From #Data
EXCEPT
--the secret of this is part 1 casting it to xml. Then you extend that with '.value'. That wants a structure to get to the Id.
--I wrap that in ()'s then say the first instance of that [1] as in theory you could have more instances and do very complex parsing.
--Then it needs a type of sql to transform this value into
SELECT CAST(company_xml_info AS XML).value('(CompanyInfo/Businesses/Business/#id)[1]', 'varchar(8)')
From #CompanyXml
Update 6-29-17
If you have something that has repeat elements in a tree structure of your XML, I prefer the 'nodes' method of repeating them and then you do not have to worry about using a first. You merely need to iterate through what you have from the use of the 'nodes' syntax and get a value like so
DECLARE #X XML = '<CompanyInfo><Businesses><Business id="C1405"/><Business id="C1408"/><Business id="C1408"/></Businesses> </CompanyInfo>'
SELECT
x.query('.')
, x.value('#id', 'varchar(8)')
FROM #X.nodes('/CompanyInfo/Businesses/Business') AS y(x)

How can I write a query in SQL Server on XML column

table tbl_event_log
columnName DataType
id Int
event XML
userinfo XML
and data should be in event is
<Event><Player readName="9.Make You Talk!" demoName="Video Game" **portal="FB"** totalDuration="0:07/0:07(100%)" /></Event>
and i want to write query to get data from portal="FB"
Use nodes() method to split your rows and then get values:
Check this solution and hope it helps you:
Declare #mytable table (id int,event xml,userinfo varchar(200))
Insert into #mytable
select 1, '<Event><Player readName="9.Make You Talk!" demoName="Video Game" portal="FB" totalDuration="0:07/0:07(100%)" /></Event>','Test'
Union
select 2, '<Event><Player readName="9.Make You Talk!" demoName="Video Game" portal="TW" totalDuration="0:07/0:07(100%)" /></Event>','Test'
select
s.id,
e.p.value('#portal', 'varchar(max)') as portal
from #mytable as s
outer apply s.event.nodes('Event/Player') as e(p)
select * from (
select
s.id,
e.p.value('#portal', 'varchar(max)') as portal
from #mytable as s
outer apply s.event.nodes('Event/Player') as e(p)
) Test
where Test.portal = 'FB'
Attn: Replace #mytable with your table name.
Note: Event column in your table must be XML datatype.
To get the data into specific fields you could extract them directly from the xml.
For example:
select id, userinfo,
event.value('/Event[1]/Player[#portal="FB"][1]/#readName','varchar(max)') as readNameFB,
event.value('/Event[1]/Player[#portal="FB"][1]/#demoName','varchar(max)') as demoNameFB,
event.value('/Event[1]/Player[#portal="FB"][1]/#totalDuration','varchar(30)') as totalDurationFB
from tbl_event_log;
[#portal="FB"] : only get the Player tags where the portal="FB"
[1] : use the first one

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()

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.