2

我在一个表中有一个列,其中包含如下所示的 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”的所有行,然后将“John”替换为“Jon”。由于我的 xml 存储在 nvarchar(max) 列中,因此我正在编写一个函数,将该列转换为我可以使用的 xml 变量。我想不通的是如何找到匹配的“项目”以及如何只替换那个值(即只是“约翰”)

我在 SQL Server 2008 上。

4

1 回答 1

3

看看下面的 MSDN 文章:

替换(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
于 2012-04-09T19:34:41.413 回答