2

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

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

然而,当我使用该函数以任何方式分解该 XML 变量时nodes(),SQL Server 抱怨说

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(当显然可以直接选择 XML 数据类型的列时?)

4

2 回答 2

1

官方文档说它是一个rowset。这是它的摘录:

nodes() 方法的结果是包含原始 XML 实例的逻辑副本的行集。在这些逻辑副本中,每个行实例的上下文节点都设置为使用查询表达式标识的节点之一。这样,以后的查询可以相对于这些上下文节点进行导航。

nodes() 方法(xml 数据类型)

于 2021-07-25T15:13:05.450 回答
1

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

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)

这将返回以下结果

Items.Item.query('.')
<item>一个</item>
<item>两个</item>

我在下面添加了一个附加列,以指示Items.Item概念上返回的每一行的结果。

Items.Item.query('.') 项目.项目
<item>一个</item> 在此处输入图像描述
<item>两个</item> 在此处输入图像描述

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

您可以通过使用..表达式选择上下文节点的父级来看到这一点

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

退货

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

如果可以Items.Item直接选择,我怀疑这将是用户的期望,即它只会返回输入文档。如果您只想返回输入文档,您可以直接选择它

SELECT Items.Item.query('.') AS [Items.Item.query('.')], @Items
FROM @Items.nodes('data/item') AS Items (Item)
于 2021-07-25T10:26:34.770 回答