Freigeben über


Angeben der Tiefe von rekursiven Beziehungen mit 'sql:max-depth'

Wenn eine Tabelle in relationalen Datenbanken an einer Beziehung mit sich selbst beteiligt ist, wird sie als rekursive Beziehung bezeichnet. Beispielsweise ist in einer Aufsichtsperson eine Tabelle, in der Mitarbeiterdatensätze gespeichert werden, an einer Beziehung mit sich selbst beteiligt. In diesem Fall spielt der Mitarbeitertisch eine Rolle des Vorgesetzten auf einer Seite der Beziehung, und die gleiche Tabelle spielt eine Rolle der Überwachung auf der anderen Seite.

Zuordnungsschemas können rekursive Beziehungen enthalten, bei denen ein Element und sein Vorgänger vom gleichen Typ sind.

Beispiel A

Betrachten Sie die folgende Tabelle:

Emp (EmployeeID, FirstName, LastName, ReportsTo)  

In dieser Tabelle speichert die Spalte "ReportsTo" die Mitarbeiter-ID des Vorgesetzten.

Angenommen, Sie möchten eine XML-Hierarchie von Mitarbeitern generieren, in der sich der Vorgesetzte am Anfang der Hierarchie befindet und in dem die Mitarbeiter, die diesen Vorgesetzten melden, in der entsprechenden Hierarchie angezeigt werden, wie im folgenden XML-Beispielfragment dargestellt. Dieses Fragment zeigt die rekursive Struktur für Mitarbeiter 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>  

In diesem Fragment meldet mitarbeiter 5 Mitarbeiter 4, Mitarbeiter 4 berichte an Mitarbeiter 3 und Mitarbeiter 3 und 2 Berichte an Mitarbeiter 1.

Um dieses Ergebnis zu erzeugen, können Sie das folgende XSD-Schema verwenden und eine XPath-Abfrage dafür angeben. Das Schema beschreibt ein Emp-Element<> vom Typ "EmployeeType", das aus einem <untergeordneten Emp-Element> desselben Typs "EmployeeType" besteht. Dies ist eine rekursive Beziehung (das Element und sein Vorgänger sind vom gleichen Typ). Darüber hinaus verwendet das Schema eine <sql:Beziehung> , um die Beziehung zwischen dem Vorgesetzten und der Aufsicht zu beschreiben. Beachten Sie, dass emp in dieser <sql:relationship> sowohl die übergeordnete als auch die untergeordnete Tabelle ist.

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

Da die Beziehung rekursiv ist, müssen Sie die Tiefe der Rekursion im Schema angeben. Andernfalls wird das Ergebnis eine endlose Rekursion sein (Mitarbeiterberichte an mitarbeiterberichterstattung an Mitarbeiter usw.). Mit der sql:max-depth Anmerkung können Sie angeben, wie tief die Rekursion verlaufen soll. In diesem beispiel, um einen Wert für sql:max-depthanzugeben, müssen Sie wissen, wie tief die Verwaltungshierarchie in das Unternehmen geht.

Hinweis

Das Schema gibt die sql:limit-field Anmerkung an, gibt jedoch nicht die sql:limit-value Anmerkung an. Dadurch wird der obere Knoten in der resultierenden Hierarchie auf die Mitarbeiter beschränkt, die keinem mitarbeiter melden. (ReportsTo ist NULL.) Wenn Sie sql:limit-field dies angeben und nicht angeben sql:limit-value (standardmäßig null), wird dies erreicht. Wenn der resultierende XML-Code alle möglichen Berichtsstruktur (die Berichtsstruktur für jeden Mitarbeiter in der Tabelle) enthalten soll, entfernen Sie die sql:limit-field Anmerkung aus dem Schema.

Hinweis

Im folgenden Verfahren wird die tempdb-Datenbank verwendet.

