共用方式為


使用 sql:max-depth 在遞歸關聯性中指定深度

在關係資料庫中,當數據表與本身有關聯性時,它稱為遞歸關聯性。 例如,在監督監督關聯性中,儲存員工記錄的數據表會參與與本身的關係。 在這種情況下,員工數據表在關係一邊扮演主管的角色,而同一張桌子在另一邊扮演監督的角色。

對應架構可以包含遞歸關聯性,其中元素及其上階屬於相同類型。

範例 A

請考慮下表:

Emp (EmployeeID, FirstName, LastName, ReportsTo)  

在此數據表中,ReportsTo 數據行會儲存經理的員工標識碼。

假設您想要產生員工 XML 階層,其中經理員工位於階層頂端,以及向該經理回報給該經理的員工會出現在對應的階層中,如下列範例 XML 片段所示。 此片段所顯示的是員工 1 的遞歸樹狀結構

<?xml version="1.0" encoding="utf-8" ?>   
<root>  
  <Emp FirstName="Nancy" EmployeeID="1" LastName="Devolio">  
     <Emp FirstName="Andrew" EmployeeID="2" LastName="Fuller" />   
     <Emp FirstName="Janet" EmployeeID="3" LastName="Leverling">  
        <Emp FirstName="Margaret" EmployeeID="4" LastName="Peacock">  
          <Emp FirstName="Steven" EmployeeID="5" LastName="Devolio">  
...  
...  
</root>  

在此片段中,員工 5 向員工 4、員工 4 回報給員工 3,以及員工 3 和 2 向員工 1 報告。

若要產生此結果,您可以使用下列 XSD 架構,並針對它指定 XPath 查詢。 架構描述 <EmployeeType 類型的 Emp 元素,其中包含相同類型 EmployeeType 的 Emp>>子專案。< 這是遞歸關聯性(元素及其上階是相同類型)。 此外,架構會使用 <sql:relationship> 來描述監督員與監督之間的父子關聯性。 請注意,在此 <sql:relationship> 中,Emp 同時是父數據表和子數據表。

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
            xmlns:dt="urn:schemas-microsoft-com:datatypes"  
            xmlns:sql="urn:schemas-microsoft-com:mapping-schema">  
  <xsd:annotation>  
    <xsd:appinfo>  
      <sql:relationship name="SupervisorSupervisee"  
                                  parent="Emp"  
                                  parent-key="EmployeeID"  
                                  child="Emp"  
                                  child-key="ReportsTo" />  
    </xsd:appinfo>  
  </xsd:annotation>  
  <xsd:element name="Emp" type="EmployeeType"   
                          sql:relation="Emp"   
                          sql:key-fields="EmployeeID"   
                          sql:limit-field="ReportsTo" />  
  <xsd:complexType name="EmployeeType">  
    <xsd:sequence>  
      <xsd:element name="Emp" type="EmployeeType"   
                              sql:relation="Emp"   
                              sql:key-fields="EmployeeID"  
                              sql:relationship="SupervisorSupervisee"  
                              sql:max-depth="6" />  
    </xsd:sequence>   
    <xsd:attribute name="EmployeeID" type="xsd:ID" />  
    <xsd:attribute name="FirstName" type="xsd:string"/>  
    <xsd:attribute name="LastName" type="xsd:string"/>  
  </xsd:complexType>  
</xsd:schema>  

因為關聯性是遞歸的,因此您需要某種方式來指定架構中的遞歸深度。 否則,結果將是無休止的遞歸(員工向員工報告員工報告等等)。 批 sql:max-depth 注可讓您指定遞歸的深度。 在此特定範例中,若要指定的值 sql:max-depth,您必須知道管理階層在公司中的深度。

備註

架構會 sql:limit-field 指定批注,但未指定 sql:limit-value 批注。 這會將產生的階層中的最上層節點限制為只有未向任何人報告的員工。 (ReportsTo 為 NULL。) sql:limit-field 指定和未指定 sql:limit-value (預設值為 NULL) 註解會完成此作業。 如果您希望產生的 XML 包含每個可能的報表樹狀結構(數據表中每位員工的報表樹狀結構),請從架構中移除 sql:limit-field 批注。

備註

下列程式會使用tempdb資料庫。

