SQL Server 2008搜索并替换xml节点值

时间:2012-04-09 19:05:20

标签: xml sql-server-2008 list replace

我在表中包含一个包含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变量。我无法弄清楚的是如何找到哪个'Item'匹配以及如何替换那个值(即只是'John')

我在SQL Server 2008上。

1 个答案:

答案 0 :(得分: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