So testen Sie eine XPath-Beispielabfrage für das Schema

  1. Erstellen Sie eine Beispieltabelle namens Emp in der tempdb-Datenbank, auf die der virtuelle Stamm verweist.

    USE tempdb  
    CREATE TABLE Emp (  
           EmployeeID int primary key,   
           FirstName  varchar(20),   
           LastName   varchar(20),   
           ReportsTo int)  
    
  2. Fügen Sie diese Beispieldaten hinzu:

    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. Kopieren Sie den oben stehenden Schemacode, und fügen Sie ihn in eine Textdatei ein. Speichern Sie die Datei als maxDepth.xml.

  4. Kopieren Sie die folgende Vorlage, und fügen Sie sie in eine Textdatei ein. Speichern Sie die Datei als maxDepthT.xml im selben Verzeichnis, in dem Sie maxDepth.xmlgespeichert haben. Die Abfrage in der Vorlage gibt alle Mitarbeiter in der Tabelle Emp zurück.

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

    Der für das Zuordnungsschema (maxDepth.xml) angegebene Verzeichnispfad ist relativ zum Verzeichnis, in dem die Vorlage gespeichert wird. Es kann auch ein absoluter Pfad angegeben werden. Beispiel:

    mapping-schema="C:\MyDir\maxDepth.xml"  
    
  5. Erstellen und verwenden Sie das SQLXML 4.0-Testskript (Sqlxml4test.vbs), um die Vorlage auszuführen. Weitere Informationen finden Sie unter Verwenden von ADO zum Ausführen von SQLXML 4.0-Abfragen.

Dies ist das Ergebnis:

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

Hinweis

Um unterschiedliche Tiefen von Hierarchien im Ergebnis zu erzeugen, ändern Sie den Wert der sql:max-depth Anmerkung im Schema, und führen Sie die Vorlage nach jeder Änderung erneut aus.

Im vorherigen Schema hatten alle <Emp-Elemente> genau denselben Satz von Attributen (EmployeeID, FirstName und LastName). Das folgende Schema wurde leicht geändert, um ein zusätzliches ReportsTo-Attribut für alle Emp-Elemente> zurückzugeben, die< einem Vorgesetzten gemeldet werden.

Dieses XML-Fragment zeigt beispielsweise die untergeordneten Elemente von Mitarbeiter 1 an:

<?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">  
...  
...  

Dies ist das überarbeitete Schema:

<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

In einem Schema, das aus rekursiven Beziehungen besteht, muss die Tiefe der Rekursion explizit im Schema angegeben werden. Dies ist erforderlich, um die entsprechende FOR XML EXPLICIT-Abfrage erfolgreich zu erstellen, die die angeforderten Ergebnisse zurückgibt.

Verwenden Sie die sql:max-depth Anmerkung im Schema, um die Tiefe der Rekursion in einer rekursiven Beziehung anzugeben, die im Schema beschrieben wird. Der Wert der sql:max-depth Anmerkung ist eine positive ganze Zahl (1 bis 50), die die Anzahl der Rekursionen angibt: Ein Wert von 1 stoppt die Rekursion am Element, für das die sql:max-depth Anmerkung angegeben wird; ein Wert von 2 stoppt die Rekursion auf der nächsten Ebene von dem Element, an dem sql:max-depth angegeben wird, usw.

Hinweis

In der zugrunde liegenden Implementierung wird eine XPath-Abfrage, die mit einem Zuordnungsschema angegeben wird, in eine SELECT ... FOR XML EXPLICIT query. Diese Abfrage erfordert, dass Sie eine endliche Tiefe der Rekursion angeben. Je höher der wert, für sql:max-depthden Sie angeben, desto größer ist die generierte FOR XML EXPLICIT-Abfrage. Dies kann die Abrufzeit verlangsamen.

Hinweis

Updategramme und XML-Massenladevorgang ignorieren die Anmerkung der maximalen Tiefe. Dies bedeutet, dass rekursive Aktualisierungen oder Einfügungen unabhängig davon auftreten, welchen Wert Sie für die maximale Tiefe angeben.

Angeben von sql:max-depth für komplexe Elemente

Die sql:max-depth Anmerkung kann für jedes komplexe Inhaltselement angegeben werden.

