views:

29

answers:

2

Hello,

I'm trying to query a particular value in an XML field. I've seen lots of examples, but they don't seem to be what I'm looking for

Supposing my xml field is called XMLAttributes and table TableName, and the complete xml value is like the below:

<Attribute name="First2Digits" value="12" />
<Attribute name="PurchaseXXXUniqueID" value="U4RV123456762MBE79" />

(although the xml field will frequently have other attributes, not just PurchaseXXXUniqueID)

If I'm looking for a specific value in the PurchaseXXXUniqueID attribute name - say U4RV123456762MBE79 - how would I write the query? I believe it would be something like:

select * 
  from TableName
 where XMLAttributes.value('(/path/to/tag)[1]', 'varchar(100)') = '5FTZP2QT8Z3E2MAV2D'

... but it's the path/to/tag that I need to figure out.

Or probably there's other ways of getting the values I want.

To summarize - I need to get all the records in a table where the value of a particular attribute in the xml field matches a value I'll pass to the query.

thanks for the help! Sylvia

edit: I was trying to make this simpler, but in case it makes a difference - ultimately I'll have a temporary table of 50 or so potential values for the PurchaseXXXUniqueID field. For these, I want to get all the matching records from the table with the XML field.

A: 

Something like that?

declare @PurchaseXXXUniqueID varchar(max)
set @PurchaseXXXUniqueID = 'U4RV123456762MBE79';

select * from TableName t
where XMLAttributes.exist('//Attribute/@value = sql:variable("@PurchaseXXXUniqueID")') = 1
Denis Valeev
Thanks for the response. I couldn't get something similar to this to run on sql 2005 - does this use 2008 specific syntax?
Sylvia
Well, the only difference is in the `declare` statement. Just separate the declaration part from the assignment part.
Denis Valeev
I did that, and it runs without errors...but it doesn't appear to actually filter out only the values I want. I get all the values.
Sylvia
+1  A: 

This ought to work:

SELECT 
    (fields from base table),
    Nodes.Attr.value('(@name)[1]', 'varchar(100)'),
    Nodes.Attr.value('(@value)[1]', 'varchar(100)')
FROM 
    dbo.TableName
CROSS APPLY
    XMLAttributes.nodes('/Attribute') AS Nodes(Attr)
WHERE
    Nodes.Attr.value('(@name)[1]', 'varchar(100)') = 'PurchaseXXXUniqueID'
    AND Nodes.Attr.value('(@value)[1]', 'varchar(100)') = 'U4RV123456762MBE79'

You basically need to join the base table's row against one "pseudo-row" for each of the <Attribute> nodes inside the XML column, and the pick out the individual attribute values from the <Attribute> node to select what you're looking for.

marc_s
This did it - thank you! It was very slow, though. Not that the slow performance is a problem with your query, it's just that this tables is not set up for XML queries. If I had a whole list of IDs that I want to find - would putting them in a temp table, and then joining them something like so:
Sylvia
on Nodes.Attr.value('(@value)[1]', 'varchar(100)') = #tempTable.UniqueID......
Sylvia
be the way to do it (sorry, the cr/lf ended up being new entries)
Sylvia