Megosztás a következőn keresztül:


Mélység megadása rekurzív kapcsolatokban az sql:max-depth használatával

A következőkre vonatkozik:SQL ServerAzure SQL Database

Relációs adatbázisokban, amikor egy tábla önmagával kapcsolatban áll, azt rekurzív kapcsolatnak nevezik. Például egy felügyelő-felügyelő kapcsolatban egy táblázat, amely dolgozói nyilvántartásokat tárol, önmagával való kapcsolatban áll. Ebben az esetben az alkalmazotti asztal a kapcsolat egyik oldalán felügyelő szerepét tölti be, míg ugyanaz az asztal a másik oldalon felügyelő szerepet.

A leképezési sémák tartalmazhatnak rekurzív kapcsolatokat, ahol egy elem és őse azonos típusú.

A példa

Vegyük a következő táblázatot:

Emp (EmployeeID, FirstName, LastName, ReportsTo)  

Ebben a táblázatban a ReportsTo oszlop tárolja a vezető alkalmazotti azonosítóját.

Tegyük fel, hogy egy XML hierarchiát szeretnél létrehozni az alkalmazottakról, amelyben a menedzser dolgozó a hierarchia tetején van, és ahol a vezetőnek jelentő alkalmazottak a megfelelő hierarchiában jelennek meg, ahogy azt a következő XML töredék mutatja. Ez a fragmentum a rekurzív fa az 1. alkalmazott számára.

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

Ebben a fragmentumban az 5-ös dolgozó jelent a 4-es alkalmazottnak, a 4-es alkalmazott a 3-as alkalmazottnak, a 3. és 2. alkalmazott pedig az 1. alkalmazottnak jelent.

Ennek eléréséhez a következő XSD sémát használhatod, és megadhatsz egy XPath lekérdezést ellene. A séma egy <EmployeeType típusú Alkalmazott> elemet ír le, amely egy <azonos típusú EmployeeType Alkalmazott> gyermekelemből áll. Ez egy rekurzív kapcsolat (az elem és őse ugyanabból a típusból áll). Ezen felül a séma sql<:kapcsolatot> használ a felügyelő és a felügyelt közötti szülő-gyermek kapcsolat leírására. Fontos megjegyezni, hogy ebben <a sql:relationshipben> az emp mind a szülő, mind a gyermek tábla.

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

Mivel a kapcsolat rekurzív, szükséged van valamilyen módra arra, hogy meghatározd a rekurzió mélységét a sémában. Ellenkező esetben végtelen rekurzió lesz (az alkalmazott jelentése a munkavállalónak, jelentés az alkalmazottnak, és így tovább). A sql:max-depth annotáció lehetővé teszi, hogy meghatározd, milyen mélyre kell menned a rekurzióban. Ebben a konkrét példában, hogy meghatározd a sql:max-depth értékét, tudnod kell, mennyire mély a menedzsment hierarchia a cégben.

Megjegyzés:

A séma megadja a sql:limit-mező annotációt, de a sql:limit-érték annotációt nem határozza meg. Ez a hierarchia felső csomópontját csak azokra az alkalmazottakra korlátozza, akik senkinek sem jelentenek. (A ReportsTo nulla.) A sql:limit-field megadása, és a sql:limit-value (amely alapértelmezett NULL) annotáció megjelölése ezt biztosítja. Ha azt szeretnéd, hogy az eredmény XML-e minden lehetséges jelentésfát tartalmazzon (a táblázatban minden alkalmazott jelentési fája), távolítsd el a sql:limit mező annotációt a sémából.

Megjegyzés:

A következő eljárás a tempdb adatbázist használja.

Egy minta-XPath lekérdezés tesztelése a sémához

  1. Hozz létre egy mintatáblát, amit Emp néven hívnak a tempdb adatbázisban, amelyre a virtuális gyökér mutat.

    USE tempdb  
    CREATE TABLE Emp (  
           EmployeeID int primary key,   
           FirstName  varchar(20),   
           LastName   varchar(20),   
           ReportsTo int)  
    
  2. Add hozzá ezt a mintaadatot:

    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. Másold le a fenti sémakódot, és illesztsd be egy szövegfájlba. Mentse el a fájlt maxDepth.xml.

  4. Másold le a következő sablont, és illesztsd be egy szövegfájlba. Mentsd a fájlt maxDepthT.xml-ként ugyanabba a könyvtárba, ahol maxDepth.xmlmentetted. A sablonban lévő lekérdezés visszaadja az összes alkalmazottat az EMP táblában.

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

    A leképezési sémához (maxDepth.xml) megadott könyvtári út viszonyítja azt a könyvtárat, ahol a sablon mentő. Abszolút út is meghatározható, például:

    mapping-schema="C:\MyDir\maxDepth.xml"  
    
  5. Hozd létre és használd az SQLXML 4.0 Test Scriptet (Sqlxml4test.vbs) a sablon végrehajtásához. További információ: SqlXML 4.0-lekérdezések végrehajtása az ADO használatával.

Ez az eredmény:

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

Megjegyzés:

A különböző hierarchia mélységek eléréséhez módosítsuk a sémában a sql:max-mélységi annotáció értékét, és minden változtatás után újra hajtsuk végre a sablont.

Az előző sémában az összes< Employ> elem pontosan ugyanazt az attribútumhalmazt tartalmazta (Alkalmazottazonosító, Keresztnév és Vezetéknév). A következő sémát kissé módosították, hogy minden EMP> elem számára egy további ReportsTo attribútumot< adjon, amely egy kezelőnek jelent.

