在 SQL 服务器 XML 查询中从 nodes() 返回什么类型

What type is returned from nodes() in a SQL Server XML query

如果我有一个 XML 类型的 SQL 变量,可以直接将它用作 SELECT 子句的列(即使值是 XML 没有单个根元素的片段)

DECLARE @Items XML
SET @Items = '<item>one</item><item>two</item>'
SELECT @Items

然而,当我使用 nodes() 函数以任何方式粉碎 XML 变量时,SQL 服务器抱怨

SELECT Items.Item FROM @Items.nodes('/') AS Items (Item)
-- The column 'Item' that was returned from the nodes() method cannot be used directly. It can only be used with one of the four XML data type methods, exist(), nodes(), query(), and value(), or in IS NULL and IS NOT NULL checks.

按照错误信息中的提示进行操作就好了

SELECT Items.Item.query('.') FROM @Items.nodes('/') AS Items (Item)
SELECT Items.Item.query('.') FROM @Items.nodes('//item') AS Items (Item)

但如果不使用其中一种“XML 数据类型”方法,我什至无法将结果转换回 XML。

SELECT CAST(Items.Item AS XML) FROM @Items.nodes('/') AS Items (Item)
-- The column that was returned from the nodes() method cannot be converted to the data type xml. It can only be used with one of the four XML data type methods, exist(), nodes(), query(), and value(), or in IS NULL and IS NOT NULL checks.

Items.Item 列的数据类型是什么,为什么我不能在不涉及其他方法的情况下将其用作 XML(当显然可以直接 select 列时XML 数据类型?)

让我们看一个稍微不同的例子。

DECLARE @Items XML
SET @Items = '<data><item>one</item><item>two</item></data>'

SELECT Items.Item.query('.') 
FROM @Items.nodes('data/item') AS Items (Item)

这 return 是下面的结果

Items.Item.query('.')
<item>one</item>
<item>two</item>

我在下面添加了一个额外的列来指示 Items.Item 的结果在概念上对每一行 returned.

Items.Item.query('.') Items.Item
<item>one</item>
<item>two</item>

这是nodes方法的输入文档相同的文档。只是上下文节点(由箭头指示)在每一行中设置不同。

您可以通过将 .. 表达式用于 select 上下文节点的父节点来查看

SELECT Items.Item.query('..') AS [Items.Item.query('..')]
FROM @Items.nodes('data/item') AS Items (Item) 

Returns

+-----------------------------------------------+
|            Items.Item.query('..')             |
+-----------------------------------------------+
| <data><item>one</item><item>two</item></data> |
| <data><item>one</item><item>two</item></data> |
+-----------------------------------------------+

如果可以直接 select Items.Item 我怀疑这是否符合用户的期望,即只是 return 输入文档。如果你只想 return 输入文档,你可以 select 直接

SELECT Items.Item.query('.') AS [Items.Item.query('.')], @Items
FROM @Items.nodes('data/item') AS Items (Item)

官方文档说它是一个行集。以下是摘录:

The result of the nodes() method is a rowset that contains logical copies of the original XML instances. In these logical copies, the context node of every row instance is set to one of the nodes that is identified with the query expression. This way, later queries can navigate relative to these context nodes.

nodes() Method (xml Data Type)