Ответ 1
Да, nodes()
генерирует строку, установленную в порядке документа. Оператор, используемый в плане запроса для этого, представляет собой XML-приложение с табличной функцией XML.
Таблица-функция Функция XML Reader вводит XML BLOB в качестве параметра и создает набор строк, представляющий узлы XML в порядке XML-документа. Другие входные параметры могут ограничивать узлы XML, возвращаемые подмножеству XML документ.
Но запрос без order by
имеет порядок undefined, поэтому никаких гарантий нет.
Один из способов обойти это - использовать 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, уровень 16, состояние 1, строка 19
Столбец 'c', который был возвращен методом nodes(), не может использоваться напрямую. Его можно использовать только с одним из четырех методов типа данных XML: exist(), 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