2013-09-26 33 views
5

使用SQL 2012 &将XML传递到必须接受该输入的存储过程&为表中的每个项目写入一行传递给存储过程的XML的一部分。的XML看起来像:SQL 2012 - 遍历XML列表(更好地替代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> 

存储过程的输出应是插入表(一个用于上述每个SendTo)5行,并且每个具有在该表中的MyMsgMsgTime字段相同的值。

我可以得到SendTo的数量的计数,可以得到XML SendToList,但我不知道如何遍历它来做插入。

我可以使用以下SQL来获取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) 

目前,我使用的变量,并通过在SendToList的项目一个WHILE循环,但我知道我们有了一个更好的办法。

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

上面得到了SendToList中每个项目的值。
如果我选择变量@mlst,我可以看到需要循环的XML结构。

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

即使WHILE工作,它正在做一个接一个地插入。我在想,可用的方法应该能够做到这一切,而不是循环,但我不知道如何使用它们来做我需要做的事情。

希望得到任何帮助或建议。

回答

12

如果你需要做的东西,需要一个循环(例如,你想发送电子邮件给每个收件人,比你可以使用光标:

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 

如果你只是想将行插入有些表,你可以在一个简单的插入做到这一点:

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

我会直接插入表格 - 第二个例子效果很好。谢谢! –

+0

如果我想读取数据并将其保存到变量以显示在前端,该怎么办? http://stackoverflow.com/questions/26426412/how-to-ens-the-sql-is-able-to-read-all-xml-tag-data – SearchForKnowledge

+0

第一个选项要求我声明SendTo,MyMsg,MsgTime – user3885927