Sdílet prostřednictvím


Určení hloubky rekurzivních relací pomocí sql:max-depth

platí pro:SQL Serverazure SQL Database

V relačních databázích, když je tabulka zapojena do vztahu sama se sebou, nazývá se to rekurzivní vztah. Například ve vztahu nadřízený a nadřízený je tabulka uchovávající záznamy zaměstnanců součástí vztahu sama se sebou. V tomto případě hraje stůl zaměstnance roli nadřízeného na jedné straně vztahu a stejný stůl zastává roli dozorce na druhé straně.

Mapovací schémata mohou zahrnovat rekurzivní vztahy, kde prvek a jeho předchůdce jsou stejného typu.

Příklad A

Zvažte následující tabulku:

Emp (EmployeeID, FirstName, LastName, ReportsTo)  

V této tabulce sloupec ReportsTo uchovává identifikační číslo zaměstnance manažera.

Předpokládejme, že chcete vytvořit XML hierarchii zaměstnanců, ve které je manažer zaměstnanec na vrcholu hierarchie a ve které se zaměstnanci, kteří tomuto manažerovi podléhají, objevují v odpovídající hierarchii, jak je ukázáno v následujícím ukázkovém XML fragmentu. Tento fragment ukazuje rekurzivní strom pro zaměstnance 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>  

V tomto fragmentu zaměstnanec 5 podřazuje zaměstnanci 4, zaměstnanec 4 zaměstnanci 3 a zaměstnanci 3 a 2 zaměstnanci 1.

Pro dosažení tohoto výsledku můžete použít následující schéma XSD a zadat dotaz XPath proti němu. Schéma popisuje Emp> prvek< typu EmployeeType, který se skládá z Emp> podprvku< stejného typu, EmployeeType. Jedná se o rekurzivní vztah (prvek a jeho předek jsou stejného typu). Kromě toho schéma používá <vztah> sql:k popisu vztahu rodič-dítě mezi vedoucím a nadřízeným. Všimněte si, že v tomto< vztahu sql:relation> je Emp zároveň rodičovskou i podřízenou tabulkou.

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

Protože vztah je rekurzivní, potřebujete nějaký způsob, jak specifikovat hloubku rekurze ve schématu. Jinak bude výsledkem nekonečná rekurze (zaměstnanec podkládá zprávy zaměstnanci, hlásí zaměstnanci a tak dále). Anotace sql:max-depth vám umožní určit, jak hluboko v rekurzi chcete jít. V tomto konkrétním příkladu, abyste mohli zadat hodnotu pro sql:max-depth, musíte vědět, jak hluboko sahá manažerská hierarchie ve firmě.

Poznámka:

Schéma specifikuje anotaci sql:limit-field , ale nespecifikuje anotaci sql:limit-value . To omezuje nejvyšší uzel v výsledné hierarchii pouze na zaměstnance, kteří nikomu nepodléhají. (ReportsTo je NULL.) Specifikace sql:limit-pole a nespecifikování anotace sql:limit-value (která výchozí je NULL) to zajistí. Pokud chcete, aby výsledné XML zahrnovalo každý možný reporting tree (reporting tree pro každého zaměstnance v tabulce), odstraňte sql :limit-field anotaci ze schématu.

Poznámka:

Následující postup využívá databázi tempdb.

Pro testování vzorku dotazu XPath proti schématu

  1. Vytvořte ukázkovou tabulku nazvanou Emp v databázi tempdb, na kterou virtuální kořen odkazuje.

    USE tempdb  
    CREATE TABLE Emp (  
           EmployeeID int primary key,   
           FirstName  varchar(20),   
           LastName   varchar(20),   
           ReportsTo int)  
    
  2. Přidejte tato ukázková data:

    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. Zkopírujte výše uvedený kód schématu a vložte ho do textového souboru. Uložte soubor jako maxDepth.xml.

  4. Zkopírujte následující šablonu a vložte ji do textového souboru. Ulož soubor jako maxDepthT.xml do stejného adresáře, kde jsi uložil maxDepth.xml. Dotaz v šabloně vrací všechny zaměstnance v tabulce EMP.

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

    Adresářová cesta určená pro mapovací schéma (maxDepth.xml) je relativní k adresáři, ve kterém je šablona uložena. Absolutní cestu lze také specifikovat, například:

    mapping-schema="C:\MyDir\maxDepth.xml"  
    
  5. Vytvořte a použijte testovací skript SQLXML 4.0 (Sqlxml4test.vbs) k provedení šablony. Další informace naleznete v tématu Použití ADO ke spouštění dotazů SQLXML 4.0.

Toto je výsledek:

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

Poznámka:

Pro vytvoření různých hloubek hierarchií ve výsledku změňte hodnotu anotace sql:max-depth ve schématu a po každé změně šablonu znovu spusťte.

V předchozím schématu měly všechny <prvky Emp> přesně stejnou sadu atributů (EmployeeID,FirstName a LastName). Následující schéma bylo mírně upraveno tak, aby vracelo další atribut ReportsTo pro všechny <prvky EMP,> které hlásí manažerovi.

