Как изменить значение узла, используя текущее значение узла в SQL с XQuery (SQL Server)
Как я могу изменить:
<data>
<row>
<a>A</a>
<a>B</a>
<a>C</a>
</row>
</data>
чтобы:
<data>
<row>
<a>Data A</a>
<a>Data B</a>
<a>Data C</a>
</row>
</data>
в SQL? Я видел много примеров того, как полностью заменить значение статическим значением, но не было примеров динамической замены значения.
3 ответа
Решение
Я не знаю, возможно ли использовать XML в replace value of
заявление. Но вы можете сделать это.
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"))')
Версия 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')
У меня была такая же проблема, но я нашел другое решение, я думаю;)
for $n in /data/row
return replace value of node $n with concat('Data',$n/text())
Искренне
Вот еще один не совсем идеальный способ сделать это.
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])')
Недостатком этого метода является то, что вам нужно отдельное утверждение для каждого дочернего элемента строки. Это работает, только если вы заранее знаете, сколько дочерних элементов будет иметь рядный узел.