인라인 XSD 스키마 생성

적용 대상:SQL ServerAzure SQL Database

FOR XML 절에서는 쿼리가 쿼리 결과와 함께 인라인 스키마를 반환하도록 요청할 수 있습니다. XDR 스키마를 원하는 경우 FOR XML 절에서 XMLDATA 키워드를 사용합니다. XSD 스키마를 원하는 경우 XMLSCHEMA 키워드를 사용합니다.

이 문서에서는 XMLSCHEMA 키워드를 설명하고 결과 인라인 XSD 스키마의 구조를 설명합니다. 인라인 스키마를 요청할 때의 제한 사항은 다음과 같습니다.

  • XMLSCHEMA는 RAW 및 AUTO 모드에서만 지정할 수 있으며 EXPLICIT 모드에서는 지정할 수 없습니다.

  • 중첩 FOR XML 쿼리에 TYPE 지시어를 지정하는 경우 쿼리 결과는 xml 형식이 되며 형식화되지 않은 XML 데이터의 인스턴스로 취급됩니다. 자세한 내용은 XML 데이터(SQL Server)를 참조하세요.

FOR XML 쿼리에서 XMLSCHEMA를 지정하면 스키마와 XML 데이터, 쿼리 결과가 모두 표시됩니다. 데이터의 각 최상위 요소는 인라인 스키마의 대상 네임스페이스를 참조하는 기본 네임스페이스 선언을 사용하여 이전 스키마를 참조합니다.

예:

<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
  <xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="https://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
  <xsd:element name="Production.ProductModel">
    <xsd:complexType>
      <xsd:attribute name="ProductModelID" type="sqltypes:int" use="required" />
      <xsd:attribute name="Name" use="required">
        <xsd:simpleType sqltypes:sqlTypeAlias="[AdventureWorks2022].[dbo].[Name]">
          <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
            <xsd:maxLength value="50" />
          </xsd:restriction>
        </xsd:simpleType>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
<Production.ProductModel xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1" ProductModelID="1" Name="Classic Vest" />

결과에는 XML 스키마와 XML 결과가 포함됩니다. <ProductModel> 결과의 최상위 요소는 기본 네임스페이스 선언 xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1"을 사용하여 스키마를 참조합니다.

결과의 스키마 부분에는 여러 네임스페이스를 설명하는 여러 스키마 문서가 포함될 수 있습니다. 최소한 다음 두 스키마 문서가 반환됩니다.

  • Sqltypes 네임스페이 스에 대한 하나의 스키마 문서와 기본 SQL 형식이 반환되는 문서입니다.

  • FOR XML 쿼리 결과의 모양을 설명하는 또 다른 스키마 문서입니다.

또한 형식화된 xml 데이터 형식이 쿼리 결과에 포함된 경우 형식화된 xml 데이터 형식과 연결된 스키마가 포함됩니다.

FOR XML 결과의 모양을 설명하는 스키마 문서의 대상 네임스페이스에는 자동으로 증가되는 고정 부분과 숫자 부분이 포함됩니다. 이 네임스페이스의 형식은 n이 양의 정수인 다음과 같습니다. 예를 들어 이전 쿼리에서 urn:schemas-microsoft-com:sql:SqlRowSet1은 대상 네임스페이스입니다.

urn:schemas-microsoft-com:sql:SqlRowSetn

결과의 대상 네임스페이스는 실행될 때마다 내용이 변경되지 않는 것이 좋습니다. 예를 들어 결과 XML을 쿼리하는 경우 대상 네임스페이스를 변경하려면 쿼리를 업데이트해야 합니다. 필요에 따라 FOR XML 절에 XMLSCHEMA 옵션이 추가되면 대상 네임스페이스를 지정할 수 있습니다. 결과 XML에는 사용자가 제공한 네임스페이스가 포함되며 쿼리를 실행하는 횟수에 관계없이 동일하게 유지됩니다.

