다음을 통해 공유


sql:max-depth를 사용하여 재귀 관계의 깊이 지정

적용 대상: SQL ServerAzure SQL Database

관계형 데이터베이스에서 테이블이 자신과의 관계에 관련된 경우 이를 재귀 관계라고 합니다. 예를 들어 supervisor-supervisee 관계에서 직원 레코드를 저장하는 테이블은 자신과 관계가 있습니다. 이 경우 employees 테이블은 관계의 한쪽에서는 supervisor 역할을 하고 다른 쪽에서는 supervisee 역할을 합니다.

매핑 스키마에는 요소와 해당 상위 항목이 동일한 형식인 재귀 관계가 포함될 수 있습니다.

예 1

다음 테이블을 살펴보세요.

Emp (EmployeeID, FirstName, LastName, ReportsTo)  

이 표에서 ReportsTo 열은 관리자의 직원 ID를 저장합니다.

관리자 직원이 계층 구조의 맨 위에 있고 해당 관리자에게 보고하는 직원이 다음 샘플 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 쿼리를 지정할 수 있습니다. 스키마는 동일한 형식의 Emp 자식 요소인 EmployeeType으로 구성된< 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. 다음 템플릿을 복사하여 텍스트 파일에 붙여넣습니다. 파일을 maxDepth.xml 저장한 디렉터리에 maxDepthT.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> 요소에는 정확히 동일한 특성 집합(EmployeeID, FirstNameLastName)이 있었습니다. 다음 스키마는 관리자에게 보고하는 모든< 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 주석

재귀 관계로 구성된 스키마에서는 재귀 깊이를 스키마에 명시적으로 지정해야 합니다. 요청된 결과를 반환하는 해당 FOR XML EXPLICIT 쿼리를 성공적으로 생성하려면 이 작업이 필요합니다.

스키마에서 sql:max-depth 주석을 사용하여 스키마에 설명된 재귀 관계에서 재귀 깊이를 지정합니다. sql:max-depth 주석의 값은 재귀 횟수를 나타내는 양의 정수(1~50)입니다. 값 1은 sql:max-depth 주석이 지정된 요소에서 재귀를 중지하고, 값 2는 sql:max-depth가 지정된 요소에서 다음 수준에서 재귀를 중지합니다.

참고 항목

기본 구현에서 매핑 스키마에 대해 지정된 XPath 쿼리가 SELECT ... FOR XML EXPLICIT 쿼리입니다. 이 쿼리를 사용하려면 한정된 재귀 깊이를 지정해야 합니다. sql:max-depth에 대해 지정하는 값이 높을수록 생성된 FOR XML EXPLICIT 쿼리가 커집니다. 이로 인해 검색 시간이 느려질 수 있습니다.

참고 항목

Updategrams 및 XML 대량 로드에서는 max-depth 주석을 무시합니다. 즉, 최대 깊이에 대해 지정한 값에 관계없이 재귀 업데이트 또는 삽입이 발생합니다.

복잡한 요소에 대해 sql:max-depth 지정

모든 복잡한 콘텐츠 요소에 sql:max-depth 주석을 지정할 수 있습니다.

재귀 요소

재귀 관계의 부모 요소와 자식 요소 둘 다에 sql:max-depth를 지정하면 부모에 지정된 sql:max-depth 주석이 우선적으로 적용됩니다. 예를 들어 다음 스키마 에서 sql:max-depth 주석은 부모 및 자식 직원 요소 모두에 지정됩니다. 이 경우 Emp> 부모 요소(감독자 역할)에 <지정된 sql:max-depth=4가 우선합니다. 자식< Emp> 요소에 지정된 sql:max-depth(감독자 역할)는 무시됩니다.

예 2

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

이 스키마를 테스트하려면 이 항목의 앞부분에 있는 예 1에 제공된 단계를 따릅니다.

비재귀 요소

재귀를 일으키지 않는 스키마의 요소에 sql:max-depth 주석을 지정하면 무시됩니다. 다음 스키마<에서 Emp> 요소는 상수> 자식 요소로 구성<되며, 이 <요소에는 Emp> 자식 요소가 있습니다.

이 스키마에서는 Emp> 부모 요소와>< Constant 자식 요소 간에 <재귀가 없으므로 Constant> 요소에< 지정된 sql:max-depth 주석이 무시됩니다. 그러나 Emp 상위 항목과 Emp>> 자식 사이에<는 재귀가 <있습니다. 스키마는 둘 다에 대한 sql:max-depth 주석을 지정합니다. 따라서 상위 항목에 지정된 sql:max-depth 주석(<감독자 역할의 Emp> )이 우선적으로 적용됩니다.

예 3

<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 복합 형식에 지정됩니다. 스키마는 CustomerBaseType에서 파생된 CustomerType 형식의 Customer 요소도 지정합니다><. sql:max-depth는 제한 기본 형식에 정의된 요소에서 지원되지 않으므로 이러한 스키마에 지정된 XPath 쿼리는 오류를 생성합니다.

딥 계층 구조가 있는 스키마

요소에 자식 요소가 포함된 딥 계층 구조가 포함된 스키마가 있을 수 있습니다. 그러면 다른 자식 요소가 포함됩니다. 이러한 스키마에 지정된 sql:max-depth 주석이 500개 이상의 수준 계층 구조를 포함하는 XML 문서를 생성하는 경우(수준 1의 최상위 요소, 수준 2의 자식 포함) 오류가 반환됩니다.