2012-04-09 11 views
2

ich eine Spalte in einer Tabelle, die XML enthält, die wie folgt aussiehtSQL Server 2008 Suchen und Ersetzen XML-Knotenwerte

<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> 

Ich brauche alle Zeilen in der Lage sein zu finden, wo das Element gleich zu "John" und dann zu "John" durch "Jon". Da meine XML-Datei in einer nvarchar (max) -Spalte gespeichert ist, schreibe ich eine Funktion, die die Spalte in eine xml-Variable umwandelt, die ich dann verwenden kann. Was ich kann nicht herausfinden, wie zu finden, die ‚Item‘ Spiele und darüber, wie man nur, dass ein Wert (dh nur ‚John‘)

ich auf SQL Server bin 2008

Antwort

3

einen Blick auf die folgenden haben MSDN-Artikel:

replace value of (XML DML)

Insbesondere, könnten Sie so etwas wie dies versuchen:

-- 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

Da ich will nicht eine Schleife durch alle Reihen in meiner Tabelle , wie kann ich nur die Zeilen finden, in denen eines der Mitglieder John ist? –

+0

Da ich sehen kann, dass ich das wieder verwenden werde, kann ich das set @ xml.modify ersetzen ('replace value von (/ memberHours/item [member = sql: variable ("@ AlterName")]/member/text()) [1] mit sql: variable ("@ NewName") ')? –

+0

Bitte beachten Sie die aktualisierte Lösung. Dadurch wird die gesamte Tabelle durchlaufen und alle übereinstimmenden Elemente ersetzt. Ich bin mir nicht sicher, ob es einen besseren Set-basierten Ansatz dafür gibt. –