涉及层次结构的 XQuery

适用于:SQL Server

AdventureWorks 数据库中的大多数 xml 类型列都是半结构化文档。 因此,每行中存储的文档可能看起来不同。 本主题中的查询示例说明如何从这些不同的文档提取信息。

示例

A. 从生产说明文档检索生产车间以及这些生产车间的第一个生产步骤

对于产品模型 7,查询构造包含 <ManuInstr> 元素的 XML,其中包含 ProductModelIDProductModelName 属性,以及一个或多个 <Location> 子元素。

每个 <Location> 元素都有自己的属性集和一个 <step> 子元素。 此 <step> 子元素是工作中心位置的第一个制造步骤。

SELECT Instructions.query('  
     declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
   \<ManuInstr  ProdModelID = "{sql:column("Production.ProductModel.ProductModelID") }"   
                ProductModelName = "{ sql:column("Production.ProductModel.Name") }" >  
            {   
              for $wc in //AWMI:root/AWMI:Location  
              return  
                <Location>  
                 {$wc/@* }  
                 <step1> { string( ($wc//AWMI:step)[1] ) } </step1>  
                </Location>  
            }  
          </ManuInstr>  
') as Result  
FROM Production.ProductModel  
WHERE ProductModelID=7  

请注意上述查询的以下方面:

  • XQuery Prolog中的 namespace 关键字定义命名空间前缀。 随后,将在查询正文中使用此前缀。

  • 上下文切换标记 {) 和 (} 用于将查询从 XML 构造切换到查询计算。

  • sql:column () 用于在正在构造的 XML 中包含关系值。

  • 在构造 元素时 <Location> ,$wc/@* 检索所有工作中心位置属性。

  • string () 函数从 <step> 元素返回字符串值。

这是部分结果:

<ManuInstr ProdModelID="7" ProductModelName="HL Touring Frame">  
   <Location LocationID="10" SetupHours="0.5"   
            MachineHours="3" LaborHours="2.5" LotSize="100">  
     <step1>Insert aluminum sheet MS-2341 into the T-85A   
             framing tool.</step1>  
   </Location>  
   <Location LocationID="20" SetupHours="0.15"   
            MachineHours="2" LaborHours="1.75" LotSize="1">  
      <step1>Assemble all frame components following   
             blueprint 1299.</step1>  
   </Location>  
...  
</ManuInstr>   

B. 在 AdditionalContactInfo 列中查找所有电话号码

以下查询通过在整个层次结构 <telephoneNumber> 中搜索 元素来检索特定客户联系人的其他电话号码。 <telephoneNumber>由于 元素可以出现在层次结构中的任意位置,因此查询在搜索中使用子代和 self 运算符 (//) 。

SELECT AdditionalContactInfo.query('  
 declare namespace ci="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo";  
 declare namespace act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes";  
for $ph in /ci:AdditionalContactInfo//act:telephoneNumber  
   return  
      $ph/act:number  
') as x  
FROM  Person.Contact  
WHERE ContactID = 1  

结果如下:

\<act:number   
  xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">  
  111-111-1111  
\</act:number>  
\<act:number   
  xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">  
  112-111-1111  
\</act:number>  

若要仅检索顶级电话号码,特别是 <telephoneNumber> 的 <AdditionalContactInfo>子元素,查询中的 FOR 表达式将更改为

for $ph in /ci:AdditionalContactInfo/act:telephoneNumber.

另请参阅

XQuery 基础知识
XML 构造 (XQuery)
XML 数据 (SQL Server)