2013-09-26 9 views
5

Użycie SQL 2012 & przechodzenie XML do procedury przechowywanej, która musi wykonać to wejście & zapisanie wiersza do tabeli dla każdego elementu, który jest w sekcja XML, która jest przekazywana do procedury przechowywanej. XML wygląda następująco:SQL 2012 - iteracja za pomocą listy XML (lepsza alternatywa dla pętli 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> 

Wyjście procedury przechowywanej powinny być 5 rzędów wstawionych do tabeli (dla każdego SendTo wyżej), a każdy ma taką samą wartość w MyMsg i MsgTime pola w tej tablicy.

Mogę uzyskać liczbę z numerem SendTo i mogę uzyskać kod XML SendToList, ale nie wiem, jak wykonać iterację, aby wykonać wstawki.

Mogę użyć następującego kodu SQL, aby uzyskać zawartość pliku 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) 

Obecnie używam zmiennych i WHILE pętli elementów w SendToList, ale wiem, że musi być lepszy sposób.

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

Powyższe daje mi wartość każdej pozycji w SendToList.
Jeśli wybiorę zmienną @mlst, widzę strukturę XML, którą muszę przechodzić.

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

Mimo że WHILE działa, robi jedną wkładkę zaraz po drugiej. Myślałem, że dostępne metody powinny być w stanie zrobić to wszystko zamiast pętli, ale nie wiem wystarczająco dużo o używaniu ich do zrobienia tego, co muszę zrobić.

Doceniam każdą pomoc lub sugestie.

Odpowiedz

12

Jeśli trzeba zrobić coś, co wymaga pętlę (na przykład chcesz wysłać e-mail do każdego odbiorcy, niż można użyć kursora:

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 

Jeśli tylko chcesz wstawić wiersze do jakiś stół, można to zrobić w jednym prostym wkładki:

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

Wstawiałbym prosto do stołu - twój drugi przykład działał świetnie. Dziękuję Ci! –

+0

Co się stanie, jeśli chcę odczytać dane i zapisać je do zmiennej, która ma być wyświetlana z przodu? http://stackoverflow.com/questions/26426412/how-to-ensure-the-sql-isable-to-read-all-xml-tag-data – SearchForKnowledge

+0

Pierwsza opcja wymagała ode mnie zadeklarowania SendTo, MyMsg, MsgTime – user3885927

Powiązane problemy