Select values from XML field in SQL Server 2008
Just looking at my XML field, my rows look like this:
<person><firstName>Jon</firstName><lastName>Johnson</lastName></person>
<person><firstName>Kathy</firstName><lastName>Carter</lastName></person>
<person><firstName>Bob</firstName><lastName>Burns</lastName></person>
Note that these are three rows in my table.
I'd like to return a SQL result as a table as in
Jon | Johnson
Kathy| Carter
Bob | Burns
What query will accomplish this?
Solution 1:
Given that the XML field is named 'xmlField'...
SELECT
[xmlField].value('(/person//firstName/node())[1]', 'nvarchar(max)') as FirstName,
[xmlField].value('(/person//lastName/node())[1]', 'nvarchar(max)') as LastName
FROM [myTable]
Solution 2:
Considering that XML data comes from a table 'table' and is stored in a column 'field': use the XML methods, extract values with xml.value()
, project nodes with xml.nodes()
, use CROSS APPLY
to join:
SELECT
p.value('(./firstName)[1]', 'VARCHAR(8000)') AS firstName,
p.value('(./lastName)[1]', 'VARCHAR(8000)') AS lastName
FROM table
CROSS APPLY field.nodes('/person') t(p)
You can ditch the nodes()
and cross apply
if each field contains exactly one element 'person'. If the XML is a variable you select FROM @variable.nodes(...)
and you don't need the cross apply
.
Solution 3:
This post was helpful to solve my problem which has a little different XML format... my XML contains a list of keys like the following example and I store the XML in the SourceKeys column in a table named DeleteBatch:
<k>1</k>
<k>2</k>
<k>3</k>
Create the table and populate it with some data:
CREATE TABLE dbo.DeleteBatch (
ExecutionKey INT PRIMARY KEY,
SourceKeys XML)
INSERT INTO dbo.DeleteBatch ( ExecutionKey, SourceKeys )
SELECT 1,
(CAST('<k>1</k><k>2</k><k>3</k>' AS XML))
INSERT INTO dbo.DeleteBatch ( ExecutionKey, SourceKeys )
SELECT 2,
(CAST('<k>100</k><k>101</k>' AS XML))
Here's my SQL to select the keys from the XML:
SELECT ExecutionKey, p.value('.', 'int') AS [Key]
FROM dbo.DeleteBatch
CROSS APPLY SourceKeys.nodes('/k') t(p)
Here's the query results...
ExecutionKey Key 1 1 1 2 1 3 2 100 2 101
Solution 4:
This may answer your question:
select cast(xmlField as xml) xmlField into tmp from (
select '<person><firstName>Jon</firstName><lastName>Johnson</lastName></person>' xmlField
union select '<person><firstName>Kathy</firstName><lastName>Carter</lastName></person>'
union select '<person><firstName>Bob</firstName><lastName>Burns</lastName></person>'
) tb
SELECT
xmlField.value('(person/firstName)[1]', 'nvarchar(max)') as FirstName
,xmlField.value('(person/lastName)[1]', 'nvarchar(max)') as LastName
FROM tmp
drop table tmp