다음을 통해 공유


WITH XMLNAMESPACES를 사용하여 쿼리에 네임스페이스 추가

적용 대상: SQL Server Azure SQL 데이터베이스 Azure SQL Managed Instance

WITH XMLNAMESPACES(Transact-SQL)는 다음과 같은 방식으로 네임스페이스 URI를 지원합니다.

  • 이 명령은 Constructing XML Using FOR XML 쿼리를 수행할 때 네임스페이스 접두사를 URI 매핑에 사용할 수 있게 합니다.

  • 이 명령은 xml 데이터 형식 메서드의 정적 네임스페이스 컨텍스트에서 네임스페이스에서 URI 매핑을 사용할 수 있게 합니다.

WITH XMLNAMESPACES in FOR XML 쿼리 사용

WITH XMLNAMESPACES를 사용하면 FOR XML 쿼리에 XML 네임스페이스를 포함할 수 있습니다. 예를 들어, 다음 FOR XML 쿼리를 생각해 보겠습니다.

SELECT ProductID, Name, Color
FROM   Production.Product
WHERE  ProductID IN (316, 317)
FOR XML RAW;

다음은 결과입니다.

<row ProductID="316" Name="Blade" />
<row ProductID="317" Name="LL Crankarm" Color="Black" />

FOR XML 쿼리에 의해 생성된 XML에 네임스페이스를 추가하려면 먼저 WITH NAMESPACES 절을 사용하여 URI 매핑에 네임스페이스 접두사를 지정합니다. 그런 후 다음의 수정된 쿼리에서와 같이 쿼리의 이름을 지정할 때 네임스페이스 접두사를 사용합니다. WITH XMLNAMESPACES 절은 네임스페이스 접두사(ns1)와 URI(uri) 매핑을 지정합니다. ns1 접두사는 FOR XML 쿼리에 의해 생성되는 요소 및 특성 이름을 지정하는 데 사용됩니다.

WITH XMLNAMESPACES ('uri' as ns1)
SELECT ProductID as 'ns1:ProductID',
       Name      as 'ns1:Name',
       Color     as 'ns1:Color'
FROM  Production.Product
WHERE ProductID IN (316, 317)
FOR XML RAW ('ns1:Prod'), ELEMENTS;

XML 결과에는 네임스페이스 접두사가 포함됩니다.

<ns1:Prod xmlns:ns1="uri">
  <ns1:ProductID>316</ns1:ProductID>
  <ns1:Name>Blade</ns1:Name>
</ns1:Prod>
<ns1:Prod xmlns:ns1="uri">
  <ns1:ProductID>317</ns1:ProductID>
  <ns1:Name>LL Crankarm</ns1:Name>
  <ns1:Color>Black</ns1:Color>
</ns1:Prod>

다음은 WITH XMLNAMESPACES 절에 적용되는 사항입니다.

  • 이 절은 FOR XML 쿼리의 RAW, AUTO 및 PATH 모드에서만 지원됩니다. EXPLICIT 모드는 지원되지 않습니다.

  • 이는 FOR XML 쿼리의 네임스페이스 접두사 및 xml 데이터 형식 메서드에만 영향을 미치며 XML 구문 분석기에는 영향을 미치지 않습니다. 예를 들어, 다음 쿼리는 XML 문서에 myNS 접두사에 대한 네임스페이스 선언이 없기 때문에 오류를 반환합니다.

  • WITH XMLNAMESPACES 절을 사용하는 경우 FOR XML 지시어, XMLSCHEMA 및 XMLDATA를 사용할 수 없습니다.

    CREATE TABLE T (x xml);
    GO
    WITH XMLNAMESPACES ('https://abc' as myNS )
    INSERT INTO T VALUES('<myNS:root/>');
    GO
    

XSINIL 지시어 사용

ELEMENTS XSINIL 지시어를 사용하는 경우 WITH XMLNAMESPACES 절에서 xsi 접두사를 정의할 수 없습니다. 대신 ELEMENTS XSINIL을 사용하면 자동으로 추가됩니다. 다음 쿼리는 xsi:nil 특성이 True로 설정된 요소에 null 값이 매핑되는 요소 중심 XML을 생성하는 ELEMENTS XSINIL을 사용합니다.

WITH XMLNAMESPACES ('uri' as ns1)
SELECT ProductID as 'ns1:ProductID',
       Name      as 'ns1:Name',
       Color     as 'ns1:Color'
FROM Production.Product
WHERE ProductID = 316
FOR XML RAW, ELEMENTS XSINIL;

다음은 결과입니다.

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="uri">
  <ns1:ProductID>316</ns1:ProductID>
  <ns1:Name>Blade</ns1:Name>
  <ns1:Color xsi:nil="true" />
</row>

기본 네임스페이스 지정

네임스페이스 접두사를 선언하는 대신 DEFAULT 키워드를 사용하여 기본 네임스페이스를 선언할 수 있습니다. FOR XML 쿼리에서는 기본 네임스페이스를 결과 XML의 XML 노드에 바인딩합니다. 다음 예에서 WITH XMLNAMESPACES는 기본 네임스페이스와 함께 정의된 두 개의 네임스페이스 접두사를 정의합니다.

WITH XMLNAMESPACES ('uri1' as ns1,
                    'uri2' as ns2,
                    DEFAULT 'uri2')
SELECT ProductID,
      Name,
      Color
FROM Production.Product
WHERE ProductID IN (316, 317)
FOR XML RAW ('ns1:Product'), ROOT('ns2:root'), ELEMENTS;

