6

我正在使用 SQL Server 2008 R2。我的问题是我想计算使用 FLWOR 从 XQuery 查询中收到的命中数。对于每个命中,我想要一个连续的数字,例如:0,1,2,3,4...

我的查询:

select @xml.query('for $s at $count in /Root/Persons/Person
return <Person ID="{$count}">{$s}</Person>')

这里唯一的问题是 SQL Server 不支持此功能,我收到错误消息:

Msg 9335, Level 16, State 1, Line 16
XQuery [query()]: The XQuery syntax 'at' is not supported.

我也尝试过使用 let 关键字并定义新变量,但我不知道如何在每次迭代中增加该变量的值?

感谢所有的答案,弗兰基

4

2 回答 2

6

XQuery 是一种声明性语言,您不能使用它let来增加计数器

缺少功能的一个相当老套的解决方法at是计算前面的兄弟<person/>标签:

for $person in /Root/Persons/Person
let $count := count($person/preceding-sibling::Person) + 1
return <Person ID="{$count}">{$person}</Person>

请注意,O(n^2)如果执行引擎未优化此代码(它可能不会这样做),则此代码将具有运行时,因为重复的前面的兄弟扫描。


编辑:如评论中所述,MS SQL 甚至不支持preceding-sibling轴。不过,它们确实支持<<节点顺序比较运算符。应该完全支持此查询:

for $person in /Root/Persons/Person
let $count := count($person/parent::Persons/Person[. << $person]) + 1
return <Person ID="{$count}">{$person}</Person>

顺便说一句,您可能只想粘贴此人的姓名,所以最好使用

(: snip :)
return <Person ID="{$count}">{data($person)}</Person>
于 2013-09-10T11:39:31.360 回答
0

如果您对 XQuery 不太熟悉,另一种可能的公式可能更容易阅读:

for $i in (1 to count(/Root/Persons/Person))
let $person := /Root/Persons/Person[$i]
return
    <Person ID="{$i}">{$person}</Person>

此外,如果 SQL Server 确实/曾经支持 XQuery 3.0,那么您可以执行以下相当不错的操作:

/Root/Persons/Person ! <Person ID="{position()}">{data(.)}</Person>
于 2014-09-23T13:56:06.527 回答