2012-11-27 3 views
5

Ich habe eine einfache XML in einer XML-SpalteSQL Server-XML-Spalte mit XQUERY aktualisieren?

<Bands> 
    <Band> 
     <Name>beatles</Name> 
     <Num>4</Num> 
     <Score>5</Score> 
    </Band> 
    <Band> 
     <Name>doors</Name> 
     <Num>4</Num> 
     <Score>3</Score> 
    </Band> 
</Bands> 

ich es geschafft haben, mit der Spalte zu aktualisieren:

-----just update the name to the id)---- 
    UPDATE tbl1 
    SET [myXml].modify('replace value of (/Bands/Band/Name/text())[1] 
    with sql:column("id")') 

Alle in Ordnung.

Frage # 1

Wie kann ich diese Abfrage verwenden, um den Wert zu id+"lalala" udpate:

UPDATE tbl1 
    SET [myXml].modify('replace value of (/Bands/Band/Name/text())[1] 
    with sql:column("id") + "lalala"') 

Fehler = XQuery [tbl1.myXml.modify()]: Das Argument '+' muss aus einem einzigen numerischen primitiven Typ sein

Frage # 1

Sagen wir, ich möchte nicht zuerst Datensatz aktualisieren ([1]), aber ich möchte udpate (das gleiche Update wie oben) nur wo score>4.

Ich kann natürlich im XPath schreiben:

replace value of (/Bands/Band[Score>4]/Name/text())[1]

Aber ich nicht, dass es in der XPath tun will. Gibt es keine normale Methode, dies mit einer Klausel Where zu tun?

so etwas wie:

UPDATE tbl1 
    SET [myXml].modify('replace value of (/Bands/Band/Name/text())[1] 
    with sql:column("id") where [...score>4...]') 

here is the online sql

Antwort

6

Wenn Sie Zeichenfolgen verketten möchten, sollten Sie concat verwenden und wenn id in Ihrem Fall eine Ganzzahl ist, müssen Sie es in eine Zeichenfolge in der concat Funktion umwandeln.

In der where-Klausel können Sie Zeilen der zu aktualisierenden Tabelle filtern. Sie können nicht angeben, welche Knoten im XML aktualisiert werden sollen. Dies muss im xquery-Ausdruck geschehen. Sie können jedoch in der where-Klausel exist verwenden, um die Zeilen herauszufiltern, die das Update wirklich benötigen.

update tbl1 
set myXml.modify('replace value of (/Bands/Band[Score > 4]/Name/text())[1] 
        with concat(string(sql:column("id")), "lalalala")') 
where myXml.exist('/Bands/Band[Score > 4]') = 1 
+1

Warum haben sie diese "[1]" Sache gemacht? Haben sie nicht gedacht, dass ich "mehr als ein Element" aktualisieren möchte? –

+0

@RoyiNamir Die Dokumentation "Expression1 muss ein statischer Singleton sein". ist [hier] (http://msdn.microsoft.com/en-us/library/ms190675.aspx). Dasselbe gilt für "Einfügen", aber "Löschen" kann mehr als einen Knoten löschen. Ich weiß nicht wirklich, warum sie sich dafür entschieden haben, aber wenn es erlaubt wäre, könnten Sie in seltsame Situationen geraten, in denen die modifizierten Knoten das Prädikat ändern, das die Knoten gefunden hat, die modifiziert werden mussten. Wenn Sie mehr als einen Knoten aktualisieren müssen, müssen Sie dies in einer while-Schleife tun. –

+0

Danke. Ich wähle diese Antwort, weil sie weniger lang und lesbarer ist. Aber vielen Dank für beide Antworten! –

5

Q1:

;with t as (select convert(varchar(10),id) + 'lalala' id2, * from #tbl1) 
    UPDATE t 
    SET [myXml].modify('replace value of (/Bands/Band/Name/text())[1] 
    with sql:column("id2")'); 

Hinweis: Haben Sie erkennen, dass diese den Namen aktualisiert nur den Vornamen des Bandes, die nicht alle Bands?

2. Q1:

Nein, Sie können nicht. Vor allem seit (/Bands/Band[Score<4]/Name/text())[1] (ich änderte <) zielt speziell auf die Türen Band in Ihrem Beispiel xml in der Frage. Eine WHERE-Klausel hingegen funktioniert über das XML hinweg anstelle einer bestimmten Ebene im Pfad. z.B. eine sehr falsche Interpretation:

;with t as (
    select a.*, n.m.value('.','int') Score 
    from #tbl1 a 
    cross apply myXml.nodes('/Bands/Band/Score') n(m) -- assume singular 
) 
    UPDATE t 
    SET [myXml].modify('replace value of (/Bands/Band/Name/text())[1] 
    with sql:column("id")') 
    where Score < 4 

Da es mindestens ein Band in der XML mit einem Score < 4 ist, wird die XML aktualisiert. JEDOCH, weil xml.modify beim ersten Match nur EINMAL funktioniert, wird der Name des ersten Bandes aktualisiert, nicht der zum Filter passende.