다음을 통해 공유


FOR XML 쿼리 및 중첩 FOR XML 쿼리 비교

적용 대상: SQL Server Azure SQL Database Azure SQL Managed Instance

이 문서에서는 단일 수준 FOR XML 쿼리를 중첩FOR XML 쿼리와 비교합니다. 중첩된 FOR XML 쿼리를 사용할 경우의 이점 중 하나는 쿼리 결과에 특성 중심 및 요소 중심 XML의 조합을 지정할 수 있다는 것입니다. 이 예제에서는 이러한 이점을 보여 줍니다.

이 문서의 Transact-SQL 코드 샘플은 AdventureWorks2022 또는 AdventureWorksDW2022 샘플 데이터베이스를 사용하며, 이는 Microsoft SQL Server 예시 및 커뮤니티 프로젝트 홈 페이지에서 다운로드할 수 있습니다.

예제

다음 SELECT 쿼리는 AdventureWorks2022 데이터베이스에서 제품 범주와 하위 범주 정보를 검색합니다. 쿼리에 중첩 FOR XML이 없습니다.

USE AdventureWorks2022;
GO

SELECT ProductCategory.ProductCategoryID,
    ProductCategory.Name AS CategoryName,
    ProductSubCategory.ProductSubCategoryID,
    ProductSubCategory.Name
FROM Production.ProductCategory,
    Production.ProductSubCategory
WHERE ProductCategory.ProductCategoryID = ProductSubCategory.ProductCategoryID
ORDER BY ProductCategoryID
FOR XML AUTO, TYPE;
GO

다음은 결과의 일부입니다.

<ProductCategory ProductCategoryID="1" CategoryName="Bike">
  <ProductSubCategory ProductSubCategoryID="1" Name="Mountain Bike"/>
  <ProductSubCategory ProductSubCategoryID="2" Name="Road Bike"/>
  <ProductSubCategory ProductSubCategoryID="3" Name="Touring Bike"/>
</ProductCategory>
...

쿼리에서 ELEMENTS 지시문을 지정하면 다음 결과 조각과 같이 요소 중심 결과가 수신됩니다.

<ProductCategory>
  <ProductCategoryID>1</ProductCategoryID>
  <CategoryName>Bike</CategoryName>
  <ProductSubCategory>
    <ProductSubCategoryID>1</ProductSubCategoryID>
    <Name>Mountain Bike</Name>
  </ProductSubCategory>
  <ProductSubCategory>
     ...
  </ProductSubCategory>
</ProductCategory>

다음으로, 다음 조각과 같이 특성 중심 XML과 요소 중심 XML의 조합인 XML 계층을 생성한다고 가정합니다.

<ProductCategory ProductCategoryID="1" CategoryName="Bike">
  <ProductSubCategory>
    <ProductSubCategoryID>1</ProductSubCategoryID>
    <SubCategoryName>Mountain Bike</SubCategoryName></ProductSubCategory>
  <ProductSubCategory>
     ...
  <ProductSubCategory>
     ...
</ProductCategory>

이전 조각에서 범주 ID 및 범주 이름과 같은 제품 범주 정보는 특성입니다. 그러나 하위 범주 정보는 요소 중심입니다. <ProductCategory> 요소를 생성하기 위해 다음과 같이 FOR XML 쿼리를 작성할 수 있습니다.

SELECT ProductCategoryID,
    Name AS CategoryName
FROM Production.ProductCategory ProdCat
ORDER BY ProductCategoryID
FOR XML AUTO, TYPE;

결과:

< ProdCat ProductCategoryID="1" CategoryName="Bikes" />
< ProdCat ProductCategoryID="2" CategoryName="Components" />
< ProdCat ProductCategoryID="3" CategoryName="Clothing" />
< ProdCat ProductCategoryID="4" CategoryName="Accessories" />

원하는 XML에서 중첩 <ProductSubCategory> 요소를 생성하려면 다음 코드 샘플과 같이 중첩 FOR XML 쿼리를 추가합니다.

SELECT ProductCategoryID,
    Name AS CategoryName,
    (
        SELECT ProductSubCategoryID, Name AS SubCategoryName
        FROM Production.ProductSubCategory
        WHERE ProductSubCategory.ProductCategoryID = ProductCategory.ProductCategoryID
        FOR XML AUTO, TYPE, ELEMENTS
    )
