(这更多的是一个文档问题,而不是行为问题。它已按照那里的建议从Stack overflow迁移过来。)
在研究另一个需要按原始元素顺序提取 XML 节点的问题的答案时,我遇到了几个答案(此处、此处和此处),它们使用了形式为的表达式ROW_NUMBER() OVER (ORDER BY xml.node)
,并断言或暗示分配的行号值将按 XML 文档顺序分配。
但是,我找不到任何定义 行为的地方ORDER BY xml.node
。尽管子句中似乎允许这样做OVER()
,但文档并未具体提及 XML 节点。
例如,给定:
DECLARE @xml XML = '<root>
<node>One</node>
<node>Two</node>
<node>Three</node>
<node>Four</node>
</root>'
SELECT
ROW_NUMBER() OVER(ORDER BY xml.node) AS rn,
xml.node.value('./text()[1]', 'varchar(255)') AS value
FROM @xml.nodes('*/node') xml(node)
ORDER BY
ROW_NUMBER() OVER(ORDER BY xml.node)
返回结果如下:
rn | value
----------
1 | One
2 | Two
3 | Three
4 | Four
问题:文档中是否有任何地方保证这些结果?这是否被接受为有保证但未记录的行为?或者这是否是另一种情况,ORDER BY (SELECT NULL)
对于看似预先排序的小型源数据集似乎有效,但最终在扩大规模时可能会失败?我之所以问这个问题,是因为我宁愿不推荐使用其行为和可靠性不受文档支持的技术。
有趣的是,尽管 XML 节点可以在 windowed 中使用ORDER BY
,但在普通的 中却不允许SELECT ... ORDER BY
。在普通的 select order-by 子句中使用时,ORDER BY xml.node
会产生以下错误:
消息 493 级别 16 状态 1 第 7 行
从 nodes() 方法返回的列“node”不能直接使用。它只能与四种 XML 数据类型方法(exist()、nodes()、query() 和 value())之一一起使用,或者在 IS NULL 和 IS NOT NULL 检查中使用。
上述错误消息没有列出窗口函数OVER(ORDER BY ...)
作为允许的用途。