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

적용 대상:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

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

FOR XML 쿼리에서 WITH XMLNAMESPACES 사용

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 절은 네임스페이스 접두사()를 URI(ns1uri) 매핑으로 지정합니다. 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을 사용할 때 자동으로 추가됩니다. 다음 쿼리에서는 null 값이 xsi:nil 특성이 True로 설정된 요소에 매핑되는 요소 중심 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;

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

ELEMENTS XSINIL을 사용할 때 xml 네임스페이스와 xsi 네임스페이스를 제외하고 미리 정의된 네임스페이스를 사용하는 경우 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;

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

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

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

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 절에 정의된 네임스페이스 접두사 및 기본 요소 네임스페이스를 재정의합니다.

참고 항목