2013-09-26 10 views
5

Utilizzo di SQL 2012 & ottenere XML passato in una stored procedure che deve prendere quell'input & scrivere una riga sulla tabella per ciascuno degli elementi in una sezione dell'XML che viene passata alla stored procedure. XML assomiglia:SQL 2012 - iterare attraverso un elenco XML (migliore alternativa a un ciclo WHILE)

<MyXML> 
    <MyMsg>My Text Message</MyMsg> 
    <MsgTime>2013-09-25 10:52:37.098</MsgTime> 
    <SendToList> 
    <SendTo>John</SendTo> 
    <SendTo>James</SendTo> 
    <SendTo>Rob</SendTo> 
    <SendTo>Pete</SendTo> 
    <SendTo>Sam</SendTo> 
    </SendToList> 
</MyXML> 

L'uscita della stored procedure dovrebbero essere 5 righe inserite in una tabella (uno per ogni SendTo sopra), e ciascuna avente lo stesso valore nei MyMsg e MsgTime campi in tale tabella.

Posso ottenere il conteggio del numero di SendTo e posso ottenere l'XML SendToList ma non so come iterarlo attraverso di esso per fare gli inserti.

Posso usare il seguente codice SQL per ottenere ciò che c'è nell'XML.

SELECT 
x.value('(/MyXML/MyMsg)[1]', 'VARCHAR(1024)'), 
x.value('(/MyXML/MsgTime)[1]', 'DATETIME'), 
    @max = x.query('<e> { count(/MyXML/SendToList/SendTo) } </e>').value('e[1]','int'), 
    @mlst = x.query('/MyXML/SendTo') 
    FROM @XML_In.nodes('//MyXML') i(x) 

Attualmente, sto usando variabili e un WHILE per scorrere le voci del SendToList, ma so che ci deve essere un modo migliore.

SELECT @msgTo= @XML_In.value('(/MyXML/SendToList/SendTo[position()=sql:variable("@cnt")])[1]','VARCHAR(100)') 

Il sopra di me ottiene il valore di ogni elemento della SendToList.
Se seleziono la variabile @mlst, posso vedere la struttura dell'XML che ho bisogno di scorrere.

<SendToList> 
    <SendTo>John</SendTo> 
    <SendTo>James</SendTo> 
    <SendTo>Rob</SendTo> 
    <SendTo>Pete</SendTo> 
    <SendTo>Sam</SendTo> 
</SendToList> 

Anche se i WHILE opere, che sta facendo un inserto dopo l'altra. Stavo pensando che i metodi disponibili dovrebbero essere in grado di fare tutto al posto del ciclo, ma non ne so abbastanza del loro utilizzo per fare ciò che devo fare.

Apprezzerebbero qualsiasi aiuto o suggerimento.

risposta

12

Se avete bisogno di fare per qualcosa che richiede un ciclo (ad esempio, si desidera inviare e-mail a ciascun destinatario, che si può utilizzare un cursore:

declare cur cursor local fast_forward for 
    select 
     s.c.value('(text())[1]', 'nvarchar(max)') as SendTo, 
     m.c.value('(MyMsg/text())[1]', 'nvarchar(max)') as MyMsg, 
     m.c.value('(MsgTime/text())[1]', 'nvarchar(max)') as MsgTime 
    from @XML_In.nodes('MyXML') as m(c) 
     outer apply m.c.nodes('SendToList/SendTo') as s(c) 

open cur 
while 1 = 1 
begin 
    fetch cur into @SendTo, @MyMsg, @MsgTime 
    if @@fetch_status <> 0 break 

    --======================================= 
    -- do what you need here 
    --======================================= 
end 
close cur 
deallocate cur 

Se si desidera solo per inserire righe in qualche tabella, è possibile farlo in un semplice inserto:

insert into <Your table> 
(
    SendTo, MyMsg, MsgTime 
) 
select 
    s.c.value('(text())[1]', 'nvarchar(max)') as SendTo, 
    m.c.value('(MyMsg/text())[1]', 'nvarchar(max)') as MyMsg, 
    m.c.value('(MsgTime/text())[1]', 'nvarchar(max)') as MsgTime 
from @XML_In.nodes('MyXML') as m(c) 
    outer apply m.c.nodes('SendToList/SendTo') as s(c) 

sql fiddle demo

+0

Inserirmi direttamente in un tavolo: il tuo secondo esempio funzionava alla grande. Grazie! –

+0

Cosa succede se voglio leggere i dati e salvarli su una variabile da visualizzare nel front-end? http://stackoverflow.com/questions/26426412/how-to-ensure-the-sql-is-able-to-read-all-xml-tag-data – SearchForKnowledge

+0

La prima opzione mi obbligava a dichiarare SendTo, MyMsg, MsgTime – user3885927

Problemi correlati