#xml #sql-server-2005 #xml-dml
#xml #sql-server-2005 #xml-dml
Вопрос:
Если вы запустите этот скрипт в SQL Server 2005:
create table #xmltemp
(
id int,
data xml null
)
insert into #xmltemp
select 1, ''
update #xmltemp
set data.modify('insert <a id="1" /> into /')
update #xmltemp
set data.modify('insert <a id="2" /> into /')
update #xmltemp
set data.modify('insert <a id="3" /> into /')
update #xmltemp
set data.modify('insert <a id="4" /> into /')
select * from #xmltemp
update x
set data.modify('delete //a[@id=sql:column("t.xmlid")]')
from #xmltemp x
inner join (
select 1 as id, 1 as xmlid union
select 1 as id, 2 as xmlid union
select 1 as id, 3 as xmlid
) t on t.id = x.id
select * from #xmltemp
drop table #xmltemp
Вы получите следующий вывод:
id data
1 <a id="1" /><a id="2" /><a id="3" /><a id="4" />
id data
1 <a id="2" /><a id="3" /><a id="4" />
Я бы ожидал, что он удалит все три узла, а не только первый, что приведет к возвращению второго select:
id data
1 <a id="4" />
Есть ли способ удалить несколько узлов в одном запросе? В частности, я хочу удалить все узлы, соответствующие критериям, из столбца в другой таблице (в этом примере t создается «на лету», но с таким же успехом это могла быть реальная таблица).
Ответ №1:
Вы можете превратить xmlid из объединенного запроса в строку, разделенную запятыми, и использовать эту строку в предикате.
create table #IdToDelete(id int, xmlid int)
insert into #IdToDelete values (1, 1)
insert into #IdToDelete values (1, 2)
insert into #IdToDelete values (1, 3)
insert into #IdToDelete values (2, 4)
update x
set data.modify('delete //a[contains(sql:column("t.xmlid"), @id)]')
from #xmltemp x
inner join (
select D1.id,
(select ',' cast(D2.xmlid as varchar(10))
from #IdToDelete as D2
where D1.id = D2.id
for xml path('')) as xmlid
from #IdToDelete as D1
group by D1.id
) t on t.id = x.id
Комментарии:
1. Спасибо, это довольно близко к тому, что я в итоге сделал. Я только что перестроил xml, используя «для xml explicit» в подзапросе.