Метод query

Метод query используется, когда необходимо выполнить запрос XQuery к XML-документу или фрагменту. Метод возвращает экземпляр типа xml, содержащий результат выполнения запроса. Поддержка развивающегося стандарта запросов для XML-документов соответствует черновикам стандарта, выпущенным консорциумом w3c на протяжении 2002 года [2]. Синтаксис вызова метода следующий:

query ('XQuery'[, noderef])

Где:

  • XQuery – запрос XQuery к данному экземпляру XML-документа.
  • noderef – ссылка на узел, относительно которого выполняется запрос.

Ссылку на узел можно получить с помощью табличной функции xmlnoderefs, возвращающей таблицу с одним полем noderef, записи которой содержат ссылки на выбранные узлы документа. Синтаксис функции следующий:

xmlnoderefs (xmlTypeInstance, 'XQuery', [ noderef ])

Где:

  • xmlTypeInstance – экземпляр XML-типа.
  • XQuery – запрос XQuery.
  • noderef – ссылка на узел, относительно которого выполняется запрос.

Ссылка на узел – это просто некоторый внутренний числовой идентификатор, обозначающий узел и действительный только в пределах данного запроса. Например, значения, возвращаемые следующим запросом, вы можете только наблюдать, нигде использовать их не получится:

declare @xml xmlset @xml = '<fam> <husband income="180">alex</husband> <wife income="161">rosa</wife> <son income="90">dima</son></fam>'select * from xmlnoderefs(@xml, '/fam/*')

Результат (ссылки на три дочерних узла элемента fam):

noderef--------0x5AC00x5B400x5BC0

Использование этой функции может привести к существенному увеличению производительности в тех случаях, когда в запросах используются «почти повторяющиеся» пути. Другое применение заключается в возможности работать с набором узлов в запросе, а не с одним документом или фрагментом xml. Выберем, например, суммарный доход всех членов семьи:

declare @xml xmlset @xml = '<fam> <husband income="180">alex</husband> <wife income="161">rosa</wife> <son income="90">dima</son></fam>'select @xml::value('@income', 'int', noderef) from xmlnoderefs(@xml, '/fam/*')

Это единственный способ выполнить подобный запрос, так как запрос "в лоб"

select @xml::query('/fam/*/@income')

не работает, потому что метод query возвращает XML-документ или фрагмент, но никак не атрибуты (сервер выдает ошибку – XQuery: Attribute may not appear outside of an element). Использование метода value:

select @xml::value('/fam/*/@income', 'int')

также не возможно, поскольку он должен возвращать скалярное значение (сервер выдает ошибку – XQuery: Expression used by 'value()' must return a singleton or empty sequence).

Также можно использовать табличную функцию xmlnoderefs вместе с новым оператором APPLY, который позволяет вызывать произвольную табличную функцию для каждой строки внешней таблицы [3]. Допустим, таблица fams содержит семьи.

create table fams(id int identity primary key, fam xml)

Необходимо выбрать доход каждого из членов семей:

select fam::value('@income', 'int', noderef) from fams cross apply xmlnoderefs(fam, '/fam/*')

Здесь функция xmlnoderefs вызывается для каждой семьи (для каждой строчки таблицы) и возвращает три ссылки на дочерние элементы (fam). Для каждой ссылки, которая обозначает узел XML-элемента (husband, wife или son) вызывается метод value.

ПРИМЕЧАНИЕ По неофициальной информации, функция xmlnoderefs уже устранена во второй бете SQL Server 2005. Ей на смену пришел пятый метод XML-типа – nodes, который, по-видимому, будет возвращать как раз набор узлов, а не малопригодные ссылки на узлы. Проверить это пока не представляется возможным.

Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: