2012-11-27 14 views
5

Ho una semplice XML in una colonna XMLAggiornare la colonna xml del server SQL utilizzando XQUERY?

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

sono riuscito ad aggiornare la colonna con:

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

tutti bene.

Domanda # 1

Come posso usare questa query per udpate il valore id+"lalala":

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

errore = XQuery [tbl1.myXml.modify()]: L'argomento di '+' deve essere di un solo tipo primitivo numerico

domanda # 1

01.235.

Diciamo che non voglio aggiornare il primo record ([1]), ma voglio udpate (lo stesso aggiornamento di cui sopra) solo dove score>4.

posso scrivere naturalmente nel XPath:

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

Ma non voglio farlo nel XPath. Non c'è un modo normale per farlo con una clausola Where?

qualcosa di simile:

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

risposta

6

Se si desidera concatenare stringhe, è necessario utilizzare concat e se id nel proprio caso è un numero intero è necessario eseguirlo su una stringa nella funzione concat.

Nella clausola where è possibile filtrare le righe della tabella da aggiornare, non è possibile specificare quali nodi aggiornare in XML. Questo deve essere fatto nell'espressione xquery. È tuttavia possibile utilizzare exist nella clausola where per filtrare le righe che richiedono realmente l'aggiornamento.

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

perché hanno fatto questa cosa '[1]'? Non pensavano che forse volevo aggiornare 'più di 1 elemento'? –

+0

@RoyiNamir La documentazione che dice "Expression1 deve essere un singleton statico". è [qui] (http://msdn.microsoft.com/en-us/library/ms190675.aspx). È lo stesso per 'insert' ma' delete' può cancellare più di un nodo. Non so davvero perché scelgono di farlo in quel modo, ma se fosse permesso, potresti finire in alcune strane situazioni in cui i nodi modificati cambiano il predicato che ha trovato i nodi che avevano bisogno di essere modificati in primo luogo. Se è necessario aggiornare più di un nodo, è necessario farlo in un ciclo while. –

+0

Grazie. Scelgo questa risposta perché è meno lunga e più leggibile. Ma grazie mille per entrambe le risposte! –

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")'); 

Nota: Ti rendi conto che questo aggiorna il nome di un solo nome del primo gruppo, non tutti bande?

secondo Q1:

No non si può. Soprattutto dal momento che (/Bands/Band[Score<4]/Name/text())[1] (ho cambiato in <) si rivolge in modo specifico alle porte Band nel tuo esempio xml nella domanda. D'altra parte una clausola WHERE funzionerà attraverso l'XML, invece di un particolare livello nel percorso. per esempio. un'interpretazione molto sbagliato:

;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 

Perché c'è almeno una banda in xml con un punteggio < 4, l'XML viene aggiornato. TUTTO IL, perché xml.modify funziona solo una volta nella prima corrispondenza, il nome della prima banda viene aggiornato, non quello corrispondente al filtro punteggio.

Problemi correlati