当前位置: 首页 > 面试题库 >

SQL 2012-遍历XML列表(比WHILE循环更好的替代方法)

单修德
2023-03-14
问题内容

使用SQL 2012并将XML传递到存储过程中,该过程必须接受该输入,并为传递到该存储过程的XML部分中的每个项目在表中写一行。XML看起来像:

<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>

存储过程的输出应该是将5行插入到一个表中(SendTo上面每个插入一行),并且在该表的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)

目前,我正在使用变量和aWHILE来遍历SendToList中的项目,但是我知道必须有一种更好的方法。

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工作正常,它也会在一个插入之后接一个插入。我当时以为可用的方法应该能够完成所有操作,而不是循环执行,但是我对使用它们来做我需要做的事还不了解。

将不胜感激任何帮助或建议。


问题答案:

如果您需要执行需要循环的操作(例如,要向每个收件人发送电子邮件,则可以使用游标:

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](http://sqlfiddle.com/#!3/d41d8/21491)



 类似资料:
  • 问题内容: 我想知道是否有人可以帮助我创建一个while循环来遍历几个数据库,以便从两列的一个表中获取数据。这是我到目前为止所做的。什么都行不通,因为我不知道如何针对我从每个数据库查询的表来使select语句在每个数据库中正常工作(dbo.tbldoc) 问题答案: 我会考虑使用sp_MSForEachDB,这要容易得多… 编辑:

  • 问题内容: 以下是提供输出的代码段:。由于访问列表中的数字3,我期望获得输出。在线给出的解释是“每次迭代中更改的价值”,但我不太了解如何或为什么。任何解释都很好! 问题答案: 这里发生的是一个列表在循环过程中发生了变异。 让我们考虑以下代码片段: 输出为: 每次迭代: 从内部指针当前指向的位置读取值 立即将其分配给列表中的最后一个元素 在最后一个元素打印在标准输出上之后 就像这样: 内部指针指向第

  • 问题 你在代码中使用 while 循环来迭代处理数据,因为它需要调用某个函数或者和一般迭代模式不同的测试条件。 能不能用迭代器来重写这个循环呢? 解决方案 一个常见的IO操作程序可能会想下面这样: CHUNKSIZE = 8192 def reader(s): while True: data = s.recv(CHUNKSIZE) if data ==

  • 问题内容: 问题很容易,我想遍历列表的每个元素和成对的下一个(将最后一个与第一个包裹在一起)。 我考虑过两种非Python的方法: 和: 预期输出: 关于这样做的更pythonic方式的任何建议?也许有一个我没有听说过的预定义功能? 同样,更一般的n折(三重奏,四重奏等代替对子)也可能很有趣。 问题答案: 我已经编写了元组通用版本的代码,我喜欢第一个版本,因为它非常简洁,我看的越多,对我的感觉就越

  • 本文向大家介绍PHP循环遍历数组的3种方法list()、each()和while总结,包括了PHP循环遍历数组的3种方法list()、each()和while总结的使用技巧和注意事项,需要的朋友参考一下 ①each()函数 each()函数需要传递一个数组作为参数,返回数组中当前元素的键/值对,并向后移动数组指针到下一个元素的位置。键/值对被返回带有4个元素的关联和索引混合的数组,键名分别为0、1

  • 问题内容: 通常我们这样编码: 但是也可以按照以下方式做一些事情: 我想要这样做的真正原因是因为我想使用python-progressbar的自动检测maxval。他们喜欢 问题答案: 您可以与callable一起使用。(您应该传递两个参数,一个用于可调用对象,另一个用于前哨值) 注意 当没有剩余元素并且没有放置哨兵值时,它将阻塞。另外,就像-循环,并且与普通的容器循环不同,它将从队列中删除项目。