Cas d'emploi généraux des requêtes XQuery

Cette rubrique donne des exemples généraux d'emploi de requêtes XQuery.

Exemples

A. Interrogation des descriptions d'un catalogue pour rechercher des produits et des poids

La requête suivante renvoie les ID de modèle de produit et les poids, le cas échéant, de la description du catalogue de produits. La requête construit le code XML sous la forme suivante :

<Product ProductModelID="…">
  <Weight>…</Weight>
</Product>

Voici la requête :

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

Notez les points suivants par rapport à la requête précédente :

  • Le mot clé namespace du prologue XQuery définit un préfixe d'espace de noms qui est utilisé dans le corps de la requête.
  • Le corps de la requête construit le code XML requis.
  • Dans la clause WHERE, la méthode exist() sert à récupérer uniquement les lignes qui contiennent les descriptions du catalogue de produits. Autrement dit, le code XML qui contient l'élément <ProductDescription>.

Voici le résultat obtenu :

<Product ProductModelID="19"/>
<Product ProductModelID="23"/> 
<Product ProductModelID="25"/> 
<Product ProductModelID="28"><Weight>Varies with size.</Weight></Product>
<Product ProductModelID="34"/>
<Product ProductModelID="35"/>

La requête suivante récupère les mêmes informations, mais uniquement pour les modèles de produit dont la description du catalogue mentionne le poids, l'élément <Weight>, dans les caractéristiques techniques, l'élément <Specifications>. Cet exemple utilise WITH XMLNAMESPACES pour déclarer le préfixe pd et sa liaison d'espace de noms. De cette façon, la liaison n'est décrite ni dans la méthode query() ni dans la méthode 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

Dans la requête précédente, la méthode exist() du type de données xml dans la clause WHERE vérifie s'il existe un élément <Weight> dans l'élément <Specifications>.

B. Recherche des ID des modèles de produit dont les descriptions englobent des illustrations de face et de petite taille

La description XML du catalogue de produits comporte les illustrations du produit, l'élément <Picture>. Chaque illustration a plusieurs propriétés dont l'angle de prise de vue, l'élément <Angle>, et la taille, l'élément <Size>.

Pour les modèles de produit dont les descriptions du catalogue englobent des illustrations de face et de petite taille, la requête construit le code XML sous la forme suivante :

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

Notez les points suivants par rapport à la requête précédente :

  • Dans la clause WHERE, la méthode exist() sert à récupérer uniquement les lignes qui contiennent des descriptions du catalogue de produits accompagnées de l'élément <Picture>.
  • La clause WHERE utilise deux fois la méthode value() pour comparer les valeurs des éléments <Size> et <Angle>.

Voici le résultat partiel :

<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. Création d'une liste en 2D des paires nom et caractéristique du modèle de produit, chaque paire étant comprise dans l'élément <Features>

Dans la description du catalogue de produits, le code XML englobe plusieurs caractéristiques du produit. Toutes ces caractéristiques sont incluses dans l'élément <Features>. La requête utilise une construction XML (XQuery) pour construire le code XML requis. L'expression entre accolades est remplacée par le résultat.

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

Notez les points suivants par rapport à la requête précédente :

  • $pd/p1:Features/* renvoie uniquement les enfants du nœud d'élément <Features>, mais $pd/p1:Features/node() renvoie tous les nœuds, notamment les nœuds d'élément et de texte, les instructions de traitement et les commentaires.
  • Les deux boucles FOR génèrent un produit cartésien à partir duquel le nom du produit et ses caractéristiques sont renvoyés.
  • L'élément ProductName est un attribut. La construction XML de cette requête le renvoie sous forme d'élément.

Voici le résultat partiel :

<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. Recensement, à partir de la description d'un modèle de produit extraite du catalogue, du nom du modèle de produit, de son ID et de ses caractéristiques (le tout regroupé à l'intérieur d'un élément <Product>)

D'après les informations stockées dans la description des produits du catalogue, la requête suivante regroupe le nom du modèle de produit, son ID et ses caractéristiques dans un élément <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

Voici le résultat partiel :

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

E. Récupération de la description des caractéristiques d'un modèle de produit

La requête suivante construit le code XML qui comprend un élément <Product> accompagné des attributs ProducModelID et ProductModelName, et des deux premières caractéristiques du produit. Plus précisément, les deux premières caractéristiques du produit sont les deux premiers éléments enfants de l'élément <Features>. En présence d'un nombre supérieur de caractéristiques, la requête renvoie un élément vide <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

Notez les points suivants par rapport à la requête précédente :

  • La structure itérative FOR ... La boucle RETURN récupère les deux premières caractéristiques du produit. La fonction position() sert à trouver la position des éléments dans la séquence.

F. Recherche de noms d'élément se terminant par « ons », d'après les descriptions du catalogue de produits

La requête suivante parcourt les descriptions du catalogue et renvoie tous les éléments de l'élément <ProductDescription> dont le nom se termine par « 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

Voici le résultat partiel :

ProductModelID   Result
-----------------------------------------
         19        <Root>       
                     <p1:Specifications xmlns:p1="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription">        
                          ...       
                     </p1:Specifications>       
                   </Root>        

G. Recherche des descriptions résumées qui contiennent le mot « Aerodynamic »

La requête suivante récupère les modèles de produit dont les descriptions du catalogue contiennent le mot « Aerodynamic » dans la description résumée :

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

Notez que la requête SELECT spécifie les méthodes query() et value() du type de données xml. Par conséquent, au lieu de répéter deux fois la déclaration des espaces de noms dans deux prologues de requête différents, le préfixe pd est utilisé dans la requête, puis défini une seule fois à l'aide de WITH XMLNAMESPACES.

Notez les points suivants par rapport à la requête précédente :

  • La clause WHERE sert à récupérer uniquement les lignes où la description du catalogue contient le mot « Aerodynamic » dans l'élément <Summary>.
  • La fonction contains() sert à vérifier si le mot est inclus dans le texte.
  • La méthode value() du type de données xml compare la valeur renvoyée par contains() à 1.

Voici le résultat obtenu :

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. Recherche de modèles de produit dont les descriptions du catalogue ne s'accompagnent pas d'illustrations

La requête suivante récupère les ID des modèles de produit dont les descriptions du catalogue ne s'accompagnent pas d'un élément <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

Notez les points suivants par rapport à la requête précédente :

  • Si la méthode exist() de la clause WHERE renvoie la valeur False (0), l'ID du modèle de produit est renvoyé. Dans le cas contraire, aucune donnée n'est renvoyée.
  • Dans la mesure où toutes les descriptions des produits comportent un élément <Picture>, le jeu de résultats est vide dans ce cas.

Voir aussi

Référence

Requêtes XQuery impliquant une hiérarchie
Requêtes XQuery impliquant un ordre
Requêtes XQuery pour la gestion des données relationnelles
Gestion des espaces de noms dans XQuery

Concepts

Recherche de chaînes dans XQuery
Ajout d'espaces de noms à l'aide de WITH XMLNAMESPACES
Type de données xml
Type de données xml

Autres ressources

Requêtes XQuery impliquant le type de données xml
Représentation du type de données xml dans la base de données AdventureWorks
Requêtes XQuery impliquant le type de données xml

Aide et Informations

Assistance sur SQL Server 2005