一般 XQuery 使用案例

此主題提供一般 XQuery 使用範例。

範例

A.查詢目錄描述來尋找產品和重量

下列查詢從產品目錄描述中傳回產品型號識別碼和重量 (如果有的話)。 此查詢建構具有下列格式的 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 初構中的 namespace 關鍵字定義用於查詢主體中的命名空間前置詞。

  • 此查詢主體建構所需的 XML。

  • 在 WHERE 子句中,exist() 方法用來尋找只包含產品目錄描述的資料列。 也就是包含 <ProductDescription> 元素的 XML。

結果如下:

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

下列查詢擷取相同資訊,但只針對目錄描述中的規格 (<Specifications> 元素) 有包含重量 (<Weight> 元素) 的那些產品型號。 此範例使用 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

在上一個查詢中,WHERE 子句中的 xml 資料類型的 exist() 方法,會查看 <Specifications> 元素中是否有 <Weight> 元素。

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 建構 (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 迴圈產生一個 Cartesian 產品,並從中傳回產品名稱和個別功能。

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

E.擷取產品型號功能描述

下列查詢建構的 XML 包含 <Product> 元素 (含有 ProducModelIDProductModelName 屬性) 和前兩個產品功能。 尤其,前兩個產品功能是 <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" 的元素名稱

下列查詢搜尋目錄描述,並傳回其名稱結尾是 "ons" 之 <ProductDescription> 元素中的所有元素。

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 查詢指定 xml 資料類型的 query()value() 方法。 因此,不在兩個不同的查詢初構中重複命名空間宣告兩次,而是在查詢中使用前置詞 pd,並且只使用 WITH XMLNAMESPACES 定義一次。

請注意,下列項目是從上一個查詢而來:

  • WHERE 子句用來只擷取其目錄描述的 <Summary> 元素中包含 "Aerodynamic" 一字的資料列。

  • contains() 函數是用來查看此字是否包含在文字中。

  • xml 資料類型的 value() 方法可將 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.尋找其目錄描述不包含產品型號圖片的產品型號

下列查詢擷取其目錄描述不包含 <Picture> 元素之產品型號的 ProductModelID。

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

XQueries 處理關聯式資料

處理 XQuery 中的命名空間

概念

XQuery 中的字串搜尋

使用 WITH XMLNAMESPACES 將命名空間加入至查詢

XML 資料 (SQL Server)

其他資源

Xquery 語言參考 (SQL Server)