nodes() 메서드(xml 데이터 형식)
nodes() 메서드는 xml 데이터 형식 인스턴스를 관계형 데이터로 조각으로 나눌 때 유용합니다. 이 메서드를 사용하면 새로운 행으로 매핑되는 열을 식별할 수 있습니다.
모든 xml 데이터 형식 인스턴스에는 암시적으로 제공된 컨텍스트 노드가 있습니다. 열 또는 변수에 저장된 XML 인스턴스의 경우 이 노드는 문서 노드입니다. 문서 노드는 모든 xml 데이터 형식 인스턴스의 최상위에 있는 암시적 노드입니다.
nodes() 메서드의 결과는 원래 XML 인스턴스의 논리적 복사본이 들어 있는 행 집합입니다. 이러한 논리적 복사본에서 모든 행 인스턴스의 컨텍스트 노드는 쿼리 식으로 식별된 노드 중 하나로 설정되므로 이후의 쿼리에서는 이러한 컨텍스트 노드에 따라 상대적으로 탐색할 수 있습니다.
행 집합에서 여러 값을 검색할 수 있습니다. 예를 들어 **nodes()**에 의해 반환된 행 집합에 value() 메서드를 적용하고 원래 XML 인스턴스에서 여러 값을 검색할 수 있습니다. XML 인스턴스에 적용된 경우 value() 메서드는 값을 하나만 반환합니다.
구문
nodes (XQuery) as Table(Column)
인수
XQuery
문자열 리터럴인 XQuery 식입니다. 쿼리 식이 노드를 생성하는 경우 이렇게 생성된 노드는 결과 행 집합에 제공됩니다. 쿼리 식에 의해 빈 시퀀스가 생성되는 경우 빈 행 집합이 반환됩니다. 쿼리 식이 노드 대신 원자 값이 들어 있는 시퀀스를 정적으로 생성하는 경우 정적 오류가 발생합니다.Table(Column)
결과 행 집합에 대한 테이블 이름 및 열 이름입니다.
주의
예를 들어 다음과 같은 테이블을 가정해 보십시오.
T (ProductModelID int, Instructions xml)
다음 제조 지침 문서가 이 테이블에 저장되어 있고 한 조각만 표시되어 있습니다. 문서에는 3개의 제조 위치가 있습니다.
<root>
<Location LocationID="10"...>
<step>...</step>
<step>...</step>
...
</Location>
<Location LocationID="20" ...>
...
</Location>
<Location LocationID="30" ...>
...
</Location>
</root>
쿼리 식 /root/Location에서 nodes() 메서드를 호출하면 각각 원래 XML 문서의 논리적 복사본이 들어 있고 컨텍스트 항목이 <<Location> 노드 중 하나로 설정된 3개의 행이 포함된 행 집합이 반환됩니다.
Product
ModelID Instructions
----------------------------------
1 <root>
<Location LocationID="20" ... />
<Location LocationID="30" .../></root>
1 <root><Location LocationID="10" ... />
<Location LocationID="30" .../></root>
1 <root><Location LocationID="10" ... />
<Location LocationID="20" ... />
</root>
그런 다음 xml 데이터 형식 메서드를 사용하여 이 행 집합을 쿼리할 수 있습니다. 다음 쿼리는 생성된 각 행에 대한 컨텍스트 항목의 하위 트리를 추출합니다.
SELECT T2.Loc.query('.')
FROM T
CROSS APPLY Instructions.nodes('/root/Location') as T2(Loc)
다음은 결과입니다.
ProductModelID Instructions
----------------------------------
1 <Location LocationID="10" ... />
1 <Location LocationID="20" ... />
1 <Location LocationID="30" .../>
반환된 행 집합에는 유형 정보가 유지 관리됩니다. query(), value(), exist() 및 **nodes()**와 같은 xml 데이터 형식 메서드를 nodes() 메서드의 결과에 적용할 수 있습니다. 하지만 modify() 메서드를 적용하여 XML 인스턴스를 수정할 수는 없습니다.
또한 행 집합의 컨텍스트 노드는 구체화할 수 없습니다. 즉, 이 노드를 SELECT 문에서 사용할 수 없습니다. 하지만 IS NULL 및 COUNT(*)에서는 사용할 수 있습니다.
nodes() 메서드를 사용하는 방법은 OPENXML(Transact-SQL)을 사용하는 방법과 동일합니다. 이 메서드는 XML에 대한 행 집합 뷰를 제공합니다. 하지만 XML 문서의 여러 행이 포함된 테이블에서 nodes() 메서드를 사용할 때는 커서를 사용할 필요가 없습니다.
nodes() 메서드에 의해 반환된 행 집합은 명명되지 않은 행 집합입니다. 따라서 별칭을 사용하여 명시적으로 이름을 지정해야 합니다.
nodes() 함수는 사용자 정의 함수의 결과에 직접 적용할 수 없습니다. 스칼라 사용자 정의 함수의 결과에서 nodes() 함수를 사용하려면 변수에 사용자 정의 함수의 결과를 할당하거나 파생 테이블을 사용하여 사용자 정의 함수 반환 값에 열 별칭을 할당한 후 CROSS APPLY를 사용하여 별칭에서 선택을 합니다.
다음 예에서는 CROSS APPLY를 사용하여 사용자 정의 함수의 결과에서 선택하는 한 가지 방법을 보여 줍니다.
USE AdventureWorks;
GO
CREATE FUNCTION XTest()
RETURNS xml
AS
BEGIN
RETURN '<document/>';
END;
GO
SELECT A2.B.query('.')
FROM
(SELECT dbo.XTest()) AS A1(X)
CROSS APPLY X.nodes('.') A2(B);
GO
DROP FUNCTION XTest;
GO
예
1. xml 형식의 변수에 대해 nodes() 메서드 사용
다음 예에는 <Root> 최상위 요소 하나와 <row> 자식 요소 3개가 있는 XML 문서가 있습니다. 이 쿼리는 nodes() 메서드를 사용하여 각 <row> 요소에 대해 하나의 개별 컨텍스트 노드를 설정합니다. nodes() 메서드는 3개의 행이 포함된 행 집합을 반환합니다. 각 행에는 원래 문서에서 서로 다른 <row> 요소를 식별하는 각 컨텍스트 노드와 함께 원래 XML의 논리적 복사본이 들어 있습니다.
그런 다음 쿼리는 각 행에서 컨텍스트 노드를 반환합니다.
DECLARE @x xml
SET @x='<Root>
<row id="1"><name>Larry</name><oflw>some text</oflw></row>
<row id="2"><name>moe</name></row>
<row id="3" />
</Root>'
SELECT T.c.query('.') AS result
FROM @x.nodes('/Root/row') T(c)
GO
다음은 결과입니다. 이 예에서 쿼리 메서드는 컨텍스트 항목과 해당 내용을 반환합니다.
<row id="1"><name>Larry</name><oflw>some text</oflw></row>
<row id="2"><name>moe</name></row>
<row id="3"/>
컨텍스트 노드에 부모 접근자를 적용하면 3개 모두에 대한 <Root> 요소를 반환합니다.
SELECT T.c.query('..') AS result
FROM @x.nodes('/Root/row') T(c)
go
다음은 결과입니다.
<Root>
<row id="1"><name>Larry</name><oflw>some text</oflw></row>
<row id="2"><name>moe</name></row>
<row id="3" />
</Root>
<Root>
<row id="1"><name>Larry</name><oflw>some text</oflw></row>
<row id="2"><name>moe</name></row>
<row id="3" />
</Root>
<Root>
<row id="1"><name>Larry</name><oflw>some text</oflw></row>
<row id="2"><name>moe</name></row>
<row id="3" />
</Root>
2. xml 형식의 열에 대해 nodes() 메서드 지정
이 예에서는 자전거 제조 지침이 사용되며 ProductModel 테이블에서 xml 유형의 Instructions 열에 저장되어 있습니다.
다음 예에서 nodes() 메서드는 ProductModel 테이블에 있는 xml 유형의 Instructions 열에 대해 지정됩니다.
nodes() 메서드는 /MI:root/MI:Location 경로를 지정하여 <Location> 요소를 컨텍스트 노드로 설정합니다. 결과 행 집합에는 <Location> 요소로 설정된 컨텍스트 노드와 함께 문서에 있는 각 <Location> 노드에 대해 원래 문서의 논리적 복사본이 하나씩 들어 있습니다. 따라서 nodes() 함수는 일련의 <Location> 컨텍스트 노드를 제공합니다.
이 행 집합에 대한 query() 메서드는 self::node를 요청하므로 각 행에 <Location> 요소를 반환합니다.
이 예에서 쿼리는 특정 제품 모델의 제조 지침 문서에 각 <Location> 요소를 컨텍스트 노드로 설정합니다. 이러한 컨텍스트 노드를 사용하여 다음과 같은 값을 검색할 수 있습니다.
각 <Location>에서 위치 ID 찾기
각 <Location>에서 제조 단계(<step>) 검색
이 쿼리는 query() 메서드에서 self::node()에 대한 축약형 구문 '.'이 지정된 컨텍스트 항목을 반환합니다.
다음을 유의하십시오.
nodes() 메서드는 Instructions 열에 적용되며 T (C) 행 집합을 반환합니다. 이 행 집합에는 컨텍스트 항목으로 /root/Location이 포함된 원래 제조 지침 문서의 논리적 복사본이 포함됩니다.
CROSS APPLY는 Instructions 테이블의 각 행에 nodes()를 적용하고 결과 집합을 생성하는 행만 반환합니다.
SELECT C.query('.') as result FROM Production.ProductModel CROSS APPLY Instructions.nodes(' declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"; /MI:root/MI:Location') as T(C) WHERE ProductModelID=7
다음은 결과의 일부입니다.
<MI:Location LocationID="10" ...> <MI:step ... /> ... </MI:Location> <MI:Location LocationID="20" ... > <MI:step ... /> ... </MI:Location> ...
3. 다른 nodes() 메서드에서 반환된 행 집합에 nodes() 적용
다음 코드는 XML 문서에서 ProductModel 테이블의 Instructions 열에 있는 제조 지침을 쿼리합니다. 이 쿼리는 제품 모델 ID, 제조 위치 및 제조 단계가 포함된 행 집합을 반환합니다.
다음을 유의하십시오.
nodes() 메서드는 Instructions 열에 적용되며 T1 (Locations) 행 집합을 반환합니다. 이 행 집합에는 항목 컨텍스트로 /root/Location 요소가 포함된 원래 제조 지침 문서의 논리적 복사본이 포함됩니다.
nodes()는 T1 (Locations) 행 집합에 적용되며 T2 (steps) 행 집합을 반환합니다. 이 행 집합에는 항목 컨텍스트로 /root/Location/step 요소가 포함된 원래 제조 지침 문서의 논리적 복사본이 포함됩니다.
SELECT ProductModelID, Locations.value('./@LocationID','int') as LocID,
steps.query('.') as Step
FROM Production.ProductModel
CROSS APPLY Instructions.nodes('
declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
/MI:root/MI:Location') as T1(Locations)
CROSS APPLY T1.Locations.nodes('
declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
./MI:step ') as T2(steps)
WHERE ProductModelID=7
GO
다음은 결과입니다.
ProductModelID LocID Step
----------------------------
7 10 <step ... />
7 10 <step ... />
...
7 20 <step ... />
7 20 <step ... />
7 20 <step ... />
...
이 쿼리는 MI 접두사를 두 번 선언합니다. 대신 WITH XMLNAMESPACES를 사용하여 접두사를 한 번만 선언하고 쿼리에서 사용할 수 있습니다.
WITH XMLNAMESPACES (
'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions' AS MI)
SELECT ProductModelID, Locations.value('./@LocationID','int') as LocID,
steps.query('.') as Step
FROM Production.ProductModel
CROSS APPLY Instructions.nodes('
/MI:root/MI:Location') as T1(Locations)
CROSS APPLY T1.Locations.nodes('
./MI:step ') as T2(steps)
WHERE ProductModelID=7
GO
참고 항목
개념
WITH XMLNAMESPACES를 사용하여 쿼리에 네임스페이스 추가