[英]Edit XML with SQL query SQL Server 2008 R2
我有以下問題,希望有人可以提供幫助。
我有一個具有數千行的SQL Server數據庫。 每行包括一個具有ID的列和一個具有XML數據的列。
此XML數據如下所示:
<record id="1">
<field tag="aa" occ="1" lang="nl-NL" invariant="false">Jan</field>
<field tag="aa" occ="1" lang="en-US" invariant="false">John</field>
<field tag="aa" occ="1" lang="de-DE" invariant="false">der Jan</field>
<field tag="aa" occ="2" lang="nl-NL" invariant="false">Jan2</field>
<field tag="aa" occ="2" lang="en-US" invariant="false">John2</field>
<field tag="ab" occ="1">Something</field>
<field tag="ac" occ="1" lang="de-DE" invariant="false">Rechnung</field>
<field tag="ac" occ="1" lang="nl-NL" invariant="false">rekening</field>
<field tag="ad" occ="1">Something2</field>
<field tag="ae" occ="1" lang="nl-NL" invariant="false">stoeptegel</field>
</record>
我想根據以下規則為每個記錄編輯此XML:
運行1個或多個SQL查詢后,代碼應如下所示:
<record id="1">
<field tag="aa" occ="1" lang="nl-NL" invariant="false">Jan</field>
<field tag="aa" occ="1" lang="en-US" invariant="true">John</field>
<field tag="aa" occ="1" lang="de-DE" invariant="false">der Jan</field>
<field tag="aa" occ="2" lang="nl-NL" invariant="false">Jan2</field>
<field tag="aa" occ="2" lang="en-US" invariant="true">John2</field>
<field tag="ab" occ="1">Something</field>
<field tag="ac" occ="1" lang="de-DE" invariant="false">Rechnung</field>
<field tag="ac" occ="1" lang="nl-NL" invariant="true">rekening</field>
<field tag="ad" occ="1">Something2</field>
<field tag="ae" occ="1" lang="nl-NL" invariant="true">stoeptegel</field>
</record>
我的問題是根據上述規則創建正確的SQL查詢,以替換所有記錄的所有節點。
到目前為止,我想到了這個:
while exists
(
select *
from databasetable
where xmlcolumn.exist('/record/field/@invariant[.="false"]') = 1
)
update databasetable
set xmlcolumn.modify
('replace value of (/record/field/@invariant[.="false"])[1] with "true"')
它將@invariant的每個值編輯為'true'。
有人可以幫我建立正確的查詢嗎? 提前致謝!
切碎您的XML,並使用帶有order by子句的row_number()
,該子句首先對en-US
進行排序,然后對nl-NL
進行排序。
使用第二個row_number()
為每一行(ID和RowNumber)生成一個唯一鍵。
將值存儲在表變量中。
獲取最大行號,並為每個行號更新XML ia循環。
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
在這里可以找到工作樣本。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.