SELECT ProductModelID, Name
FROM   Production.ProductModel
WHERE ProductModelID=1
FOR XML AUTO, XMLSCHEMA ('MyURI');

엔터티 요소

쿼리 결과에 대해 생성된 XSD 스키마 구조의 세부 내용을 다루기 전에 엔터티 요소에 대해 먼저 이해해야 합니다.

FOR XML 쿼리에서 반환된 XML 데이터의 엔터티 요소는 열이 아닌 테이블에서 생성되는 요소입니다. 예를 들어 다음 FOR XML 쿼리는 데이터베이스의 Person 테이블에서 AdventureWorks2022 연락처 정보를 반환합니다.

SELECT BusinessEntityID, FirstName
FROM Person.Person
WHERE BusinessEntityID = 1
FOR XML AUTO, ELEMENTS;

결과는 다음과 같습니다.

<Person>
  <BusinessEntityID>1</BusinessEntityID>
  <FirstName>Ken</FirstName>
</Person>

이 결과에서 <Person> 엔터티 요소입니다. XML 결과에는 여러 엔터티 요소가 있을 수 있으며 각 엔터티에는 인라인 XSD 스키마에 전역 선언이 있습니다. 예를 들어 다음 쿼리는 판매 주문 제목과 특정 주문에 대한 세부 정보를 검색합니다.

SELECT  SalesOrderHeader.SalesOrderID, ProductID, OrderQty
FROM    Sales.SalesOrderHeader, Sales.SalesOrderDetail
WHERE   SalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID
AND     SalesOrderHeader.SalesOrderID=5001
FOR XML AUTO, ELEMENTS, XMLSCHEMA;

쿼리가 ELEMENTS 지시문을 지정하므로 결과 XML은 요소 중심입니다. 또한 이 쿼리는 XMLSCHEMA 지시문을 지정합니다. 따라서 인라인 XSD 스키마가 반환됩니다. 결과는 다음과 같습니다.

<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
  <xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="https://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
  <xsd:element name="Sales.SalesOrderHeader">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="SalesOrderID" type="sqltypes:int" />
        <xsd:element ref="schema:Sales.SalesOrderDetail" minOccurs="0" maxOccurs="unbounded" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="Sales.SalesOrderDetail">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="ProductID" type="sqltypes:int" />
        <xsd:element name="OrderQty" type="sqltypes:smallint" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

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

  • 결과 <SalesOrderHeader><SalesOrderDetail> 에서 엔터티 요소입니다. 이 때문에 스키마에서 전역적으로 선언됩니다. 즉, 선언이 요소 내 <Schema> 의 최상위 수준에 나타납니다.

  • 열에 <SalesOrderID><OrderQty> 매핑되므로 엔<ProductID>터티 요소가 아닙니다. 열 데이터는 ELEMENTS 지시문 때문에 XML의 요소로 반환됩니다. 이러한 데이터는 엔터티 요소의 복합 유형에 대한 로컬 요소로 매핑됩니다. ELEMENTS 지시문을 지정 SalesOrderID하지 않으면 해당 ProductID 엔터티 요소의 복합 형식의 로컬 특성에 해당 값과 OrderQty 값이 매핑됩니다.

특성 이름 충돌

다음 토론은 테이블과 CustOrderDetail 테이블을 기반으로 합니다CustOrder. 다음 샘플을 테스트하려면 이러한 테이블을 만들고 고유한 샘플 데이터를 추가합니다.

CREATE TABLE CustOrder (OrderID int primary key, CustomerID int);
GO
CREATE TABLE CustOrderDetail (OrderID int, ProductID int, Qty int);
GO

FOR XML에서 일부 경우에는 동일 이름을 사용하여 서로 다른 속성과 특성을 나타냅니다. 예를 들어 다음 특성 중심 RAW 모드 쿼리는 이름이 같은 두 특성인 OrderID를 생성합니다. 이렇게 하면 오류가 발생합니다.

