Is the result of a SELECT like the one below using XQuery in SQL Server guaranteed to be in document order, that is in the original order the nodes are listed in the xml string?

DECLARE @x XML = '<hey i="3"/><hey i="4"/><hey i="0"/>'
SELECT t.i.value('.', 'int')
FROM @x.nodes('/hey/@i') t(i)

I ask because in general SELECT statements do not guarantee an order unless one is provided.

Also, if this order is (or is not) guaranteed, is that documented somewhere officially, maybe on Microsoft's web site?

Last, is it possible to sort opposite of document order or do other strange sorts and queries based on the original document order from within the SELECT statement?

有帮助吗?

解决方案

The DECLARE @x XML = '<hey i="3"/><hey i="4"/><hey i="0"/>' is an example of an XML "sequence". By definition, without a sort order, the select should always come back in the documents original order.

As already mentioned, you can change the sort order. Here is one example:

SELECT t.i.value('.', 'int') as x, ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) as rn

FROM @x.nodes('/hey/@i') t(i)

order by rn desc

Here is some information about sequences on the Microsoft site:

http://msdn.microsoft.com/en-us/library/ms179215(v=sql.105).aspx

Here is a more general discussion of a sequence in Xquery.

http://en.wikibooks.org/wiki/XQuery/Sequences


I realize that my original answer above is incorrect after reading the page on the Microsoft site I referred to above. That page says that you need a comma between elements to construct a sequence. The example given is not a "sequence". However, my original info about changing the sort order stands :)

其他提示

I think that same rules of Select apply here, no matter if you're selectig from ordinary table, or XML. There's selection part, and there's projection part, and the engine can take different paths to retrieve your data (from the middle sideways, for example). Unfortunately I can't find any official document to support that. And for sure, there's no intrinsic table/document order that you can access and manipulate.

You can add order by clause to the select statement.

DECLARE @x XML = '<hey i="3"/><hey i="4"/><hey i="0"/>'SELECT [column1] = t.i.value('.', 'int') FROM @x.nodes('/hey/@i') t(i)  order by column1 desc

I know what you mean about this. I suspect the order would be document order, but the documentation does not make it clear, and relying on it implicitly just isn't nice.

One way to be confident about the order would be:

DECLARE @x XML = '<hey i="3"/><hey i="4"/><hey i="0"/>';
select @x.value('(/hey[sql:column("id")]/@i)[1]', 'int'), id
from (
    select row_number() over (order by (select 0)) as id
    from @x.nodes('/hey') t(i)
) t
order by id

This would then give you a way to answer your other question, i.e. getting the values in reverse, or some other, order.

N.B. This is going to be much slower than just using nodes as the size of your XML increases.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top