I have some data stored in an SQL Server XML data column in a table. It's used to configure HTML content (to be sent as emails) and works fine. However, I would now like to change some of the data, but I can't seem to find the correct incantation to effect just the bits I want.
Take the following as an example.
declare @s1 varchar(max);
declare @s2 varchar(max);
declare @s3 varchar(max);
-- rough approximation of my data
set @s1 = '<email sender="bob"><html><body><table><tbody><tr><td><b>'
set @s2 = '</b></td></tr><tr><td><b>'
set @s3 = '</b></td></tr></tbody></table></body></html></email>'
declare @t table (id int, data xml)
insert into @t values (1, @s1 + 'Hello World' + @s2 + 'Goodbye cruel world' + @s3)
insert into @t values (2, @s1 + 'Hello World' + @s2 + 'I''m leaving you today' + @s3)
insert into @t values (3, @s1 + 'Hello World' + @s2 + 'Goodbye, goodbye, goodbye' + @s3)
select data from @t
update @t -- change sender to "fred"
set data.modify('replace value of (/email/@sender)[1] with "fred"')
select data from @t
select data,x.nd.value('b[1]','varchar(max)') -- find the "hello world" bits
from @t
cross apply data.nodes('email/html/body/table/tbody/tr/td') as x(nd)
where x.nd.value('b[1]','varchar(max)') = 'Hello World'
I want to change the "sender" data (which I think I've worked out), and the "Hello World" data - which I can find, but I don't know how to change. I'm not really sure what's going on with the "cross apply" syntax either, and guess that I could write the XPath stuff to only find the "Hello World" nodes without the "where" clause ?
My table only has about 9 rows in it, so I could write nine update commands if needed and this is a one-off data maintenance task.
Any help would be appreciated.
Edit:
Is this the way its done ?
update @t
set data.modify('replace value of (email/html/body/table/tbody/tr/td/b/text())[1] with "bonjour monde"')
from @t
cross apply data.nodes('email/html/body/table/tbody/tr/td') as x(nd)
where x.nd.value('b[1]','varchar(max)') = 'Hello World'
Thanks.