Поделиться через


Общие варианты использования XQuery

Область применения:SQL Server

В этой статье приведены общие примеры использования 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> элемент. В этом примере используется WITH XMLNAMESPACES для объявления pd префикса и привязки пространства имен. Таким образом, привязка не описана как в методе 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> .

B. Поиск идентификаторов моделей продукции, описания которых в каталоге имеют фронтальные и малоразмерные изображения.

Описание каталога 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() возвращает все узлы. В их число входят узлы элементов, текстовые узлы, инструкции по обработке, а также примечания.

  • FOR Два цикла создают декартовую продукцию, из которой возвращаются название продукта и отдельная функция.

  • Это 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>
...
...

D. В описании каталога модели продукта выведите имя модели продукта, идентификатор модели и функции, сгруппированные внутри <элемента 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> элемент, имеющий ProductModelIDатрибуты 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() используется для поиска позиции элементов в последовательности.

F. Поиск имен элементов из описания каталога продуктов, заканчивающихся 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>

G. Поиск сводных описаний, содержащих слово «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 используется для извлечения только строк, в которых описание каталога содержит слово "Аэродинамическая" в элементе <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>

H. Поиск моделей продуктов, описания каталога которых не содержат рисунки модели продукта

Следующий запрос извлекает productModelIDs для моделей продуктов, описания каталога которых не включают <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;

Обратите внимание на следующие рекомендации из предыдущего запроса:

  • exist() Если метод в предложении WHERE возвращает false (0), возвращается идентификатор модели продукта. В противном случае он не возвращается.

  • Так как все описания продукта включают <Picture> элемент, результирующий набор пуст в данном случае.