【问题标题】:Parse XML in T-SQL在 T-SQL 中解析 XML
【发布时间】:2016-05-12 21:01:05
【问题描述】:

我知道已经有很多关于在 MS T-SQL 中查询 xml 的主题,但是对于所有示例,我无法让我的查询正常工作。

我有以下 XML:

<group>
    <items>
        <groupitem>
            <key>23137</key>
        </groupitem>
        <groupitem>
            <key>23139</key>
        </groupitem>
        <groupitem>
            <key>23151</key>
        </groupitem>
        <groupitem>
            <key>23153</key>
        </groupitem>
    </items>
</group>

我想获取所有“关键”项目,以便我可以将它们插入到一个表中(所以 4 行)

我开始将我的 xml 放入变量 @xml 并运行此查询:

SELECT doc.value('(key/text())[1]', 'nvarchar(255)') AS 'key'
    FROM @xml.nodes('/group/items/groupitem/*') AS ref(doc)

这给了我 4 个空行,如果我删除 [1],它会给我这个错误:“XQuery [value()]: '*value()' requires a singleton (or empty sequence), found operand类型为'xdt:untypedAtomic '"

然后我尝试了这个:

SELECT doc.value('(/group/items/groupitem/key)[1]', 'nvarchar(255)') AS 'key'
    FROM @xml.nodes('/group/items/groupitem/*') AS ref(doc)

这实际上给了我一些数据,但不幸的是,它是相同键 23137 的 4 倍,可能是语句中的 [1] 引起的。但是,删除它会使我回到与以前相同的错误消息。

我知道我应该如何在 Xpath (/group/items/groupitem/key) 中执行此操作,但无法理解如何在 T-Sql 中执行此操作。有什么想法吗?

【问题讨论】:

  • 您是否有任何理由在.nodes() 中的XPath 表达式末尾添加一个星号?你期待不同的元素吗?

标签: sql sql-server xml


【解决方案1】:

试试这个:

SELECT 
    doc.value('(key)[1]', 'int') AS 'key'
FROM 
    @xml.nodes('/group/items/groupitem') AS ref(doc)

在我的例子中,这会返回如下输出:

key
-----
23137
23139
23151
23153

这就是你要找的吗?

.nodes() 的调用基本上为您提供了一个XML 片段的“伪”表——XPath 表达式的每个匹配项都有一个表。因此,在您的情况下,您得到四行 XML,每行代表 &lt;groupitem&gt; 节点的内容。您进入其中,获取其中包含的 &lt;key&gt; 元素的值,将其转换为 int - 很快,您就完成了!

【讨论】:

  • 感谢您的解释,这确实是我想要的。还有一个问题:为什么需要 [1]?
  • @ErikL:因为潜在地,可能有多个元素嵌套在父元素下。仅使用(key) 将返回元素的集合,并且您不能将整个XML 元素集合转换为原子值(如int) - 只有单个元素
【解决方案2】:

在以下查询中,doc 的上下文元素已经是 key 元素:

SELECT doc.value('(key/text())[1]', 'nvarchar(255)') AS 'key'
FROM @xml.nodes('/group/items/groupitem/*') AS ref(doc)

所以你不应该在 select 子句中再次提及key。您可以使用 . 来引用当前上下文元素:

SELECT doc.value('.', 'nvarchar(255)') AS 'key'
FROM @xml.nodes('/group/items/groupitem/*') AS ref(doc)

【讨论】:

  • 谢谢,确实有效。我猜节点语句中的 * 用作通配符,并且由于 groupitem 下方只有一个元素,因此将其分配给 doc 的根?
  • 可能是 text() 在 OP 的查询中有意为之,可能忽略了更深层次的节点内容。然后'(./text())[1]'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-25
相关资源
最近更新 更多