views:

3905

answers:

2

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?

+2  A: 

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]
Larsenal
You must use .nodes() and cross apply if xmlField contains more than one <person> elements.
Remus Rusanu
+2  A: 

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.

Remus Rusanu
I wonder how efficient this method is and whether there's a better way. The CROSS APPLY combiend with XPath results seems like it might result in quite a resource hungry query.
locster
@thelocster: this is no different from ordinary data access. Techniques for improving XML performance are well documented. http://msdn.microsoft.com/en-us/library/ms345118%28SQL.90%29.aspx
Remus Rusanu