若要針對架構測試範例 XPath 查詢

  1. 在虛擬根點所在的 tempdb 資料庫中建立名為 Emp 的範例數據表。

    USE tempdb  
    CREATE TABLE Emp (  
           EmployeeID int primary key,   
           FirstName  varchar(20),   
           LastName   varchar(20),   
           ReportsTo int)  
    
  2. 新增此範例資料:

    INSERT INTO Emp values (1, 'Nancy', 'Devolio',NULL)  
    INSERT INTO Emp values (2, 'Andrew', 'Fuller',1)  
    INSERT INTO Emp values (3, 'Janet', 'Leverling',1)  
    INSERT INTO Emp values (4, 'Margaret', 'Peacock',3)  
    INSERT INTO Emp values (5, 'Steven', 'Devolio',4)  
    INSERT INTO Emp values (6, 'Nancy', 'Buchanan',5)  
    INSERT INTO Emp values (7, 'Michael', 'Suyama',6)  
    
  3. 複製上述架構程序代碼,並將它貼到文本檔中。 將檔案儲存為 maxDepth.xml。

  4. 複製下列範本,並將它貼到文字檔中。 將檔案儲存為 maxDepthT.xml 儲存在儲存 maxDepth.xml的相同目錄中。 範本中的查詢會傳回 Emp 數據表中的所有員工。

    <ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">  
      <sql:xpath-query mapping-schema="maxDepth.xml">  
        /Emp  
      </sql:xpath-query>  
    </ROOT>  
    

    針對對應架構所指定的目錄路徑 (maxDepth.xml) 相對於儲存範本的目錄。 您也可以指定絕對路徑,例如:

    mapping-schema="C:\MyDir\maxDepth.xml"  
    
  5. 建立並使用 SQLXML 4.0 測試腳本 (Sqlxml4test.vbs) 來執行範本。 如需詳細資訊,請參閱使用 ADO 執行 SQLXML 4.0 查詢

以下是結果:

<?xml version="1.0" encoding="utf-8" ?>   
<root>  
  <Emp FirstName="Nancy" EmployeeID="1" LastName="Devolio">  
  <Emp FirstName="Andrew" EmployeeID="2" LastName="Fuller" />   
    <Emp FirstName="Janet" EmployeeID="3" LastName="Leverling">  
      <Emp FirstName="Margaret" EmployeeID="4" LastName="Peacock">  
        <Emp FirstName="Steven" EmployeeID="5" LastName="Devolio">  
          <Emp FirstName="Nancy" EmployeeID="6" LastName="Buchanan">  
            <Emp FirstName="Michael" EmployeeID="7" LastName="Suyama" />   
          </Emp>  
        </Emp>  
      </Emp>  
    </Emp>  
  </Emp>  
</root>  

備註

若要在結果中產生不同的階層深度,請變更架構中的註釋值 sql:max-depth ,並在每次變更之後再次執行範本。

在先前的架構中 <,所有 Emp> 元素都有完全相同的屬性集(EmployeeIDFirstNameLastName)。 下列架構已經過稍微修改,以針對向管理員報告的所有 <Emp> 元素傳回其他 ReportsTo 屬性。

例如,此 XML 片段會顯示員工 1 的下屬:

<?xml version="1.0" encoding="utf-8" ?>   
<root>  
<Emp FirstName="Nancy" EmployeeID="1" LastName="Devolio">  
  <Emp FirstName="Andrew" EmployeeID="2"   
       ReportsTo="1" LastName="Fuller" />   
  <Emp FirstName="Janet" EmployeeID="3"   
       ReportsTo="1" LastName="Leverling">  
...  
...  

這是修訂后的架構:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
            xmlns:dt="urn:schemas-microsoft-com:datatypes"  
            xmlns:sql="urn:schemas-microsoft-com:mapping-schema">  
  <xsd:annotation>  
    <xsd:documentation>  
      Customer-Order-Order Details Schema  
      Copyright 2000 Microsoft. All rights reserved.  
    </xsd:documentation>  
    <xsd:appinfo>  
      <sql:relationship name="SupervisorSupervisee"   
                  parent="Emp"  
                  parent-key="EmployeeID"  
                  child="Emp"  
                  child-key="ReportsTo" />  
    </xsd:appinfo>  
  </xsd:annotation>  
  <xsd:element name="Emp"   
                   type="EmpType"   
                   sql:relation="Emp"   
                   sql:key-fields="EmployeeID"   
                   sql:limit-field="ReportsTo" />  
  <xsd:complexType name="EmpType">  
    <xsd:sequence>  
       <xsd:element name="Emp"   
                    type="EmpType"   
                    sql:relation="Emp"   
                    sql:key-fields="EmployeeID"  
                    sql:relationship="SupervisorSupervisee"  
                    sql:max-depth="6"/>  
    </xsd:sequence>   
    <xsd:attribute name="EmployeeID" type="xsd:int" />  
    <xsd:attribute name="FirstName" type="xsd:string"/>  
    <xsd:attribute name="LastName" type="xsd:string"/>  
    <xsd:attribute name="ReportsTo" type="xsd:int" />  
  </xsd:complexType>  