FROM Production.ProductCategory
ORDER BY ProductCategoryID
FOR XML AUTO, TYPE;

이전 쿼리의 다음 사항에 유의하세요.

  • 내부 FOR XML 쿼리는 제품 하위 범주 정보를 검색합니다. 외부 쿼리에서 생성된 XML에 추가되는 요소 중심 XML을 생성하기 위해 내부 FOR XMLELEMENTS 지시문이 추가됩니다. 기본적으로 외부 쿼리는 특성 중심 XML을 생성합니다.

  • 내부 쿼리에서 결과가 xml 형식이 되도록 TYPE 지시문이 지정됩니다. TYPE을 지정하지 않으면 결과가 nvarchar(max) 형식으로 반환되고 XML 데이터가 엔터티로 반환됩니다.

  • 다음 쿼리는 TYPE 지시문도 지정합니다. 따라서 이 쿼리의 결과는 xml 형식으로 클라이언트에 반환됩니다.

다음은 결과의 일부입니다.

<ProductCategory ProductCategoryID="1" CategoryName="Bike">
  <ProductSubCategory>
    <ProductSubCategoryID>1</ProductSubCategoryID>
    <SubCategoryName>Mountain Bike</SubCategoryName></ProductSubCategory>
  <ProductSubCategory>
     ...
  <ProductSubCategory>
     ...
</ProductCategory>

다음 쿼리는 이전 쿼리의 확장에 불과합니다. AdventureWorks2022 데이터베이스의 전체 제품 계층 구조가 표시됩니다. 다음 내용이 포함됩니다.

  • 제품 범주
  • 각 범주의 제품 하위 범주
  • 각 하위 범주의 제품 모델
  • 각 모델의 제품

다음 쿼리는 AdventureWorks2022 데이터베이스를 이해하는 데 도움이 됩니다.

SELECT ProductCategoryID,
    Name AS CategoryName,
    (
        SELECT ProductSubCategoryID,
            Name AS SubCategoryName,
            (
                SELECT ProductModel.ProductModelID,
                    ProductModel.Name AS ModelName,
                    (
                        SELECT ProductID, Name AS ProductName, Color
                        FROM Production.Product
                        WHERE Product.ProductModelID = ProductModel.ProductModelID
                        FOR XML AUTO, TYPE
                    )
                FROM (
                    SELECT DISTINCT ProductModel.ProductModelID, ProductModel.Name
                    FROM Production.ProductModel, Production.Product
                    WHERE ProductModel.ProductModelID = Product.ProductModelID
                        AND Product.ProductSubCategoryID = ProductSubCategory.ProductSubCategoryID
                    ) ProductModel
                FOR XML AUTO, TYPE
                )
        FROM Production.ProductSubCategory
        WHERE ProductSubCategory.ProductCategoryID = ProductCategory.ProductCategoryID
        FOR XML AUTO, TYPE, ELEMENTS
    )
FROM Production.ProductCategory
ORDER BY ProductCategoryID
FOR XML AUTO, TYPE;

다음은 결과의 일부입니다.

<Production.ProductCategory ProductCategoryID="1" CategoryName="Bikes">
  <Production.ProductSubCategory>
    <ProductSubCategoryID>1</ProductSubCategoryID>
    <SubCategoryName>Mountain Bikes</SubCategoryName>
    <ProductModel ProductModelID="19" ModelName="Mountain-100">
      <Production.Product ProductID="771"
                ProductName="Mountain-100 Silver, 38" Color="Silver" />
      <Production.Product ProductID="772"
                ProductName="Mountain-100 Silver, 42" Color="Silver" />
      <Production.Product ProductID="773"
                ProductName="Mountain-100 Silver, 44" Color="Silver" />
        ...
    </ProductModel>
     ...

제품 하위 범주를 생성하는 중첩된 ELEMENTS 쿼리에서 FOR XML 지시어를 제거하면 전체 결과가 특성 중심이 됩니다. 그런 다음 중첩하지 않고 이 쿼리를 작성할 수 있습니다. 부분적으로 특성 중심이고 부분적으로 요소 중심인 XML에 ELEMENTS 결과를 추가합니다. 이 결과는 단일 수준 FOR XML 쿼리로 생성할 수 없습니다.