SELECT CustOrder.OrderID,
       CustOrderDetail.ProductID,
       CustOrderDetail.OrderID
FROM   dbo.CustOrder, dbo.CustOrderDetail
WHERE  CustOrder.OrderID = CustOrderDetail.OrderID
FOR XML RAW, XMLSCHEMA;

그러나 이름이 같은 두 요소를 사용할 수 있으므로 ELEMENTS 지시문을 추가하여 문제를 제거할 수 있습니다.

SELECT CustOrder.OrderID,
       CustOrderDetail.ProductID,
       CustOrderDetail.OrderID
from   dbo.CustOrder, dbo.CustOrderDetail
where  CustOrder.OrderID = CustOrderDetail.OrderID
FOR XML RAW, XMLSCHEMA, ELEMENTS;

이것이 결과입니다. 인라인 XSD 스키마에서 OrderID 요소는 두 번 정의됩니다. 선언 중 하나에는 custOrderDetail 테이블의 OrderID에 해당하는 minOccurs가 0으로 설정되고, 두 번째 선언은 minOccurs가 기본적으로 1인 테이블의 CustOrder OrderID 기본 키 열에 매핑됩니다.

<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="https://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
  <xsd:element name="row">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="OrderID" type="sqltypes:int" />
        <xsd:element name="ProductID" type="sqltypes:int" minOccurs="0" />
        <xsd:element name="OrderID" type="sqltypes:int" minOccurs="0" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

요소 이름 충돌

FOR XML에서 동일한 이름을 사용하여 두 개의 하위 개체를 나타낼 수 있습니다. 예를 들어 다음 쿼리는 제품의 ListPrice 및 DealerPrice 값을 검색하지만 쿼리는 이러한 두 열에 대해 동일한 별칭인 Price를 지정합니다. 따라서 결과 행 집합에는 이름이 같은 두 개의 열이 있습니다.

사례 1: 두 하위 요소 모두 동일한 형식의 키가 아닌 열이며 NULL일 수 있습니다.

다음 쿼리에서 두 하위 요소는 동일한 형식의 키가 아닌 열이며 NULL일 수 있습니다.

DROP TABLE T;
GO
CREATE TABLE T (ProductID int primary key, ListPrice money, DealerPrice money);
GO
INSERT INTO T values (1, 1.25, null);
GO

SELECT ProductID, ListPrice Price, DealerPrice Price
FROM   T
for    XML RAW, ELEMENTS, XMLSCHEMA;

생성된 해당 XML입니다. 인라인 XSD의 일부만 표시됩니다.

...
<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" />
  <xsd:element name="row">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="ProductID" type="sqltypes:int" />
        <xsd:element name="Price" type="sqltypes:money" minOccurs="0" maxOccurs="2" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
<row xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
  <ProductID>1</ProductID>
  <Price>1.2500</Price>
</row>

인라인 XSD 스키마에서 다음을 확인합니다.

  • ListPrice와 DealerPrice는 모두 동일한 형식 money이며 둘 다 테이블에서 NULL일 수 있습니다. 따라서 결과 XML에서 반환되지 않을 수 있으므로 요소의 복합 형식 선언 <row>minOccurs=0 에는 자식 요소가 하나 <Price> 만 있습니다maxOccurs=2.

  • 결과에서 값은 테이블의 DealerPrice NULL이므로 요소로 <Price>ListPrice 반환됩니다. ELEMENTS 지시문에 매개 변수를 추가 XSINIL 하면 DealerPrice에 해당하는 요소에 대해<Price> 값이 xsi:nil TRUE로 설정된 두 요소를 모두 받게 됩니다. 또한 인라인 XSD 스키마의 <row> 복합 형식 정의에 두 개의 <Price> 자식 요소가 표시되며 특성이 nillable 둘 다 TRUE로 설정됩니다. 이 조각은 부분적인 결과입니다.

