Sdílet prostřednictvím


Obecné případy použití XQuery

platí pro:SQL Server

Tento článek obsahuje obecné příklady použití XQuery.

Examples

A. Dotazování na popisy katalogu k vyhledání produktů a hmotností

Následující dotaz vrátí ID a váhy modelu produktu, pokud existují, z popisu katalogu produktů. Dotaz vytvoří XML, který má následující formulář:

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

Tady je dotaz:

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;

Všimněte si následujících aspektů z předchozího dotazu:

  • Klíčové namespace slovo v prologu XQuery definuje předponu oboru názvů, která se používá v textu dotazu.

  • Tělo dotazu vytvoří požadovaný kód XML.

  • WHERE V klauzuli exist() se metoda používá k vyhledání pouze řádků, které obsahují popisy katalogu produktů. To znamená XML, který obsahuje <ProductDescription> element.

Tady je výsledek:

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

Následující dotaz načte stejné informace, ale pouze pro modely produktů, jejichž popis katalogu obsahuje hmotnost, <Weight> prvek, ve specifikacích <Specifications> , prvek. Tento příklad používá WITH XMLNAMESPACES k deklaraci předpony pd a její vazby oboru názvů. Tímto způsobem není vazba popsaná v query() metodě i v exist() metodě.

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;

V předchozím dotazu metoda datového typu XML v WHERE klauzuli zkontroluje, exist() jestli v elementu <Specifications> existuje <Weight> prvek.

B. Vyhledání ID modelů produktů pro modely produktů, jejichž popisy katalogu zahrnují obrázky s předním úhlem a malou velikostí

Popis katalogu produktů XML obsahuje obrázky produktů, <Picture> element. Každý obrázek má několik vlastností, včetně úhlu obrázku <Angle> (prvku) a velikosti (elementu <Size> ).

Pro modely produktů, jejichž popisy katalogu obsahují obrázky s předním úhlem a malými rozměry, vytvoří dotaz XML, který má následující formulář:

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

Všimněte si následujících aspektů z předchozího dotazu:

  • WHERE V klauzuli se exist() metoda používá k načtení pouze řádků, které mají popisy katalogu produktů s prvkem<Picture>.

  • Klauzule WHERE používá metodu value() dvakrát k porovnání hodnot prvků <Size> a <Angle> prvků.

Tady je částečný výsledek:

<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. Vytvoření plochého seznamu názvů modelů produktů a párů funkcí s každou dvojicí uzavřenou v <prvku Features>

V popisu katalogu modelů produktů xml obsahuje několik funkcí produktu. Všechny tyto funkce jsou součástí elementu <Features> . Dotaz používá k vytvoření požadovaného XML konstruktoru XML (XQuery ). Výraz ve složených závorkách se nahradí výsledkem.

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;

Všimněte si následujících aspektů z předchozího dotazu:

  • $pd/p1:Features/* vrátí pouze podřízené <Features>položky uzlu prvku , ale $pd/p1:Features/node() vrátí všechny uzly. To zahrnuje uzly prvků, textové uzly, pokyny ke zpracování a komentáře.

  • FOR Dvě smyčky generují kartézský součin, ze kterého se vrátí název produktu a jednotlivá funkce.

  • Jedná se ProductName o atribut. Konstrukce XML v tomto dotazu ho vrátí jako prvek.

Tady je částečný výsledek:

<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. V popisu katalogu modelu produktu vypíšete název modelu produktu, ID modelu a funkce seskupené uvnitř <prvku Product> .

Pomocí informací uložených v popisu katalogu modelu produktu jsou v následujícím dotazu uvedeny názvy modelů produktu, ID modelu a funkce seskupené uvnitř <Product> prvku.

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;

Tady je částečný výsledek:

<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. Načtení popisů funkcí modelu produktu

Následující dotaz vytvoří XML, který obsahuje <Product> element, který má ProductModelID, ProductModelName atributy a první dvě funkce produktu. Konkrétně první dvě funkce produktu jsou prvními dvěma podřízenými prvky <Features> prvku. Pokud existuje více funkcí, vrátí prázdný <There-is-more/> prvek.

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;

Všimněte si následujících aspektů z předchozího dotazu:

  • Struktura FOR smyčky ... RETURN načte první dvě funkce produktu. Funkce position() se používá k vyhledání pozice prvků v sekvenci.

F. Vyhledání názvů prvků z popisu katalogu produktů, který končí na ons

Následující dotaz prohledá popisy katalogu a vrátí všechny prvky v elementu <ProductDescription> , jehož název končí 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;

Tady je částečný výsledek:

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

G. Vyhledání souhrnných popisů obsahujících slovo "Aerodynamika"

Následující dotaz načte modely produktů, jejichž popisy katalogu obsahují v souhrnném popisu slovo "Aerodynamika":

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;

Dotaz SELECT určuje query() a value() metody datového typu XML . Proto se místo opakování deklarace oborů názvů dvakrát ve dvou rozdílových dotazech prology používá předpona pd v dotazu a je definována pouze jednou pomocí WITH XMLNAMESPACES.

Všimněte si následujících aspektů z předchozího dotazu:

  • Klauzule WHERE se používá k načtení pouze řádků, ve kterých popis katalogu obsahuje slovo "Aerodynmika" v <Summary> prvku.

  • Funkce contains() slouží k tomu, aby bylo vidět, jestli je slovo součástí textu.

  • Metoda value() datového typu XML porovnává hodnotu vrácenou contains() hodnotou 1.

Tady je výsledek:

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. Vyhledání modelů produktů, jejichž popisy katalogu neobsahují obrázky modelů produktů

Následující dotaz načte Identifikátory ProductModelIDs pro modely produktů, jejichž popisy katalogu neobsahují <Picture> prvek.

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;

Všimněte si následujících aspektů z předchozího dotazu:

  • exist() Pokud metoda v WHERE klauzuli vrátí hodnotu False (0), vrátí se ID modelu produktu. Jinak se nevrátí.

  • Vzhledem k tomu, že všechny popisy produktů obsahují <Picture> prvek, je sada výsledků v tomto případě prázdná.