nodes()
数据类型的xml
方法是否按文档顺序返回节点?
例如,如果有以下数据:
declare @xml xml
set @xml = '<Fruits><Apple /><Banana /><Orange /><Pear /></Fruits>'
被查询为
select T.c.query('.')
from @xml.nodes('/Fruits/*') T(c)
元素会按文档顺序返回吗?如果省略select
子句,则order by
返回的行的顺序是未定义的。是select ... from ... .nodes()
的情况,还是例外?
在某些情况下,是否有可能在以下查询的输出中获得非空行集:
declare @xml xml
set @xml = '<Data><Element OrderNo="1" /><Element OrderNo="2" />'
+ '<Element OrderNo="3" /><Element OrderNo="4" />'
+ '<Element OrderNo="5" /></Data>'
select * from (
select T.c.value('.', 'int') OrderNo1,
row_number() over (order by @@spid) OrderNo2
from @xml.nodes('/Data/Element/@OrderNo') T(c)) sq
where OrderNo1 != OrderNo2
答案 0 :(得分:20)
是的,nodes()
按文档顺序生成一行。查询计划中使用的运算符是Table Valued Function XML Reader。
表值函数XML Reader输入XML BLOB作为参数和 生成一个表示XML文档顺序的XML节点的行集。其他 输入参数可以限制返回到XML子集的XML节点 文档。
但是没有order by
的查询有一个未定义的顺序,所以没有保证。
解决这个问题的一种方法是使用id
子句中由表值函数生成的row_number() over()
,并按顺序使用生成的数字。
select X.q
from
(
select T.c.query('.') as q,
row_number() over(order by T.c) as rn
from @xml.nodes('/Fruits/*') T(c)
) as X
order by X.rn
无法直接在T.c
中使用order by
。试着这会给你
Msg 493,Level 16,State 1,Line 19
从nodes()方法返回的列'c'不能直接使用。它只能与四种XML数据类型方法之一,exists(),nodes(),query()和value()一起使用,或者在IS NULL和IS NOT NULL检查中使用。
错误没有提到它应该与row_number
一起使用,但确实如此,这很可能是可能修复的错误,因此上面的代码将失败。但直到SQL Server 2012它才能正常工作。
在不依赖于row_number
的未记录使用的情况下获得保证订单的方法是使用数字表,您可以按位置提取节点。
select T.c.query('.') as q
from Numbers as N
cross apply @xml.nodes('/Fruits/*[sql:column("N.Number")]') as T(c)
where N.Number between 1 and @xml.value('count(/Fruits/*)', 'int')
order by N.Number