1

How can I change:

<data>
  <row>
    <a>A</a>
    <a>B</a>
    <a>C</a>
  </row>
</data>

to:

<data>
  <row>
    <a>Data A</a>
    <a>Data B</a>
    <a>Data C</a>
  </row>
</data>

in SQL? I've seen lots of examples on how to completely replace a value with a static value, but no examples of replacing the value dynamically.

3 Answers 3

3

I do not know if it is possible to use the xml in the replace value of statement. But you can do this.

declare @xml xml = '
<data>
  <row>
    <a>A</a>
    <a>B</a>
    <a>C</a>
  </row>
</data>'

declare @Val1 varchar(10) 
declare @Val2 varchar(10) 
declare @Val3 varchar(10) 

select 
  @Val1 = 'Data '+r.value('a[1]', 'varchar(1)'), 
  @Val2 = 'Data '+r.value('a[2]', 'varchar(1)'), 
  @Val3 = 'Data '+r.value('a[3]', 'varchar(1)') 
from @xml.nodes('/data/row') n(r)

set @xml.modify('replace value of (/data/row/a/text())[1] with (sql:variable("@val1"))')
set @xml.modify('replace value of (/data/row/a/text())[2] with (sql:variable("@val2"))')
set @xml.modify('replace value of (/data/row/a/text())[3] with (sql:variable("@val3"))')

Version 2

declare @xml xml = '
<data>
  <row>
    <a>A</a>
    <a>B</a>
    <a>C</a>
  </row>
  <row>
    <a>1</a>
    <a>2</a>
    <a>3</a>
  </row>
</data>'

;with cte as
(
  select
    r.query('.') as Row,
    row_number() over(order by (select 0)) as rn
  from @xml.nodes('/data/row') n(r)
)
select
  (select 
     'Data '+a.value('.', 'varchar(1)')
   from cte as c2
     cross apply Row.nodes('row/a') as r(a)
   where c1.rn = c2.rn
   for xml path('a'), root('row'), type)  
from cte as c1 
group by rn
for xml path(''), root('data')
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Mikael. I've seen that solution on other sites, but it's not dynamic. What if I have 1000 "row" tags with 1-100 "a" tags each?
1

I had the same problem, but I found another solution I think ;)

for $n in /data/row
 return replace value of node $n with concat('Data',$n/text())

Sincerely

Comments

0

Here is another less-than-ideal way to go about it.

SET @temp.modify('replace value of (/data/row/node()/text())[1] with concat("Data ", (/data/row/node()/text())[1])')
SET @temp.modify('replace value of (/data/row/node()/text())[2] with concat("Data ", (/data/row/node()/text())[2])')
SET @temp.modify('replace value of (/data/row/node()/text())[3] with concat("Data ", (/data/row/node()/text())[3])')

The disadvantage of this method is that you need to a separate statement for each child of row. This only works if you know in advance how many children the row node will have.

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.