...
<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" />
  <xsd:element name="row">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="ProductID" type="sqltypes:int" nillable="1" />
        <xsd:element name="Price" type="sqltypes:money" nillable="1" />
        <xsd:element name="Price" type="sqltypes:money" nillable="1" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
<row xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ProductID>1</ProductID>
  <Price>1.2500</Price>
  <Price xsi:nil="true" />
</row>

사례 2: 키 1개와 키가 아닌 열 1개

다음 쿼리는 동일한 형식의 키와 키가 아닌 열 하나를 보여 줍니다.

CREATE TABLE T (Col1 int primary key, Col2 int, Col3 nvarchar(20));
GO
INSERT INTO T VALUES (1, 1, 'test');
GO

테이블 T 에 대한 다음 쿼리는 Col1 및 Col2에 대해 같은 별칭을 지정하며, 여기서 Col1은 기본 키이며 Null일 수 없고 Col2는 Null일 수 있습니다. 이렇게 하면 요소의 <row> 자식인 두 형제 요소가 생성됩니다.

SELECT Col1 as Col, Col2 as Col, Col3
FROM T
FOR XML RAW, ELEMENTS, XMLSCHEMA

이것이 결과입니다. 인라인 XSD 스키마의 조각만 표시됩니다.

...
<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" />
  <xsd:element name="row">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="Col" type="sqltypes:int" />
        <xsd:element name="Col" type="sqltypes:int" minOccurs="0" />
        <xsd:element name="Col3" minOccurs="0">
          <xsd:simpleType>
            <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
              <xsd:maxLength value="20" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
<row xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
  <Col>1</Col>
  <Col>1</Col>
  <Col3>test</Col3>
</row>

인라인 XSD 스키마에서 Col2에 해당하는 요소에 <Col> minOccurs가 0으로 설정되어 있습니다.

사례 3: 서로 다른 형식의 요소와 해당 열은 모두 NULL일 수 있습니다.

다음 쿼리는 사례 2에 표시된 예제 테이블에 대해 지정됩니다.

SELECT Col1, Col2 as Col, Col3 as Col
FROM T
FOR XML RAW, ELEMENTS, XMLSCHEMA;

다음 쿼리에서 Col2 및 Col3에는 동일한 별칭이 제공됩니다. 이렇게 하면 이름이 같고 결과에 있는 요소의 <raw> 자식인 두 형제 요소가 생성됩니다. 이러한 두 열은 서로 다른 형식이며 둘 다 NULL일 수 있습니다. 이것이 결과입니다. 부분 인라인 XSD 스키마만 표시됩니다.

...
<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" />
  <xsd:simpleType name="Col1">
    <xsd:restriction base="sqltypes:int" />
  </xsd:simpleType>
  <xsd:simpleType name="Col2">
    <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
      <xsd:maxLength value="20" />
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:element name="row">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="Col1" type="sqltypes:int" />
        <xsd:element name="Col" minOccurs="0" maxOccurs="2" type="xsd:anySimpleType" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
<row xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
  <Col1>1</Col1>
  <Col xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Col1">1</Col>
  <Col xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Col2">test</Col>
</row>

인라인 XSD 스키마에서 다음을 확인합니다.

  • Col2와 Col3은 모두 NULL <Col> 일 수 있으므로 요소 선언은 minOccurs를 0으로, maxOccurs를 2로 지정합니다.

  • 두 요소가 모두 <Col> 형제이므로 스키마에는 하나의 요소 선언이 있습니다. 또한 두 요소 모두 서로 다른 형식이기 때문에 둘 다 단순 형식이지만 스키마에 있는 요소의 형식은 다음과 같습니다 xsd:anySimpleType. 결과에서 각 인스턴스 형식은 특성으로 xsi:type 식별됩니다.

  • 결과에서 요소의 <Col> 모든 인스턴스는 특성을 사용하여 해당 인스턴스 형식을 xsi:type 참조합니다.