</xsd:schema>  

sql:max-depth Annotation

在包含遞歸關聯性的架構中,必須在架構中明確指定遞歸深度。 若要成功產生傳回所要求結果的對應 FOR XML EXPLICIT 查詢,必須執行此作業。

sql:max-depth使用架構中的批注,即可在架構中所述的遞歸關聯性中指定遞歸深度。 批注的值sql:max-depth是正整數(1 到 50),表示遞歸的數目:值 1 會停止指定批注之元素sql:max-depthsql:max-depth的遞歸;值 2 會停止下一個層級的遞歸,依此表示。

備註

在基礎實作中,針對對應架構指定的 XPath 查詢會轉換成 SELECT ...FOR XML EXPLICIT 查詢。 此查詢會要求您指定遞歸的有限深度。 您為 sql:max-depth指定的值越高,產生的 FOR XML EXPLICIT 查詢就越大。 這可能會減緩擷取時間。

備註

Updategram 和 XML 大量載入會忽略最大深度註釋。 這表示,不論您為最大深度指定的值為何,都會發生遞歸更新或插入。

在複雜元素上指定 sql:max-depth

sql:max-depth批注可以在任何複雜的內容元素上指定。

遞歸元素

如果在 sql:max-depth 遞歸關聯性中的父元素和子專案上指定, sql:max-depth 則父代上指定的註釋優先。 例如,在下列架構中, sql:max-depth 註釋會在父元素和子員工元素上指定。 在這裡情況下, sql:max-depth=4<Emp> 父元素上指定 (扮演主管角色) 會優先使用 。 sql:max-depth忽略子 <Emp> 元素上指定的 (扮演監督角色)。

範例 B

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
            xmlns:dt="urn:schemas-microsoft-com:datatypes"  
            xmlns:sql="urn:schemas-microsoft-com:mapping-schema">  
  <xsd:annotation>  
    <xsd:appinfo>  
      <sql:relationship name="SupervisorSupervisee"  
                                  parent="Emp"  
                                  parent-key="EmployeeID"  
                                  child="Emp"  
                                  child-key="ReportsTo" />  
    </xsd:appinfo>  
  </xsd:annotation>  
  <xsd:element name="Emp" type="EmployeeType"   
                          sql:relation="Emp"   
                          sql:key-fields="EmployeeID"   
                          sql:limit-field="ReportsTo"   
                          sql:max-depth="3" />  
  <xsd:complexType name="EmployeeType">  
    <xsd:sequence>  
      <xsd:element name="Emp" type="EmployeeType"   
                              sql:relation="Emp"   
                              sql:key-fields="EmployeeID"  
                              sql:relationship="SupervisorSupervisee"  
                              sql:max-depth="2" />  
    </xsd:sequence>   
    <xsd:attribute name="EmployeeID" type="xsd:ID" />  
    <xsd:attribute name="FirstName" type="xsd:string"/>  
    <xsd:attribute name="LastName" type="xsd:string"/>  
  </xsd:complexType>  
</xsd:schema>  

若要測試此架構,請遵循本主題稍早針對範例 A 提供的步驟。

非遞歸專案

sql:max-depth如果批注是在架構中不造成任何遞歸的元素上指定,則會忽略它。 在下列架構中, <Emp> 元素是由 Constant 子元素所組成 <,而常數> 子元素接著會具有 <Emp> 子專案。

