Share via


XML 建構 (XQuery)

適用於:SQL Server

在 XQuery 中,您可以使用 直接 計算的 建構函式來建構查詢內的 XML 結構。

注意

直接 計算建 構函式之間 沒有任何差異。

使用直接建構函式

當您使用直接建構函式時,您可以在建構 XML 時指定類似 XML 的語法。 下列範例說明直接建構函式的 XML 建構。

建構項目

在使用 XML 標記法時,您可以建構元素。 下列範例會使用直接元素建構函式運算式,並建立 < ProductModel > 元素。 建構的專案有三個子項目

  • 文位元組點。

  • 兩個元素節點: < 摘要 > 和 < 功能 > 。

    • <Summary > 元素有一個文位元組點子系,其值為 「Some description」。

    • Features 元素有三個元素節點子系: < Color > 、 < Weight > 和 < 保固 > 。 >< 每個節點都有一個文位元組點子節點,且分別具有 Red、25、2 年元件和人力的值。

declare @x xml;  
set @x='';  
select @x.query('<ProductModel ProductModelID="111">;  
This is product model catalog description.  
<Summary>Some description</Summary>  
<Features>  
  <Color>Red</Color>  
  <Weight>25</Weight>  
  <Warranty>2 years parts and labor</Warranty>  
</Features></ProductModel>')  
  

這是產生的 XML:

<ProductModel ProductModelID="111">  
  This is product model catalog description.  
  <Summary>Some description</Summary>  
  <Features>  
    <Color>Red</Color>  
    <Weight>25</Weight>  
    <Warranty>2 years parts and labor</Warranty>  
  </Features>  
</ProductModel>  

雖然從常數運算式建構元素,如本範例所示,但這個 XQuery 語言功能的真正威力是建構可動態從資料庫擷取資料的 XML 的能力。 您可以使用大括弧來指定查詢運算式。 在產生的 XML 中,運算式會由其值取代。 例如,下列查詢會建構具有一個 <NewRoot> 子項目 ( <e> ) 的專案。 元素的值 <e> 是藉由在大括弧內指定路徑運算式來計算 (「{ ... }」 。

DECLARE @x xml;  
SET @x='<root>5</root>';  
SELECT @x.query('<NewRoot><e> { /root } </e></NewRoot>');  

大括弧會作為內容切換權杖,並將查詢從 XML 建構切換至查詢評估。 在此情況下,會評估大括弧 /root 內的 XQuery 路徑運算式,並取代結果。

以下是結果:

<NewRoot>  
  <e>  
    <root>5</root>  
  </e>  
</NewRoot>  

下列查詢與上一個查詢類似。 不過,大括弧中的運算式會 指定 data() 函式來擷取元素的 >root< 不可部分完成值,並將它指派給建構的專案。 <e>

DECLARE @x xml;  
SET @x='<root>5</root>';  
DECLARE @y xml;  
SET @y = (SELECT @x.query('  
                           <NewRoot>  
                             <e> { data(/root) } </e>  
                           </NewRoot>' ));  
SELECT @y;  

以下是結果:

<NewRoot>  
  <e>5</e>  
</NewRoot>  

如果您想要使用大括弧做為文字的一部分,而不是內容切換權杖,您可以將它們逸出為 「}}」 或 「{{」,如下列範例所示:

DECLARE @x xml;  
SET @x='<root>5</root>';  
DECLARE @y xml;  
SET @y = (SELECT @x.query('  
<NewRoot> Hello, I can use {{ and  }} as part of my text</NewRoot>'));  
SELECT @y;  

以下是結果:

<NewRoot> Hello, I can use { and  } as part of my text</NewRoot>  

下列查詢是使用直接元素建構函式建構元素的另一個範例。 此外,元素的值 <FirstLocation> 是藉由在大括弧中執行運算式來取得。 查詢運算式會從 Production.ProductModel 資料表的 Instructions 資料行,傳回第一個工作中心位置的製造步驟。

SELECT Instructions.query('  
    declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
        <FirstLocation>  
           { /AWMI:root/AWMI:Location[1]/AWMI:step }  
        </FirstLocation>   
') as Result   
FROM Production.ProductModel  
WHERE ProductModelID=7;  

以下是結果:

<FirstLocation>  
  <AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">  
      Insert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.   
  </AWMI:step>  
  <AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">  
      Attach <AWMI:tool>Trim Jig TJ-26</AWMI:tool> to the upper and lower right corners of the aluminum sheet.   
  </AWMI:step>  
   ...  
</FirstLocation>  

XML 建構中的元素內容

下列範例說明使用直接專案建構函式建構專案內容時運算式的行為。 在下列範例中,直接元素建構函式會指定一個運算式。 針對此運算式,會在產生的 XML 中建立一個文位元組點。

declare @x xml;  
set @x='  
<root>  
  <step>This is step 1</step>  
  <step>This is step 2</step>  
  <step>This is step 3</step>  
</root>';  
select @x.query('  
<result>  
 { for $i in /root[1]/step  
    return string($i)  
 }  
</result>');  
  

運算式評估所產生的不可部分完成值序列會新增至文位元組點,並在相鄰不可部分完成值之間新增空格,如結果所示。 建構的專案有一個子系。 這是包含結果中所顯示值的文位元組點。

<result>This is step 1 This is step 2 This is step 3</result>  

如果您指定三個不同的運算式來產生三個文位元組點,則連續的文位元組點會藉由串連合併成單一文位元組點,而不是一個運算式。

declare @x xml;  
set @x='  
<root>  
  <step>This is step 1</step>  
  <step>This is step 2</step>  
  <step>This is step 3</step>  
</root>';  
select @x.query('  
<result>  
 { string(/root[1]/step[1]) }  
 { string(/root[1]/step[2]) }  
 { string(/root[1]/step[3]) }  
</result>');  

建構的專案節點有一個子系。 這是包含結果中所顯示值的文位元組點。

<result>This is step 1This is step 2This is step 3</result>  

建構屬性

當您使用直接元素建構函式來建構專案時,您也可以使用類似 XML 的語法來指定元素的屬性,如下列範例所示:

declare @x xml;  
set @x='';  
select @x.query('<ProductModel ProductModelID="111">;  
This is product model catalog description.  
<Summary>Some description</Summary>  
</ProductModel>')  

這是產生的 XML:

<ProductModel ProductModelID="111">  
  This is product model catalog description.  
  <Summary>Some description</Summary>  
</ProductModel>  

建構的專案 <ProductModel> 具有 ProductModelID 屬性和這些子節點:

  • 文位元組點, This is product model catalog description.

  • 專案節點, <Summary> 。 此節點有一個文位元組點子節點, Some description

當您建構屬性時,可以使用大括弧中的運算式來指定其值。 在此情況下,運算式的結果會當做屬性值傳回。

在下列範例中, 不需要 data() 函式。 因為您要將運算式值指派給屬性, 因此會隱含套用 data() 以擷取指定運算式的具型別值。

DECLARE @x xml;  
SET @x='<root>5</root>';  
DECLARE @y xml;  
SET @y = (SELECT @x.query('<NewRoot attr="{ data(/root) }" ></NewRoot>'));  
SELECT @y;  

以下是結果:

<NewRoot attr="5" />  

以下是針對 LocationID 和 SetupHrs 屬性建構指定運算式的另一個範例。 這些運算式會根據指令資料行中的 XML 進行評估。 運算式的具型別值會指派給屬性。

SELECT Instructions.query('  
    declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
        <FirstLocation   
         LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"  
         SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >  
           { /AWMI:root/AWMI:Location[1]/AWMI:step }  
        </FirstLocation>   
') as Result   
FROM  Production.ProductModel  
where ProductModelID=7;  

以下是部份結果:

<FirstLocation LocationID="10" SetupHours="0.5" >  
  <AWMI:step ...   
  </AWMI:step>  
  ...  
</FirstLocation>  

實作限制

以下是限制:

  • 不支援多個或混合 (字串和 XQuery 運算式) 屬性運算式。 例如,如下列查詢所示,您可以建構 XML,其中 Item 是常數,而值 5 是透過評估查詢運算式來取得:

    <a attr="Item 5" />  
    

    下列查詢會傳回錯誤,因為您正在混合常數位符串與運算式 ({/x}),因此不支援:

    DECLARE @x xml  
    SET @x ='<x>5</x>'  
    SELECT @x.query( '<a attr="Item {/x}"/>' )   
    

    在這種情況下,您有下列選項:

    • 透過兩個不可部分完成值的串連,形成屬性值。 這些不可部分完成的值會以不可部分完成值之間的空格序列化為屬性值:

      SELECT @x.query( '<a attr="{''Item'', data(/x)}"/>' )   
      

      以下是結果:

      <a attr="Item 5" />  
      
    • 使用 concat 函式 ,將兩個字串引數串連至產生的屬性值:

      SELECT @x.query( '<a attr="{concat(''Item'', /x[1])}"/>' )   
      

      在此情況下,兩個字串值之間沒有新增空格。 如果您想要兩個值之間的空格,您必須明確提供它。

      以下是結果:

      <a attr="Item5" />  
      
  • 不支援多個運算式做為屬性值。 例如,下列查詢會傳回錯誤:

    DECLARE @x xml  
    SET @x ='<x>5</x>'  
    SELECT @x.query( '<a attr="{/x}{/x}"/>' )  
    
  • 不支援異質序列。 任何將異質序列指派為屬性值的嘗試都會傳回錯誤,如下列範例所示。 在此範例中,異質序列、字串 「Item」 和 元素 <x> 會指定為 屬性值:

    DECLARE @x xml  
    SET @x ='<x>5</x>'  
    select @x.query( '<a attr="{''Item'', /x }" />')  
    

    如果您套用 data() 函式,查詢會運作,因為它會擷取與字串串連的運算式 /x 不可部分完成值。 以下是不可部分完成值的序列:

    SELECT @x.query( '<a attr="{''Item'', data(/x)}"/>' )   
    

    以下是結果:

    <a attr="Item 5" />  
    
  • 屬性節點順序會在序列化期間強制執行,而不是在靜態類型檢查期間強制執行。 例如,下列查詢失敗,因為它嘗試在非屬性節點之後新增屬性。

    select convert(xml, '').query('  
    element x { attribute att { "pass" }, element y { "Element text" }, attribute att2 { "fail" } }  
    ')  
    go  
    

    上述查詢會傳回下列錯誤:

    XML well-formedness check: Attribute cannot appear outside of element declaration. Rewrite your XQuery so it returns well-formed XML.  
    

新增命名空間

使用直接建構函式建構 XML 時,建構的專案和屬性名稱可以使用命名空間前置詞來限定。 您可以透過下列方式將前置詞系結至命名空間:

  • 使用命名空間宣告屬性。

  • 使用 WITH XMLNAMESPACES 子句。

  • 在 XQuery 初構中。

使用命名空間宣告屬性新增命名空間

下列範例會使用 專案 <a> 建構中的命名空間宣告屬性來宣告預設命名空間。 子專案的 <b> 建構會復原父元素中宣告的預設命名空間宣告。

declare @x xml  
set @x ='<x>5</x>'  
select @x.query( '  
  <a xmlns="a">  
    <b xmlns=""/>  
  </a>' )   

以下是結果:

<a xmlns="a">  
  <b xmlns="" />  
</a>  

您可以將前置詞指派給命名空間。 前置詞是在 元素 <a> 的建構中指定。

declare @x xml  
set @x ='<x>5</x>'  
select @x.query( '  
  <x:a xmlns:x="a">  
    <b/>  
  </x:a>' )  

以下是結果:

<x:a xmlns:x="a">  
  <b />  
</x:a>  

您可以在 XML 建構中取消宣告預設命名空間,但無法取消宣告命名空間前置詞。 下列查詢會傳回錯誤,因為您無法取消宣告元素建構 <b> 中指定的前置詞。

declare @x xml  
set @x ='<x>5</x>'  
select @x.query( '  
  <x:a xmlns:x="a">  
    <b xmlns:x=""/>  
  </x:a>' )  

新建構的命名空間可用於查詢內。 例如,下列查詢會在建構 元素時宣告命名空間, <FirstLocation> 並在 LocationID 和 SetupHrs 屬性值的運算式中指定前置詞。

SELECT Instructions.query('  
        <FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"  
         LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"  
         SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >  
           { /AWMI:root/AWMI:Location[1]/AWMI:step }  
        </FirstLocation>   
') as Result   
FROM  Production.ProductModel  
where ProductModelID=7  

請注意,以此方式建立新的命名空間前置詞將會覆寫此前置詞的任何預先存在的命名空間宣告。 例如,查詢初構中的命名空間宣告 AWMI="https://someURI" 會由 元素中的 <FirstLocation> 命名空間宣告覆寫。

SELECT Instructions.query('  
declare namespace AWMI="https://someURI";  
        <FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"  
         LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"  
         SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >  
           { /AWMI:root/AWMI:Location[1]/AWMI:step }  
        </FirstLocation>   
') as Result   
FROM  Production.ProductModel  
where ProductModelID=7  

使用 Prolog 新增命名空間

此範例說明如何將命名空間新增至建構的 XML。 預設命名空間會在查詢初構中宣告。

declare @x xml  
set @x ='<x>5</x>'  
select @x.query( '  
           declare default element namespace "a";  
            <a><b xmlns=""/></a>' )  

請注意,在 專案的 <b> 建構中,命名空間宣告屬性是以空字串作為其值來指定。 這會取消宣告父系中宣告的預設命名空間。

以下是結果:

<a xmlns="a">  
  <b xmlns="" />  
</a>  

XML 建構和空白字元處理

XML 建構中的元素內容可以包含空白字元。 這些字元會以下列方式處理:

  • 命名空間 URI 中的空白字元會被視為 XSD 類型 anyURI 。 具體來說,這就是其處理方式:

    • 開始和結尾的任何空白字元會修剪。

    • 內部空白字元值會折迭成單一空白字元

  • 屬性內容內的換行字元會由空格取代。 所有其他空白字元都會保持原狀。

  • 會保留元素內的空白字元。

下列範例說明 XML 建構中的空白字元處理:

-- line feed is repaced by space.  
declare @x xml  
set @x=''  
select @x.query('  
  
declare namespace myNS="   https://       
 abc/  
xyz  
  
";  
<test attr="    my   
test   attr   
value    " >  
  
<a>  
  
This     is  a  
  
test  
  
</a>  
</test>  
') as XML_Result  
  

以下是結果:

-- result  
<test attr="<test attr="    my test   attr  value    "><a>  
  
This     is  a  
  
test  
  
</a></test>  
"><a>  
  
This     is  a  
  
test  
  
</a></test>  

其他直接 XML 建構函式

處理指示和 XML 批註的建構函式會使用與對應 XML 建構相同的語法。 也支援文位元組點的計算建構函式,但主要用於 XML DML 來建構文位元組點。

注意 如需使用明確文位元組點建構函式的範例,請參閱 insert (XML DML) 中的 特定範例。

在下列查詢中,建構的 XML 包含元素、兩個屬性、批註和處理指示。 請注意,在 之前 <FirstLocation> 會使用逗號,因為正在建構序列。

SELECT Instructions.query('  
  declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
   <?myProcessingInstr abc="value" ?>,   
   <FirstLocation   
        WorkCtrID = "{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"  
        SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >  
       <!-- some comment -->  
       <?myPI some processing instructions ?>  
       { (/AWMI:root/AWMI:Location[1]/AWMI:step) }  
    </FirstLocation>   
') as Result   
FROM Production.ProductModel  
where ProductModelID=7;  
  

以下是部份結果:

<?myProcessingInstr abc="value" ?>  
<FirstLocation WorkCtrID="10" SetupHrs="0.5">  
  <!-- some comment -->  
  <?myPI some processing instructions ?>  
  <AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">I  
  nsert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.   
  </AWMI:step>  
    ...  
</FirstLocation>  
  

使用計算建構函式

. 在此情況下,您可以指定可識別您要建構之節點類型的關鍵字。 僅支援下列關鍵字:

  • 項目

  • 屬性

  • text

對於元素和屬性節點,這些關鍵字後面接著節點名稱,後面還有以大括弧括住的運算式,以產生該節點的內容。 在下列範例中,您要建構此 XML:

<root>  
  <ProductModel PID="5">Some text <summary>Some Summary</summary></ProductModel>  
</root>  

這是使用計算建構函式的查詢會產生 XML:

declare @x xml  
set @x=''  
select @x.query('element root   
               {   
                  element ProductModel  
     {  
attribute PID { 5 },  
text{"Some text "},  
    element summary { "Some Summary" }  
 }  
               } ')  
  

產生節點內容的運算式可以指定查詢運算式。

declare @x xml  
set @x='<a attr="5"><b>some summary</b></a>'  
select @x.query('element root   
               {   
                  element ProductModel  
     {  
attribute PID { /a/@attr },  
text{"Some text "},  
    element summary { /a/b }  
 }  
               } ')  

請注意,計算專案和屬性建構函式,如 XQuery 規格中所定義,可讓您計算節點名稱。 當您在 SQL Server 中使用直接建構函式時,節點名稱,例如元素和屬性,必須指定為常數常值。 因此,元素和屬性的直接建構函式和計算建構函式沒有任何差異。

在下列範例中,建構節點的內容是從 ProductModel 資料表中 xml 資料類型之 Instructions 資料行中儲存的 XML 製造指令取得。

SELECT Instructions.query('  
  declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
   element FirstLocation   
     {  
        attribute LocationID { (/AWMI:root/AWMI:Location[1]/@LocationID)[1] },  
        element   AllTheSteps { /AWMI:root/AWMI:Location[1]/AWMI:step }  
     }  
') as Result   
FROM  Production.ProductModel  
where ProductModelID=7  

以下是部份結果:

<FirstLocation LocationID="10">  
  <AllTheSteps>  
    <AWMI:step> ... </AWMI:step>  
    <AWMI:step> ... </AWMI:step>  
    ...  
  </AllTheSteps>  
</FirstLocation>    

其他實作限制

計算屬性建構函式無法用來宣告新的命名空間。 此外,SQL Server 不支援下列計算建構函式:

  • 計算的檔節點建構函式

  • 計算處理指示建構函式

  • 計算批註建構函式

另請參閱

XQuery 運算式