views:

433

answers:

2

In an table I have the following.

ParameterID (int)    ParameterValue (XML)
------------    --------------
1               <USER><User ID="1" Name="Billy"/><USER>
                <USER><User ID="2" Name="Billy"/><USER>
                <MANAGER><User ID="1" Name="Billy"/><MANAGER>
2               <USER><User ID="1" Name="John"/><USER>
                <USER><User ID="2" Name="Billy"/><USER>
                <MANAGER><User ID="1" Name="Billy"/><MANAGER>
3               <USER><User ID="1" Name="David"/><USER>
                <USER><User ID="2" Name="Billy"/><USER>
                <MANAGER><User ID="1" Name="Billy"/><MANAGER>

How do I modify all instances of Billy to be Peter?

I tried

-- Update the table         
UPDATE  @tbXML
SET     ParameterValue.modify('replace value of (//User/@Name[.="Billy"])[1] with "Peter"')

But only the first Billy in the row was updated.

Running the update multiple times:

For Row 1: 
1st Time = 1 <USER><User ID="1" Name="Peter"/><USER> <USER><User ID="2" Name="Billy"/><USER> <MANAGER><User ID="1" Name="Billy"/><MANAGER> 

2nd Time 1 <USER><User ID="1" Name="Peter"/><USER> <USER><User ID="2" Name="Peter"/><USER> <MANAGER><User ID="1" Name="Billy"/><MANAGER> 

3rd Time 1 <USER><User ID="1" Name="Peter"/><USER> <USER><User ID="2" Name="Peter"/><USER> <MANAGER><User ID="1" Name="Peter"/><MANAGER>
A: 

The "simple" approach would be to cast the XML column to VARCHAR(MAX) and just simply do a REPLACE on it:

UPDATE
  YourTable
SET
  ParameterValue = CAST(REPLACE(CAST(ParameterValue AS VARCHAR(MAX)), '
                                Billy', 'Peter') AS XML)
WHERE
  ....

It almost seems like you cannot do an update of multiple XML node values in a single UPDATE statement, as Richard Szalay explains here:

Unfortunately, it appears that the implementation is horribly limited in that it cannot make an arbitrary number of modifications to the same value in a single update.

So I guess you'll either have to use the "dumb" VARCHAR(MAX) approach mentioned above, or do the update in a loop (WHILE you still find a node with "billy", UPDATE that node to read "Peter" instead).

Marc

marc_s
I was hoping to use the XQuery approach incase we add further attributes to the XML, if I had something like <User><User Name="Billy" NickName="Billy"/></User> then i might not want to rename the nickname attribute.
Gribbler
I'm trying to figure that out - what if you run your update statement multiple times? Does it update the rows one by one?
marc_s
For Row 1:1st Time = 1 <USER><User ID="1" Name="Peter"/><USER> <USER><User ID="2" Name="Billy"/><USER> <MANAGER><User ID="1" Name="Billy"/><MANAGER>2nd Time1 <USER><User ID="1" Name="Peter"/><USER> <USER><User ID="2" Name="Peter"/><USER> <MANAGER><User ID="1" Name="Billy"/><MANAGER>3rd Time1 <USER><User ID="1" Name="Peter"/><USER> <USER><User ID="2" Name="Peter"/><USER> <MANAGER><User ID="1" Name="Peter"/><MANAGER>
Gribbler
Sorry about the formatting
Gribbler
So running the update multiple times also solves the problem - not perfect and not very slick and neat, but it works, right?
marc_s
Yeah it works, I'll have to use that somehow.. grr!Thanks for the suggestion!
Gribbler
A: 

I ended up using a cursor to do the update

Used the update in marcs answer in the cursor in a while loop

Gribbler