在此架構中,sql:max-depth會忽略 Constant> 元素上<指定的批注,因為 Emp> 父元素與 Constant 子元素之間<沒有遞歸。>< 但是,Emp 祖先和 Emp> 子系之間<有遞歸。>< 架構會在 sql:max-depth 兩者上指定批注。 因此, sql:max-depth 在上階上指定的批注(<主管角色中的 Emp> ) 優先。

範例 C

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"   
xmlns:sql="urn:schemas-microsoft-com:mapping-schema">  
  <xsd:annotation>  
    <xsd:appinfo>  
      <sql:relationship name="SupervisorSupervisee"   
                  parent="Emp"   
                  child="Emp"   
                  parent-key="EmployeeID"   
                  child-key="ReportsTo"/>  
    </xsd:appinfo>  
  </xsd:annotation>  
  <xsd:element name="Emp"   
               sql:relation="Emp"   
               type="EmpType"  
               sql:limit-field="ReportsTo"  
               sql:max-depth="1" />  
    <xsd:complexType name="EmpType" >  
      <xsd:sequence>  
       <xsd:element name="Constant"   
                    sql:is-constant="1"   
                    sql:max-depth="20" >  
         <xsd:complexType >  
           <xsd:sequence>  
            <xsd:element name="Emp"   
                         sql:relation="Emp" type="EmpType"  
                         sql:relationship="SupervisorSupervisee"   
                         sql:max-depth="3" />  
         </xsd:sequence>  
         </xsd:complexType>  
         </xsd:element>  
      </xsd:sequence>  
      <xsd:attribute name="EmployeeID" type="xsd:int" />  
    </xsd:complexType>  
</xsd:schema>  

若要測試此架構,請遵循本主題稍早針對範例 A 所提供的步驟。

依限制衍生的複雜型別

如果您有依 <限制>衍生的複雜型別,對應基底複雜類型的元素無法指定 sql:max-depth 批注。 在這些情況下, sql:max-depth 批注可以新增至衍生型別的 元素。

另一方面,如果您有以延伸>方式<衍生的複雜型別,對應的基底複雜型別的專案可以指定sql:max-depth批注。

例如,下列 XSD 架構會產生錯誤,因為 sql:max-depth 註釋是在基底類型上指定。 此批注不受其他類型限制>所衍生<的類型支援。 若要修正此問題,您必須變更架構,並在衍生型別的 元素上指定 sql:max-depth 批注。

範例 D

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
            xmlns:dt="urn:schemas-microsoft-com:datatypes"  
            xmlns:msdata="urn:schemas-microsoft-com:mapping-schema">  
  <xsd:complexType name="CustomerBaseType">   
    <xsd:sequence>  
       <xsd:element name="CID" msdata:field="CustomerID" />  
       <xsd:element name="CompanyName"/>  
       <xsd:element name="Customers" msdata:max-depth="3">  
         <xsd:annotation>  
           <xsd:appinfo>  
             <msdata:relationship  
                     parent="Customers"  
                     parent-key="CustomerID"  
                     child-key="CustomerID"  
                     child="Customers" />  
           </xsd:appinfo>  
         </xsd:annotation>  
       </xsd:element>  
    </xsd:sequence>  
  </xsd:complexType>  
  <xsd:element name="Customers" type="CustomerType"/>  
  <xsd:complexType name="CustomerType">  
    <xsd:complexContent>  
       <xsd:restriction base="CustomerBaseType">  
          <xsd:sequence>  
            <xsd:element name="CID"   
                         type="xsd:string"/>  
            <xsd:element name="CompanyName"   
                         type="xsd:string"  
                         msdata:field="CName" />  
            <xsd:element name="Customers"   
                         type="CustomerType" />  
          </xsd:sequence>  
       </xsd:restriction>  
    </xsd:complexContent>  
  </xsd:complexType>  
</xsd:schema>   

在架構中, sql:max-depth 是在複雜型別上 CustomerBaseType 指定。 架構也會指定 <類型的 Customer> 元素,其衍生自 CustomerBaseTypeCustomerType 在這類架構上指定的 XPath 查詢會產生錯誤,因為 sql:max-depth 限制基底類型中定義的專案不支援。

具有深層階層的架構

您可能有一個架構,其中包含一個深層階層,其中元素包含子元素,接著包含另一個子專案等等。 sql:max-depth如果這類架構中指定的批注會產生包含階層超過 500 層的 XML 檔(具有層級 1 的最上層元素、層級 2 的子專案等等),則會傳回錯誤。