FOR XML 쿼리는 요소 중심 XML을 생성합니다. 이 쿼리는 노드 이름 지정에 네임스페이스 접두사를 모두 사용합니다. SELECT 절에서 ProductID, Name 및 Color는 접두사가 포함된 이름을 지정하지 않습니다. 따라서 결과 XML의 해당 요소는 기본 네임스페이스에 속합니다.

<ns2:root xmlns="uri2" xmlns:ns2="uri2" xmlns:ns1="uri1">
  <ns1:Product>
    <ProductID>316</ProductID>
    <Name>Blade</Name>
  </ns1:Product>
  <ns1:Product>
    <ProductID>317</ProductID>
    <Name>LL Crankarm</Name>
    <Color>Black</Color>
  </ns1:Product>
</ns2:root>

다음 쿼리는 이전 쿼리와 비슷하지만 FOR XML AUTO 모드가 지정되어 있습니다.

WITH XMLNAMESPACES ('uri1' as ns1,  'uri2' as ns2,DEFAULT 'uri2')
SELECT ProductID,
      Name,
      Color
FROM Production.Product as "ns1:Product"
WHERE ProductID IN (316, 317)
FOR XML AUTO, ROOT('ns2:root'), ELEMENTS;

미리 정의된 네임스페이스 사용

미리 정의된 네임스페이스를 사용하는 경우, xml 네임스페이스와 xsi 네임스페이스(ELEMENTS XSINIL 사용 시)를 제외한 나머지 네임스페이스는 WITH XMLNAMESPACES를 사용하여 명시적으로 네임스페이스 바인딩을 지정해야 합니다. 다음 쿼리는 미리 정의된 네임스페이스에 대해 URI 바인딩에 대한 네임스페이스 접두사를 명시적으로 정의합니다(urn:schemas-microsoft-com:xml-sql).

WITH XMLNAMESPACES ('urn:schemas-microsoft-com:xml-sql' as sql)
SELECT 'SELECT * FROM Customers FOR XML AUTO, ROOT("a")' AS "sql:query"
FOR XML PATH('sql:root');

다음은 결과입니다. SQLXML 사용자는 이 XML 템플릿에 익숙합니다. 자세한 내용은 SQLXML 4.0 프로그래밍 개념을 참조하세요.

<sql:root xmlns:sql="urn:schemas-microsoft-com:xml-sql">
  <sql:query>SELECT * FROM Customers FOR XML AUTO, ROOT("a")</sql:query>
</sql:root>

다음 PATH 모드 쿼리에서 볼 수 있듯이 WITH XMLNAMESPACES에서 명시적으로 정의하지 않고 xml 네임스페이스 접두사만 사용할 수 있습니다. 또한 접두사가 선언된 경우 http://www.w3.org/XML/1998/namespace 네임스페이스에 바인딩되어야 합니다. SELECT 절에 지정된 이름은 WITH XMLNAMESPACES를 사용하여 명시적으로 정의되지 않은 xml 네임스페이스 접두사를 참조합니다.

SELECT 'en'    as "English/@xml:lang",
       'food'  as "English",
       'ger'   as "German/@xml:lang",
       'Essen' as "German"
FOR XML PATH ('Translation');
GO

@xml:lang 특성은 미리 정의된 xml 네임스페이스를 사용합니다. XML 버전 1.0에서는 xml 네임스페이스 바인딩의 명시적 선언이 필요하지 않으므로 결과에는 네임스페이스 바인딩의 명시적 선언이 포함되지 않습니다.

다음은 결과입니다.

<Translation>
  <English xml:lang="en">food</English>
  <German xml:lang="ger">Essen</German>
</Translation>

xml 데이터 형식 메서드와 함께 WITH XMLNAMESPACES 사용

SELECT 쿼리에 지정된 xml 데이터 형식 메서드 또는 modify() 메서드인 경우 UPDATE에 지정된 메서드는 모두 프롤로그에서 네임스페이스 선언을 반복해야 합니다. 이 작업은 시간이 많이 걸릴 수 있습니다. 예를 들어 다음 쿼리는 카탈로그 설명에 사양이 포함되지 않는 제품 모델 ID를 검색합니다. 즉, <Specifications> 요소가 존재합니다.

SELECT ProductModelID, CatalogDescription.query('
declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
    <Product
        ProductModelID= "{ sql:column("ProductModelID") }"
        />
') AS Result
FROM Production.ProductModel
WHERE CatalogDescription.exist('
    declare namespace  pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
     /pd:ProductDescription[(pd:Specifications)]'
    ) = 1;

이전 쿼리에서 query()exist() 메서드는 모두 프롤로그에서 동일한 네임스페이스를 선언합니다. 예시:

declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";

또는 먼저 WITH XMLNAMESPACES를 선언하고 쿼리에서 네임스페이스 접두사를 사용할 수 있습니다. 이 경우 query()exist() 메서드는 프롤로그에 네임스페이스 선언을 포함할 필요가 없습니다.

WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' as pd)
SELECT ProductModelID, CatalogDescription.query('
    <Product
        ProductModelID= "{ sql:column("ProductModelID") }"
        />
') AS Result
FROM Production.ProductModel
WHERE CatalogDescription.exist('
     /pd:ProductDescription[(pd:Specifications)]'
    ) = 1;
GO

XQuery 프롤로그의 명시적 선언은 WITH 절에 정의된 네임스페이스 접두사 및 기본 요소 네임스페이스를 재정의합니다.

참고 항목