I have an XML field that I know will have at least one "ChildNode" in it, but possibly more. I am trying to make a loop in T-SQL that will get the XML of each ChildNode as a VarChar(1000) and do some logic with it. When I try the following...
...
SET @intIterator=1
SET @strValue = (SELECT XMLField.value('(/RootNode/ParentNode/ChildNode)[' + CAST(@intIterator AS VARCHAR(2)) + ']', VARCHAR(1000)) WHERE PrimaryKeyField=@intID)
WHILE LEN(@strValue) > 0
BEGIN
--LOGIC with @strValue not shown.
@intIterator = @intIterator + 1
@strValue = (SELECT XMLField.value('(/RootNode/ParentNode/ChildNode)[' + CAST(@intIterator AS VARCHAR(2)) + ']', VARCHAR(1000)) WHERE PrimaryKeyField=@intID)
END
I get the following error: The argument 1 of the xml data type method "value" must be a string literal.
I know that it's blowing up when I try to use the @intIterator in the value method as it wants a string literal instead of a variable, but then how can I iterate through the child nodes one by one in T-SQL?
You can retrieve multiple values from the rowset. For example, you can apply the value() method to the rowset returned by nodes() and retrieve multiple values from the original XML instance. The value() method, when applied to the XML instance, returns only one value.
You should use the query() Method if you want to get a part of your XML. If you want the value from a specific node you should use value() Method. Update: If you want to shred your XML to multiple rows you use nodes() Method.
XQuery in the SQL Server helps to query and extract data from XML documents. XQuery gives different approaches to get information from the XML document and the equivalent can be used on applying a data filter or where clause on XML elements as well.
You can optionally retrieve formal results of a SQL query as XML by specifying the FOR XML clause in the query. The FOR XML clause can be used in top-level queries and in subqueries. The top-level FOR XML clause can be used only in the SELECT statement.
There still could be a need to query sub elements which the answer to this question would not solve. You can just use sql:variable to satisfy nodes() requirement of a string literal argument to query sub elements of a specific node iteratively.
DECLARE @iterator = 1
SELECT
Child.value('(SomeElement)[1]', 'int'),
Child.value('(SomeOtherElement)[1]', 'Varchar(50)'),
FROM
XMLField.nodes("/RootNode/ParentNode[sql:variable("@iterator")]/ChildNode") AS N(Child)
I don't have any idea what your XML looks like, but you probably have to use a different approach - don't try to iterate and loop and stuff like that - instead use the .nodes()
function in XQuery:
SELECT
Child.value('(SomeElement)[1]', 'int'),
Child.value('(SomeOtherElement)[1]', 'Varchar(50)')
FROM
XMLField.nodes("/RootNode/ParentNode/ChildNode") AS N(Child)
That basically leaves the iterating / looping to XQuery and you don't have to mess around with indices or anything like that at all.....
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With