I have a Page table in my database. Lets say for simplicity it has two columns; title and xmlData It has Title something like "my example " and I have a xml field that looks like:
<MA>
<A>
<URL>my-example-</URL>
<id>5</id>
</A>
</MA>
I am trying to do a find replace of any url that has "-" at the end, and remove the only the last trailing "-" if it exists
and remove the trailing space(if it has one, to title)
I am able to grab the rows that need to be changed by doing
select * from Pages
where title like '% '
(there is some joins and stuff, but that is basically it)
This will replace one occurrence of the URL for each row. By the look of your sample XML you have only one URL per row.
with C1 as
(
select xmlData,
xmlData.value('(/MA/A/URL/text())[1]', 'nvarchar(500)') as URL
from Pages
),
C2 as
(
select xmlData,
URL,
left(URL, len(URL) - 1) as URL2
from C1
where right(URL, 1) = '-'
)
update C2
set xmlData.modify('replace value of (/MA/A/URL/text())[1]
with sql:column("C2.URL2")')
Extract the URL value in CTE C1.
Remove the last '-' from the URL and put that in URL2 in CTE C2. Also remove the rows that does not need to be updated.
Update the XML using modify() Method (xml Data Type)
And here is another version that does the job in the XML part of the query instead.
update Pages
set xmlData.modify('replace value of (/MA/A/URL/text())[1]
with fn:substring((/MA/A/URL/text())[1], 1, fn:string-length((/MA/A/URL/text())[1])-1)')
where xmlData.exist('/MA/A/URL[fn:substring(text()[1], fn:string-length(text()[1]), 1) = "-"]') = 1
It is only possible to update one node at a time so if you have multiple URL's in in one row you have to put the code above in a loop and do the updates as long as there is something to update. You could use @@ROWCOUNT to check if the update did update anything and redo the update until @@ROWCOUNT = 0.
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