Общие способы применения запросов 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  

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

  • Ключевое слово пространства имен в прологе 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<.

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>  
...  

C. Создайте плоский список имен модели продукта и пар функций с каждой парой, заключенной <в элемент Features> .

В описании каталога моделей продукции XML содержит несколько характеристик продукта. Все эти функции включены в <Features> элемент. Запрос использует XML Construction (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>  
...  
...      

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() используется для поиска позиции элементов в последовательности.

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

См. также

Запросы XQuery с использованием иерархии
Запросы XQuery с использованием последовательности
Запросы XQuery с использованием реляционных данных
Поиск по строкам в XQuery
Обработка пространств имен в XQuery
Добавление пространств имен в запросы с WITH XMLNAMESPACES
XML-данные (SQL Server)
Справочник по языку XQuery (SQL Server)