Reputation: 828
I have a SQL query that currently gets the value that is stored in a column in my database like this:
SELECT
@filevalue = (CAST(REPLACE(CAST(de.TRIGGERS_XML_DATA AS VARCHAR(MAX)), 'encoding="utf-16"', '') AS XML).value('(//value)[1]', 'NVARCHAR(max)')),
@filecontent = de.ENVIRONMENT_ID
FROM
dbo.DEPLOYMENT_ENVIRONMENT AS de
WHERE
de.ENVIRONMENT_ID = CAST(REPLACE(CAST(@filevalue AS numeric(19, 0)), 'encoding="uft-16"', '') AS numeric(19, 0))
The part where it is .value('(//value)[1]')
is the problem because sometimes there will be multiple value nodes. I tried to concatenate a counter and the value node together but this came back with the error the value needs to be a string not a varchar when I did this: .value(@ValueNodes, 'NVARCHAR(max)'))
So how can I successfully loop through the xml to get my result? The problem with the way I was doing it is that the first value is not always what I need and will give errors (null values and unable to cast types).
Upvotes: 1
Views: 1233
Reputation: 67311
You can use a deep search XPath
, which will find all <value>
-nodes wherever they are. You do this with a double //
at the beginning. The following will extract all text()
within each <value>
together with the parent node name:
DECLARE @xml XML=
N'<root>
<value>test1</value>
<SomeParent>
<value>test in parent</value>
<value>one more in parent</value>
</SomeParent>
<value>One more on first level</value>
</root>';
SELECT val.value(N'(./text())[1]','nvarchar(max)') AS TheValueInValue
,val.value(N'local-name(..)','nvarchar(max)') AS ParentNode
FROM @xml.nodes(N'//value') AS Each(val)
The result
TheValueInValue ParentNode
test1 root
test in parent SomeParent
one more in parent SomeParent
One more on first level root
...as I am getting the xml from a column
This is a blind flight, but you might need something like this:
WITH Casted AS
(
SELECT
TheXML = CAST(REPLACE(CAST(de.TRIGGERS_XML_DATA AS VARCHAR(MAX)), 'encoding="utf-16"', '') AS XML)
,de.ENVIRONMENT_ID
FROM
dbo.DEPLOYMENT_ENVIRONMENT AS de
)
SELECT Casted.ENVIRONMENT_ID
,val.value(N'(./text())[1]','nvarchar(max)') AS TheValueInValue
,val.value(N'local-name(..)','nvarchar(max)') AS ParentNode
FROM Casted
CROSS APPLY TheXML.nodes(N'//value') AS Each(val)
Upvotes: 1