Общие способы применения запросов XQuery
В этом подразделе приведены примеры использования запросов XQuery.
Примеры
А. Запрос описаний каталога для поиска продукции и значений веса
Следующий запрос возвращает идентификаторы моделей продукции и их вес (если указан) из описания в каталоге продукции. Запрос формирует XML следующей структуры:
<Product ProductModelID="…">
<Weight>…</Weight>
</Product>
Это запрос:
SELECT CatalogDescription.query('
declare namespace p1="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
<Product ProductModelID="{ (/p1:ProductDescription/@ProductModelID)[1] }">
{
/p1:ProductDescription/p1:Specifications/Weight
}
</Product>
') as Result
FROM Production.ProductModel
WHERE CatalogDescription is not null
Обратите внимание на следующее в предыдущем запросе.
- Ключевое слово namespace в прологе запроса XQuery определяет префикс пространства имен, используемый в теле запроса.
- Текст запроса формирует требуемый XML.
- В предложении WHERE метод exist() используется для нахождения только тех строк, которые содержат описания каталога продукции. То есть XML-данные, которые содержат элемент <
ProductDescription
>.
Результат:
<Product ProductModelID="19"/>
<Product ProductModelID="23"/>
<Product ProductModelID="25"/>
<Product ProductModelID="28"><Weight>Varies with size.</Weight></Product>
<Product ProductModelID="34"/>
<Product ProductModelID="35"/>
Следующий запрос получает те же сведения, но лишь для моделей продукции, описания которых в каталоге включают значение веса (элемент <Weight
>) в спецификациях (элемент <Specifications
>). В данном примере для объявления префикса pd и привязки пространства имен используется предложение WITH XMLNAMESPACES. При таком подходе описание привязки отсутствует как в методе query(), так и в методе exist().
WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' AS pd)
SELECT CatalogDescription.query('
<Product ProductModelID="{ (/pd:ProductDescription/@ProductModelID)[1] }">
{
/pd:ProductDescription/pd:Specifications/Weight
}
</Product>
') as x
FROM Production.ProductModel
WHERE CatalogDescription.exist('/pd:ProductDescription/pd:Specifications//Weight ') = 1
В предыдущем запросе метод exist() типа данных xml в предложении WHERE производит проверку наличия элемента <Weight
> в элементе <Specifications
>.
Б. Поиск идентификаторов моделей продукции, описания которых в каталоге имеют фронтальные и малоразмерные изображения
Описание в каталоге продукции формата XML включает изображения товаров — элемент <Picture
>. Каждое изображение обладает несколькими свойствами, среди которых угол изображения (элемент <Angle
>) и размер (элемент <Size
>).
Для тех моделей продукции,описания которых в каталоге содержат фронтальные и малоразмерные изображения, запрос формирует XML со следующей структурой:
< Product ProductModelID="…">
<Picture>
<Angle>front</Angle>
<Size>small</Size>
</Picture>
</Product>
WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' AS pd)
SELECT CatalogDescription.query('
<pd:Product ProductModelID="{ (/pd:ProductDescription/@ProductModelID)[1] }">
<Picture>
{ /pd:ProductDescription/pd:Picture/pd:Angle }
{ /pd:ProductDescription/pd:Picture/pd:Size }
</Picture>
</pd:Product>
') as Result
FROM Production.ProductModel
WHERE CatalogDescription.exist('/pd:ProductDescription/pd:Picture') = 1
AND CatalogDescription.value('(/pd:ProductDescription/pd:Picture/pd:Angle)[1]', 'varchar(20)') = 'front'
AND CatalogDescription.value('(/pd:ProductDescription/pd:Picture/pd:Size)[1]', 'varchar(20)') = 'small'
Обратите внимание на следующее в предыдущем запросе.
- Предложение WHERE использует метод exist() для получения только тех строк, которые содержат описания каталога продукции с элементом <
Picture
>. - Предложение WHERE использует метод value() дважды для сравнения значений элементов <
Size
> и <Angle
>.
Промежуточный результат:
<p1:Product
xmlns:p1="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription"
ProductModelID="19">
<Picture>
<p1:Angle>front</p1:Angle>
<p1:Size>small</p1:Size>
</Picture>
</p1:Product>
...
В. Создание неструктурированного списка пар имен и характеристик моделей продукции, где каждая пара заключена в элемент <Features>
В описании каталога моделей продукции XML содержит несколько характеристик продукта. Все эти характеристики включены в элемент <Features
>. Данный запрос использует Построение XML (XQuery) для формирования требуемого XML. Выражение в фигурных скобках заменяется результатом.
SELECT CatalogDescription.query('
declare namespace p1="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
for $pd in /p1:ProductDescription,
$f in $pd/p1:Features/*
return
<Feature>
<ProductModelName> { data($pd/@ProductModelName) } </ProductModelName>
{ $f }
</Feature>
') as x
FROM Production.ProductModel
WHERE ProductModelID=19
Обратите внимание на следующее в предыдущем запросе.
- $pd/p1:Features/* возвращает только дочерние узлы элементов <
Features
>, а $pd/p1:Features/node() возвращает все узлы. В их число входят узлы элементов, текстовые узлы, инструкции по обработке, а также примечания. - Два контейнера «цикл по элементам» формируют декартов продукт, из которого возвращаются имя продукта и отдельная характеристика.
- ProductName является атрибутом. Построение XML в этом запросе возвращает его как элемент.
Промежуточный результат:
<Feature>
<ProductModelName>Mountain 100</ProductModelName>
<ProductModelID>19</ProductModelID>
<p1:Warranty
xmlns:p1="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain">
<p1:WarrantyPeriod>3 year</p1:WarrantyPeriod>
<p1:Description>parts and labor</p1:Description>
</p1:Warranty>
</Feature>
<Feature>
<ProductModelName>Mountain 100</ProductModelName>
<ProductModelID>19</ProductModelID>
<p2:Maintenance xmlns:p2="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain">
<p2:NoOfYears>10</p2:NoOfYears>
<p2:Description>maintenance contact available through your dealer
or any AdventureWorks retail store.</p2:Description>
</p2:Maintenance>
</Feature>
...
...
Г. Построение списка, состоящего из имени модели продукции, идентификатора модели и характеристик, сгруппированных в элементе <Product> на основе описания модели продукции в каталоге
Используя сведения, хранящиеся в описании модели продукции в каталоге, следующий запрос строит список, включающий в себя имя модели продукции, идентификатор модели и характеристики, сгруппированные в элементе <Product>.
SELECT ProductModelID, CatalogDescription.query('
declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
<Product>
<ProductModelName>
{ data(/pd:ProductDescription/@ProductModelName) }
</ProductModelName>
<ProductModelID>
{ data(/pd:ProductDescription/@ProductModelID) }
</ProductModelID>
{ /pd:ProductDescription/pd:Features/* }
</Product>
') as x
FROM Production.ProductModel
WHERE ProductModelID=19
Промежуточный результат:
<Product>
<ProductModelName>Mountain 100</ProductModelName>
<ProductModelID>19</ProductModelID>
<p1:Warranty>... </p1:Warranty>
<p2:Maintenance>... </p2:Maintenance>
<p3:wheel xmlns:p3="https://www.adventure-works.com/schemas/OtherFeatures">High performance wheels.</p3:wheel>
<p4:saddle xmlns:p4="https://www.adventure-works.com/schemas/OtherFeatures">
<p5:i xmlns:p5="http://www.w3.org/1999/xhtml">Anatomic design</p5:i> and made from durable leather for a full-day of riding in comfort.</p4:saddle>
<p6:pedal xmlns:p6="https://www.adventure-works.com/schemas/OtherFeatures">
<p7:b xmlns:p7="http://www.w3.org/1999/xhtml">Top-of-the-line</p7:b> clipless pedals with adjustable tension.</p6:pedal>
...
Д. Получение описаний характеристик для модели продукции
Следующий запрос формирует XML, включающий в себя элемент <Product
> с атрибутами ProducModelID и ProductModelName, а также две первые характеристики. Следует уточнить, что первые две характеристики продукта являются первыми двумя дочерними элементами элемента <Features
>. При наличии большего числа характеристик данный запрос возвращает пустой элемент <There-is-more/
>.
SELECT CatalogDescription.query('
declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
<Product>
{ /pd:ProductDescription/@ProductModelID }
{ /pd:ProductDescription/@ProductModelName }
{
for $f in /pd:ProductDescription/pd:Features/*[position()<=2]
return
$f
}
{
if (count(/pd:ProductDescription/pd:Features/*) > 2)
then <there-is-more/>
else ()
}
</Product>
') as Result
FROM Production.ProductModel
WHERE CatalogDescription is not NULL
Обратите внимание на следующее в предыдущем запросе.
- Циклическая структура FOR ... RETURN получает первые две характеристики продукта. Функция position() используется для определения положения элементов в последовательности.
Е. Поиск в описании каталога продукции имен элементов, которые заканчиваются на «ons»
Следующий запрос используется для поиска в описаниях каталога всех элементов в элементе <ProductDescription
>, имена которых заканчиваются на «ons».
SELECT ProductModelID, CatalogDescription.query('
declare namespace p1="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
for $pd in /p1:ProductDescription/*[substring(local-name(.),string-length(local-name(.))-2,3)="ons"]
return
<Root>
{ $pd }
</Root>
') as Result
FROM Production.ProductModel
WHERE CatalogDescription is not NULL
Промежуточный результат:
ProductModelID Result
-----------------------------------------
19 <Root>
<p1:Specifications xmlns:p1="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription">
...
</p1:Specifications>
</Root>
Ж. Поиск сводных описаний, содержащих слово «Aerodynamic»
Следующий запрос получает модели продукции, описания которых в каталоге содержат слово «Aerodynamic»:
WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' AS pd)
SELECT ProductModelID, CatalogDescription.query('
<Prod >
{ /pd:ProductDescription/@ProductModelID }
{ /pd:ProductDescription/pd:Summary }
</Prod>
') as Result
FROM Production.ProductModel
WHERE CatalogDescription.value('
contains( string( (/pd:ProductDescription/pd:Summary)[1] ),"Aerodynamic")','bit') = 1
Следует отметить, что запрос SELECT определяет методы query() и value() для типа данных xml. Поэтому вместо повторения декларации пространства имен дважды в двух разных прологах запроса, в запросе используется префикс pd, который определяется только один раз в предложении WITH XMLNAMESPACES.
Обратите внимание на следующее в предыдущем запросе.
- Предложение WHERE используется для получения лишь тех строк, которые содержат слово «Aerodynamic» в элементе <
Summary
> описания каталога. - Функция contains() используется для определения наличия слова в тексте.
- Метод value() типа данных xml сравнивает возвращенное методом contains() значение с 1.
Результат:
ProductModelID Result
-------------- ------------------------------------------
28 <Prod ProductModelID="28">
<pd:Summary xmlns:pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription">
<p1:p xmlns:p1="http://www.w3.org/1999/xhtml">
A TRUE multi-sport bike that offers streamlined riding and a
revolutionary design. Aerodynamic design lets you ride with the
pros, and the gearing will conquer hilly roads.</p1:p>
</pd:Summary>
</Prod>
З. Поиск моделей продукции, описания которых в каталоге не содержат изображений моделей продукции
Следующий запрос получает значения ProductModelID моделей продукции, описания которых в каталоге не содержат элемента <Picture
>.
SELECT ProductModelID
FROM Production.ProductModel
WHERE CatalogDescription is not NULL
AND CatalogDescription.exist('declare namespace p1="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
/p1:ProductDescription/p1:Picture
') = 0
Обратите внимание на следующее в предыдущем запросе.
- Если в предложении WHERE метод exist() возвращает значение False (0), то в ответ на запрос будет извлечен идентификатор модели продукции. В противном случае идентификатор не извлекается.
- В данном случае результирующий набор пуст, поскольку все описания продукции содержат элемент <
Picture
>.
См. также
Справочник
Запросы XQuery, использующие иерархию
Запросы XQuery, использующие упорядочивание
Запросы XQuery, обрабатывающие реляционные данные
Поддержка пространств имен в XQuery
Основные понятия
Поиск строки в XQuery
Добавление пространств имен с помощью предложения WITH XMLNAMESPACES
Тип данных xml
Тип данных xml
Другие ресурсы
Запрос XQuery к типу данных xml
Представление типов xml-данных в базе данных AdventureWorks
Запрос XQuery к типу данных xml