Například tento XML fragment ukazuje podřízené zaměstnance 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">  
...  
...  

Toto je upravené schéma:

<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

Ve schématu složeném z rekurzivních vztahů musí být hloubka rekurze explicitně specifikována ve schématu. To je nutné pro úspěšné vytvoření odpovídajícího dotazu FOR XML EXPLICIT, který vrací požadované výsledky.

Použijte anotaci sql:max-depth ve schématu k určení hloubky rekurze v rekurzivním vztahu, který je ve schématu popsán. Hodnota anotace sql:max-depth je kladné celé číslo (1 až 50), které udává počet rekurzí: Hodnota 1 zastaví rekurzi v prvku, pro který je specifikována sql :max-depth anotace; Hodnota 2 zastaví rekurzi na další úrovni od prvku, na kterém je specifikováno sql:max-depth ; a tak dále.

Poznámka:

V základní implementaci je dotaz XPath, který je specifikován proti mapovacímu schématu, převeden na SELECT ... PRO XML EXPLICITNÍ dotaz. Tento dotaz vyžaduje zadání konečné hloubky rekurze. Čím vyšší hodnotu zadáte pro sql:max-depth, tím větší je dotaz PRO XML EXPLICITNÍ, který se generuje. To by mohlo zpomalit dobu odběru.

Poznámka:

Updategramy a XML Bulk Load ignorují maximální hloubkové anotace. To znamená, že rekurzivní aktualizace nebo vkládání se budou dět bez ohledu na to, jakou hodnotu nastavíte pro maximální hloubku.

Specifikace sql:max-depth na komplexních prvcích

Anotace sql:max-depth může být specifikována na jakémkoli složitém obsahovém prvku.

Rekurzivní prvky

Pokud je sql:max-depth specifikováno jak na rodičovském prvku, tak na podřízeném prvku v rekurzivním vztahu, má přednost anotace sql:max-depth specifikovaná na rodiči. Například v následujícím schématu je anotace sql:max-depth specifikována jak na rodičovském, tak na podřízeném zaměstnaneckém prvku. V tomto případě má přednost sql:max-depth=4, specifikovaný na mateřském <prvku Emp> (který hraje roli supervizora). Sql :max-depth specifikovaná na podřízeném <prvku Emp> (který hraje roli supervisee) je ignorována.

Příklad 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>  

Pro ověření tohoto schématu postupujte podle kroků uvedených ve Vzorku A, který jsem zde dříve v tomto tématu.

Nerekurzivní prvky

Pokud je anotace sql:max-depth specifikována na prvku schématu, který nezpůsobuje žádnou rekurzi, je ignorována. V následujícím schématu se Emp> prvek< skládá z konstantního podprvku<>, který má zase Emp podřízený prvek<>.

V tomto schématu je anotace sql:max-depth specifikovaná na prvku <Constant> ignorována, protože mezi rodičem <Emp> a potomkem <Constant> nedochází k rekurzi. Ale mezi předkem <Emp> a dítětem Emp> dochází k rekurzi.< Schéma specifikuje sql :max-depth anotaci na obou platformách. Proto má přednost anotace sql:max-depth specifikovaná na předkovi (<Emp> v roli supervizora).

Příklad 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>  

Pro ověření tohoto schématu postupujte podle kroků uvedených pro příklad A, který je uveden dříve v tomto tématu.

Komplexní typy odvozené restrikcí

Pokud máte odvození komplexního typu podle <omezení, prvky odpovídajícího základního komplexního typu nemohou specifikovat> sql :max-depth anotaci. V těchto případech lze k prvku odvozeného typu přidat anotaci sql:max-depth .

Na druhou stranu, pokud máte odvození komplexního typu rozšířením<>, prvky odpovídajícího základního komplexního typu mohou specifikovat sql:max-depth anotaci.

Například následující schéma XSD generuje chybu, protože sql :max-depth anotace je specifikována na základním typu. Tato anotace není podporována na typu, který je odvozen <omezením> z jiného typu. Pro vyřešení tohoto problému musíte změnit schéma a specifikovat sql :max-depth anotaci na prvku v odvozeném typu.

Příklad 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>   

Ve schématu je sql:max-depth specifikován na komplexním typu CustomerBaseType . Schéma také specifikuje prvek <zákazníka> typu CustomerType, který je odvozen z CustomerBaseType. Dotaz XPath specifikovaný na takovém schématu vygeneruje chybu, protože sql:max-depth není podporován na prvku definovaném v restrikčním základním typu.

Schémata s hlubokou hierarchií

Můžete mít schéma, které zahrnuje hlubokou hierarchii, kde prvek obsahuje podprvek, který zase obsahuje další podprvek, a tak dále. Pokud anotace sql:max-depth specifikovaná v takovém schématu vygeneruje XML dokument obsahující hierarchii více než 500 úrovní (s nejvyšším prvkem na úrovni 1, jeho potomkem na úrovni 2 a tak dále), chyba se vrátí.