Teilen über


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

Gilt für: SQL Server Azure SQL-Datenbank

Wenn in einer relationalen Datenbank eine Tabelle in einer Beziehung zu sich selbst steht, wird dies als rekursive Beziehung bezeichnet. Beispielsweise steht eine Tabelle, in der Mitarbeiterdatensätze gespeichert werden, in einer Beziehung zwischen Vorgesetzten und unterstellten Mitarbeitern mit sich selbst in Beziehung. In diesem Fall spielt die Mitarbeitertabelle auf der einen Seite der Beziehung die Rolle des Vorgesetzten und auf der anderen Seite spielt dieselbe Tabelle die Rolle des unterstellten Mitarbeiters.

Zuordnungsschemas können rekursive Beziehungen enthalten, wenn 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 enthält die Spalte ReportsTo die Mitarbeiter-ID des Vorgesetzten.

Angenommen, Sie möchten eine XML-Hierarchie der Mitarbeiter generieren, in der sich der Vorgesetzte an der Spitze der Hierarchie befindet, und die Mitarbeiter, die diesem Vorgesetzten unterstellt sind, wie in folgendem XML-Beispielfragment dargestellt, in der zugehörigen Hierarchie angezeigt werden. 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 berichtet Mitarbeiter 5 an Mitarbeiter 4, Mitarbeiter 4 berichtet an Mitarbeiter 3, und die Mitarbeiter 3 und 2 berichten an Mitarbeiter 1.

Sie können das folgende XSD-Schema verwenden und eine XPath-Abfrage damit ausführen, um dieses Ergebnis zu erhalten. 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>  

Weil die Beziehung rekursiv ist, müssen Sie auf irgendeine Weise die Rekursionstiefe im Schema angeben können. Andernfalls enthält das Ergebnis eine endlose Rekursion (ein Mitarbeiter berichtet an den Mitarbeiter, der an den Mitarbeiter berichtet usw.). Mit der sql:max-depth-Anmerkung können Sie angeben, wie tief die Rekursion ausgeführt werden soll. In diesem beispiel, um einen Wert für sql:max-depth anzugeben, 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 oberste Knoten der resultierenden Hierarchie lediglich auf diejenigen Mitarbeiter beschränkt, die niemandem unterstellt sind. (ReportsTo ist NULL.) Wenn Sie sql:limit-field angeben und keine sql:limit-value-Anmerkung (standardmäßig null) angeben, 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

In der folgenden Prozedur wird die Datenbank tempdb verwendet.

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

  1. Erstellen Sie eine Beispieltabelle namens Emp in der Datenbank tempdb, auf die das virtuelle Stammverzeichnis zeigt.

    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 unter dem Dateinamen maxDepth.xml.

  4. Kopieren Sie die folgende Vorlage, und fügen Sie sie in eine Textdatei ein. Speichern Sie die Datei unter dem Namen maxDepthT.xml im gleichen Verzeichnis, in dem Sie maxDepth.xml gespeichert haben. Die Abfrage in der Vorlage gibt alle in der Emp-Tabelle enthaltenen Elemente 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 bezieht sich auf das 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.

Zum Beispiel zeigt dieses XML-Fragment die Untergebenen 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-Anmerkung

In einem Schema, das aus rekursiven Beziehungen besteht, muss die Rekursionstiefe im Schema explizit angegeben werden. Dies ist erforderlich, um die entsprechende FOR XML EXPLICIT-Abfrage, die die gewünschten Ergebnisse zurückgibt, erfolgreich zu erzeugen.

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 vom Element, bei dem sql:max-depth angegeben ist, usw.

Hinweis

In der zugrunde liegenden Implementierung wird eine XPath-Abfrage, die mit einem Zuordnungsschema angegeben wird, in eine SELECT ... FOR XML EXPLICIT query. Bei dieser Abfrage ist es erforderlich, eine endliche Rekursionstiefe anzugeben. Je höher der Wert, den Sie für sql:max-depth angeben, desto größer ist die FOR XML EXPLICIT-Abfrage, die generiert wird. Dies könnte den Abrufvorgang verlangsamen.

Hinweis

Bei Updategrams und beim XML-Massenladen wird die -Anmerkung ignoriert. Dies bedeutet, rekursive Updates oder Einfügungen werden unabhängig von dem Wert ausgeführt, der für angegeben wird.

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

Die sql:max-depth-Anmerkung kann für ein beliebiges komplexes 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 im übergeordneten Element angegebene sql:max-depth-Anmerkung Vorrang. Im folgenden Schema wird beispielsweise die sql:max-depth-Anmerkung sowohl für das übergeordnete als auch für die untergeordneten Mitarbeiterelemente angegeben. In diesem Fall hat "sql:max-depth=4", das für das <übergeordnete Emp-Element> angegeben ist (die Rolle des Vorgesetzten spielt), Vorrang. Die für das untergeordnete <Emp-Element> angegebene sql:max-depth (die 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.

Nicht rekursive 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 für das <Constant-Element> angegebene sql:max-depth-Anmerkung ignoriert, da keine Rekursion zwischen dem< übergeordneten Emp>- und dem< untergeordneten Constant-Element> 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 Anmerkungen an. Daher hat die sql:max-depth-Anmerkung , die für den Vorgänger angegeben ist (<Emp> in der Aufsichtsrolle), 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>  

Um dieses Schema zu testen, führen Sie die für Beispiel A weiter oben in diesem Thema beschriebenen Schritte aus.

Durch Einschränkungen abgeleitete komplexe Typen

Wenn Sie eine komplexe 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.

Das folgende XSD-Schema generiert z. B. 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 wird sql:max-depth für einen komplexen CustomerBaseType-Typ angegeben. Das Schema gibt auch ein <Customer-Element> vom Typ CustomerType an, das von CustomerBaseType abgeleitet wird. 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 liegt ein Schema vor, das eine tiefe Hierarchie umfasst, in der ein Element ein untergeordnetes Element enthält, das wiederum ein untergeordnetes Element enthalt usw. Wenn die in einem solchen Schema angegebene sql:max-depth-Anmerkung ein XML-Dokument generiert, das eine Hierarchie von mehr als 500 Ebenen enthält (mit Element der obersten Ebene auf Ebene 1, dessen untergeordnetes Element auf Ebene 2 usw.), wird ein Fehler zurückgegeben.