Például ez az XML töredék az 1. alkalmazott alárendeltjeit mutatja:

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

Ez a módosított sé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 Annotáció

Egy rekurzív kapcsolatokból álló sémában a rekurzió mélységét kifejezetten meg kell határozni a sémában. Ez szükséges ahhoz, hogy sikeresen elhozza a megfelelő XML EXPLICIT lekérdezést, amely visszaadja a kért eredményeket.

Használjuk a sémában a sql:max-mélységi annotációt arra, hogy meghatározd a rekurzió mélységét egy rekurzív kapcsolatban, amelyet a séma leír. A sql:max-mélységi annotáció értéke egy pozitív egész szám (1-től 50-ig), amely a rekurziók számát jelzi: 1 érték megállítja a rekurziót azon az elemnél, amelyre a sql:max-mélységi annotációt megadták; 2 érték megállítja a rekurziót a következő szinten attól az elemtől, ahol a SQL:max-depth van megadva; és így tovább.

Megjegyzés:

Az alapimplementációban egy XPath lekérdezés, amelyet egy leképezési sémához jelölnek, átalakítva SELECT-re alakul ... XML EXPLICIT lekérdezés esetén. Ez a lekérdezés megköveteli, hogy meghatározd a véges rekursziós mélységet. Minél magasabb az érték, amit sql:max-depth-re állítasz, annál nagyobb a generált FOR XML EXPLICIT lekérdezés. Ez lassíthatja a visszaszerzési időt.

Megjegyzés:

A Updategrams és az XML Bulk Load figyelmen kívül hagyja a maximális mélységű annotációt. Ez azt jelenti, hogy rekurzív frissítések vagy beillesztések függetlenül történnek, hogy milyen értéket adsz meg a maximális mélységhez.

Sql:max-mélység meghatározása összetett elemekhez

A sql:max-mélységi annotáció bármely összetett tartalmi elemre megadható.

Rekurzív elemek

Ha sql:max-depth mind a szülőelemen, mind a gyermekelemen van megadva, rekurzív kapcsolatban, akkor a sql:max-mélység annotáció a szülőnél helyezkedik el az elsőbbséget. Például a következő sémában a sql:max-mélység annotáció mind a szülő, mind a gyermek alkalmazotti elemeken van megadva. Ebben az esetben az emp szülőelemen (felügyelő szerepet) meghatározott sql:max-depth=4<> kerül előtérbe. A gyermek <EMP> elemen (amely felügyelt szerepet tölt be) megadott sql:max-mélységet figyelmen kívül hagyjuk.

B példa

<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 séma teszteléséhez kövesse a téma korábbi A mintájához megadott lépéseket.

Nem rekurzív elemek

Ha a sql:max-mélységi annotációt egy olyan elemen van megadva, amely nem okoz rekurziót, akkor figyelmen kívül hagyjuk. A következő sémában egy <Emp> elem egy <állandó> gyermekelemből áll, amely viszont rendelkezik egy< Emp> gyermekelemmel.

Ebben a sémában a Constant> elemen megadott sql:max-mélységi annotációt< figyelmen kívül hagyjuk, mert nincs rekurzió az <Emp> szülő és a< Constant> gyermekelem között. De rekurzió van az <Emp> ős és az <Emp> gyermek között. A séma mindkét sql:max-mélységi annotációt tartalmazza. Ezért az ősnél (<Emp> a felügyelői szerepben) meghatározott sql:max-mélységi annotáció kerül előtérbe.

C példa

<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 séma teszteléséhez kövesse a korábbi A példához megadott lépéseket.

Korlátozóval származtatott komplex típusok

Ha van egy komplex típus levezetése korlátozással<>, a megfelelő alap komplex típus elemei nem tudják megadni a sql:max-mélységi annotációt. Ilyen esetekben a sql:max-mélységi annotáció hozzáadható a származtatott típus eleméhez.

Másrészt, ha van egy összetett típus kiterjesztés<> szerinti levezetés, akkor a megfelelő alap komplex típus elemei megadhatják a sql:max-mélységi annotációt.

Például a következő XSD séma hibát generál, mert az alap típuson a sql:max-mélységi annotáció van megadva. Ez az annotáció nem támogatott olyan típusnál, amely egy <másik típusból való korlátozással> származik. Ennek a problémának a megoldásához meg kell változtatnod a sémát, és meg kell határoznod a sql:max-mélység annotációt az elemen a származtatott típusban.

D példa

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

A sémában a sql:max-depth egy CustomerBaseType komplex típuson van megadva. A séma egy <CustomerType típusú ügyfélelemet> is megad, amely a CustomerBaseType típusból származik. Egy ilyen sémán megadott XPath lekérdezés hibát generál, mert a sql:max-depth nem támogatott olyan elemen, amely egy korlátozó alaptípusban van definiálva.

Sémák mély hierarchiával

Lehet, hogy van egy sémá, amely mély hierarchiát tartalmaz, amelyben egy elem tartalmaz egy gyermekelemet, amely viszont egy másik gyermekelemet tartalmaz, és így tovább. Ha az ilyen sémában megadott sql:max-mélységi annotáció egy olyan XML dokumentumot generál, amely több mint 500 szintből álló hierarchiát tartalmaz (a felső szintű elem az 1. szinten, a gyermeke a 2. szinten, stb.), akkor hiba jelenik meg.