2012-04-09 61 views
2

我有包含XML,看起來像一個表中的列如下SQL Server 2008中的搜索和替換XML節點值

<memberHours type="TeamHours[]"> 
<item> 
    <member type="String">Bill</member> 
    <hours type="Decimal">0.0</hours> 
</item> 
<item> 
    <member type="String">John</member> 
    <hours type="Decimal">0.0</hours> 
</item> 
<item> 
    <member type="String">Sally</member> 
    <hours type="Decimal">0.0</hours> 
</item> 
</memberHours> 

我需要能夠找到所有行的其中一個成員都是相等到'John',然後用'Jon'替換'John'。由於我的xml存儲在nvarchar(max)列中,因此我正在編寫一個將列轉換爲可以隨後使用的xml變量的函數。我無法弄清楚是如何找到這些「項目」比賽和如何更換隻是一個值(即只是「約翰」)

我SQL服務器2008年

回答

3

看一看以下MSDN文章:

replace value of (XML DML)

具體來說,你可以嘗試這樣的事:

-- Setup test data 
declare @table table (
    col nvarchar(max) not null 
) 
insert into @table select 
'<memberHours type="TeamHours[]"> 
<item> 
    <member type="String">Bill</member> 
    <hours type="Decimal">0.0</hours> 
</item> 
<item> 
    <member type="String">John</member> 
    <hours type="Decimal">0.0</hours> 
</item> 
<item> 
    <member type="String">Sally</member> 
    <hours type="Decimal">0.0</hours> 
</item> 
</memberHours>' 

-- Set search/replace vars 
declare @oldval nvarchar(max) = 'John' 
declare @newval nvarchar(max) = 'Jon' 
declare @oldcol xml 
declare @newcol xml 

-- Loop over records fitting the search 
while exists (
    select null 
    from (
     select cast(col as xml) as col 
     from @table 
    ) as a 
    where col.exist('/memberHours/item/member[(text()[1]) eq sql:variable("@oldval")]') = 1 
) begin 

    -- Grab a record as xml 
    set @oldcol = (
     select top 1 col 
     from (
      select cast(col as xml) as col 
      from @table 
     ) as a 
     where col.exist('/memberHours/item/member[(text()[1]) eq sql:variable("@oldval")]') = 1 
    ) 
    set @newcol = @oldcol 

    -- Modify xml data 
    while @newcol.exist('/memberHours/item/member[(text()[1]) eq sql:variable("@oldval")]') = 1 begin 
     set @newcol.modify(' 
      replace value of (/memberHours/item[member=sql:variable("@oldval")]/member/text())[1] with sql:variable("@newval") 
     ') 
    end 

    -- Update table 
    update @table 
    set col = cast(@newcol as nvarchar(max)) 
    where cast(cast(col as xml) as nvarchar(max)) = cast(@oldcol as nvarchar(max)) -- Cast both for equality test! 

end 

-- Test output 
select * from @table 
+0

因爲我沒有通過我的表中的所有行要循環,我如何才能找到其中一個成員是約翰的行? – 2012-04-09 20:04:19

+0

因爲我可以看到我將再次使用這個可以替換set @ xml.modify('替換值(/ memberHours/item [member = sql:variable(「@ OldName」))/ member/text() )[1]與sql:variable(「@ NewName」)')? – 2012-04-09 20:13:48

+0

請參閱更新的解決方案。這將遍歷整個表並替換所有匹配的元素。我不確定是否有更好的基於集合的方法來做到這一點。 – 2012-04-09 20:35:35