Rekursive Elemente

Wenn sql:max-depth sowohl für das übergeordnete Element als auch für das untergeordnete Element in einer rekursiven Beziehung angegeben wird, hat die sql:max-depth im übergeordneten Element angegebene Anmerkung Vorrang. Im folgenden Schema wird beispielsweise die sql:max-depth Anmerkung sowohl für die übergeordneten als auch für die untergeordneten Mitarbeiterelemente angegeben. In diesem Fall hat die sql:max-depth=4für das <übergeordnete Emp-Element> (die Rolle des Betreuers spielt) Vorrang. Das sql:max-depth auf dem untergeordneten <Emp-Element> angegebene Element (das eine Rolle der Überwachung spielt) wird ignoriert.

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

Führen Sie zum Testen dieses Schemas die schritte aus, die weiter oben in diesem Thema für Beispiel A bereitgestellt wurden.

Nichtcursive Elemente

Wenn die sql:max-depth Anmerkung für ein Element im Schema angegeben wird, das keine Rekursion verursacht, wird sie ignoriert. Im folgenden Schema besteht ein <Emp-Element> aus einem <untergeordneten Konstantenelement> , das wiederum über ein <untergeordnetes Emp-Element> verfügt.

In diesem Schema wird die sql:max-depth für das <Constant-Element> angegebene Anmerkung ignoriert, da zwischen dem <übergeordneten Emp-Element> und dem <untergeordneten Konstantenelement> keine Rekursion vorhanden ist. Aber es gibt Rekursion zwischen dem <Emp-Vorfahren> und dem <Emp-Kind> . Das Schema gibt die sql:max-depth Anmerkung für beide an. Daher hat die sql:max-depth Anmerkung, die auf dem Vorgänger <(Emp> in der Aufsichtsrolle) angegeben ist, Vorrang.

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

Führen Sie zum Testen dieses Schemas die schritte aus, die oben in diesem Thema für Beispiel A bereitgestellt wurden.

Komplexe Typen, die durch Einschränkung abgeleitet werden

Wenn Sie einen komplexen Typableitung nach <Einschränkung> haben, können Elemente des entsprechenden basiskomplexen Typs die sql:max-depth Anmerkung nicht angeben. In diesen Fällen kann die sql:max-depth Anmerkung dem Element des abgeleiteten Typs hinzugefügt werden.

Wenn Sie jedoch einen komplexen Typableitung nach <Erweiterung> haben, können die Elemente des entsprechenden basiskomplexen Typs die sql:max-depth Anmerkung angeben.

Beispielsweise generiert das folgende XSD-Schema einen Fehler, da die sql:max-depth Anmerkung für den Basistyp angegeben ist. Diese Anmerkung wird für einen Typ, der durch <Einschränkung> von einem anderen Typ abgeleitet wird, nicht unterstützt. Um dieses Problem zu beheben, müssen Sie das Schema ändern und die sql:max-depth Anmerkung für das Element im abgeleiteten Typ angeben.

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

Im Schema sql:max-depth wird für einen CustomerBaseType komplexen Typ angegeben. Das Schema gibt auch ein Customer-Element<> vom Typ CustomerTypean, das von CustomerBaseType. Eine für ein solches Schema angegebene XPath-Abfrage generiert einen Fehler, da sql:max-depth für ein Element, das in einem Einschränkungsbasistyp definiert ist, nicht unterstützt wird.

Schemas mit einer tiefen Hierarchie

Möglicherweise verfügen Sie über ein Schema, das eine tiefe Hierarchie enthält, in der ein Element ein untergeordnetes Element enthält, das wiederum ein anderes untergeordnetes Element enthält usw. Wenn die sql:max-depth in einem solchen Schema angegebene Anmerkung ein XML-Dokument generiert, das eine Hierarchie von mehr als 500 Ebenen enthält (mit Element der obersten Ebene auf Ebene 1, untergeordnetem Element auf Ebene 2 usw.), wird ein Fehler zurückgegeben.