11

I've come across a problem with modifying XML within SQL Server that doesn't seem to make sense to me. I want to update the value of an empty node, but it doesn't seem to be working. For instance, say I have this XML tree:

<root>
    <node />
</root>

and I want to update the value of <node /> with 'foo' so I have the XML query:

UPDATE  [Table]
SET     [XmlColumn].modify('
        replace value of (root/node/text())[1]
        with "foo"')

For some reason, this doesn't work. It treats the node like it doesn't exist. If the node already has a value (e.g., <node>bar</node>), it works just fine, but when the node is empty, it silently ignores the command, without even throwing any errors. Is there a way to make SQL Server acknowledge a replace value of on an empty node?

EDIT:

I want the end result of this query to be this:

<root>
    <node>
        foo
    </node>
</root>
2
  • 1
    possible duplicate of Update XML field with no text in T-SQL Commented Jun 20, 2011 at 20:31
  • 1
    Awesome, Mikael. This solution seems way cleaner than the one pointed to by Andrey. Thanks a lot! Commented Jun 20, 2011 at 20:44

3 Answers 3

9
UPDATE  [Table] 
SET     [XmlColumn].modify(' insert text{"foo"} into (/root/node)[1]') 

Try out this work for me

Sign up to request clarification or add additional context in comments.

3 Comments

What about if instead of "foo" I want a variable? stackoverflow.com/questions/32253235/…
In this case you can use: ' insert text{sql:variable("@variableName")} into (/root/node)[1]'
This should be marked as the answer. I had the same issue as the OP and my addressing was fine (no missing slashes, etc.) -- this is what actually worked for an empty node; 'replace value' did NOT. Thank you @jaspreet !
2

Will this be of any help: http://whyiamright.wordpress.com/2008/01/02/updating-xml-column-in-sql-server-2005/?

You seem to miss slash in the begining of xpath.

EDIT: Then it seems to be a duplicate of this question:

Update Empty XML Tag in SQL Server

3 Comments

The leading slash only makes the path absolute. Without it, the XPath will match any node whose path ends with root/node. Since there aren't any other nodes in the tree, in this instance, the leading slash makes no difference.
not sure why this is the accepted answer; as @Chris mentioned above, the leading slash makes no difference in this scenario
0

Necromancing.
Providing an actual answer:

You cannot do this in one pass.
You first need to set the value to empty (replace if it exists), and then insert it:

SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/text())[1] with ""')
SET @tXML.modify('insert text{"This Works"} into (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])[1]')

example XML used:

DECLARE @tXML xml = '<svg>
<g>
<path></path>
<path data-objid="0000X1">tt</path>
<path data-objid="0000X2"></path>
<path data-objid="0000X3"></path>
</g>
</svg>';

Same goes for attributes.
There you need to insert the attribute first, but you need to check with [not(@data-objid)] if the attribute already exists. Once it has been inserted where it's needed, you can modify the values.

SET @tXML.modify('insert attribute data-objid {"1"} into (//path[not(@data-objid) and contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])[1]')
SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/@data-objid)[1] with "Test"')

Thus you created the attribute (with a dummy value) where the attribute didn't exist, and then you updated it where it already exists, which means all the values have been updated now, including the dummy values.

Since modify/insert can only operate on a single record, you cannot bulk-update/insert anyway.
Interestingly, contrary to expectations, you can bulk delete... Not very consequent... I presume somebody ran out of time to implement this when shipping that crap.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.