Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update, find/replace for xml field

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>
  1. 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

  2. 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)

like image 947
Spooks Avatar asked May 15 '26 07:05

Spooks


1 Answers

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.

like image 198
Mikael Eriksson Avatar answered May 16 '26 21:05

Mikael Eriksson