Reputation: 393
Is it possible to write a WHERE clause to select values from XML based on the value of a child node?
Example XML
<Message>
<PrimaryKeyValue>12345</PrimaryKeyValue>
<Events>
<UpdatedDefaultAddress>True</UpdatedDefaultAddress>
<UpdatedCustomerName>False</UpdatedCustomerName>
</Events>
</Message>
<Message>
<PrimaryKeyValue>67890</PrimaryKeyValue>
<Events>
<UpdatedDefaultAddress>False</UpdatedDefaultAddress>
<UpdatedCustomerName>True</UpdatedCustomerName>
</Events>
</Message>
My Question
How would I construct a query to only select PrimaryKeyValues where the value of <UpdatedDefaultAddress>
is 'True'?
My current code
SELECT
t.c.value('(PrimaryKeyValue)[1]', 'varchar(100)') AS PrimaryKeyValue
FROM @message_body.nodes('Message') as T(C)
WHERE t.c.exist('./Events/UpdateDefaultAddress') = 'True'
The problem with this is that I get both PrimaryKeyValues back in the result - I think the code is checking whether <UpdatedDefaultAddress>
exists, rather than the value contained within it?
Upvotes: 2
Views: 1525
Reputation: 175586
Use .value()
instead of .exists()
DECLARE @message_body XML =N'<Message>
<PrimaryKeyValue>12345</PrimaryKeyValue>
<Events>
<UpdatedDefaultAddress>True</UpdatedDefaultAddress>
<UpdatedCustomerName>False</UpdatedCustomerName>
</Events>
</Message>
<Message>
<PrimaryKeyValue>67890</PrimaryKeyValue>
<Events>
<UpdatedDefaultAddress>False</UpdatedDefaultAddress>
<UpdatedCustomerName>True</UpdatedCustomerName>
</Events>
</Message>';
SELECT t.c.value('(PrimaryKeyValue)[1]', 'varchar(100)') AS PrimaryKeyValue
FROM @message_body.nodes('Message') as T(C)
WHERE t.c.value('(./Events/UpdatedDefaultAddress)[1]', 'varchar(10)')='True';
Upvotes: 3