Измельчите ваш XML и используйте row_number()
с предложением order by, которое упорядочивает en-US
первый и nl-NL
второй.
Используйте секунду row_number()
для генерации уникального ключа для каждой строки (ID и RowNumber).
Сохранить значения в табличной переменной.
Получить максимальный номер строки и обновить цикл ia XML для каждого номера строки.
declare @Tmp table
(
ID int, -- Primary key in databasetable
RowNumber int,
Tag varchar(2),
Occ int,
Lang varchar(5),
Invariant bit
primary key (ID, RowNumber)
);
with C1 as
(
select T.ID, -- Primary key in databasetable
R.F.value('@tag', 'varchar(2)') as Tag,
R.F.value('@occ', 'int') as Occ,
R.F.value('@lang', 'varchar(5)') as Lang
from databasetable as T
cross apply T.xmlcolumn.nodes('/record/field') as R(F)
),
C2 as
(
select ID, Tag, Occ, Lang,
row_number() over(partition by ID order by (select 0)) as RowNumber,
row_number() over(partition by ID, Tag, Occ
order by case Lang
when 'en-US' then 1
when 'nl-NL' then 2
else 3
end) as rnInv
from C1
)
insert into @Tmp (ID, RowNumber, Tag, Occ, Lang, Invariant)
select ID, RowNumber, Tag, Occ, Lang, case rnInv when 1 then 1 else 0 end
from C2;
declare @MaxRowNum int;
declare @I int = 1;
select @MaxRowNum = max(RowNumber)
from @Tmp;
while @I <= @MaxRowNum
begin
update T
set xmlcolumn.modify('replace value of (/record/field[@tag = sql:column("Tmp.Tag") and
@occ = sql:column("Tmp.Occ") and
@lang = sql:column("Tmp.Lang")]/@invariant)[1]
with sql:column("Tmp.Invariant")')
from databasetable as T
inner join @Tmp as Tmp
on T.ID = Tmp.ID
where Tmp.RowNumber = @I;
set @I += 1;
end
Рабочий образец можно найти здесь .