nodes() 메서드(xml 데이터 형식)
적용 대상: SQL Server Azure SQL 데이터베이스 Azure SQL Managed Instance
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)
다음 제조 지침 문서가 이 테이블에 저장되어 있고 조각만 표시됩니다. 문서에는 세 개의 제조 위치가 있습니다.
<root>
<Location LocationID="10"...>
<step>...</step>
<step>...</step>
...
</Location>
<Location LocationID="20" ...>
...
</Location>
<Location LocationID="30" ...>
...
</Location>
</root>
nodes()
쿼리 식을 /root/Location
사용하는 메서드 호출은 각각 원래 XML 문서의 논리적 복사본을 포함하고 컨텍스트 항목이 노드 중 <Location>
하나로 설정된 세 개의 행이 있는 행 집합을 반환합니다.
Product
ModelID Instructions
----------------------------------
1 <root><Location LocationID="10" ... />
<Location LocationID="20" ... />
<Location LocationID="30" .../></root>
1 <root><Location LocationID="10" ... />
<Location LocationID="20" ... />
<Location LocationID="30" .../></root>
1 <root><Location LocationID="10" ... />
<Location LocationID="20" ... />
<Location LocationID="30" .../></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() 메서드의 결과에 적용할 수 있습니다. 그러나 XML 인스턴스를 수정하기 위해 modify() 메서드를 적용할 수는 없습니다.
또한 행 집합의 컨텍스트 노드는 구체화할 수 없습니다. 즉, SELECT 문에는 사용할 수 없습니다. 그러나 IS NULL 및 COUNT(*)에서 사용할 수 있습니다.
nodes() 메서드를 사용하는 시나리오는 XML의 행 집합 뷰를 제공하는 OPENXML(Transact-SQL)을 사용하는 시나리오와 동일합니다. 그러나 여러 행의 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
예제
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>
xml 형식의 열에 대해 nodes() 메서드 지정
자전거 제조 지침은 이 예제에서 사용되며 ProductModel 테이블의 Instructions xml 형식 열에 저장됩니다.
다음 예제에서는 테이블의 nodes()
xml 형식 열에 Instructions
대해 메서드를 ProductModel
지정합니다.
nodes()
메서드는 /MI:root/MI:Location
경로를 지정하여 <Location
> 요소를 컨텍스트 노드로 설정합니다. 결과 행 집합에는 <Location
> 요소로 설정된 컨텍스트 노드와 함께 문서에 있는 각 <Location
> 노드에 대해 원래 문서의 논리적 복사본이 하나씩 들어 있습니다. 따라서 nodes()
함수는 일련의 <Location
> 컨텍스트 노드를 제공합니다.
이 행 집합에 대한 query()
메서드는 self::node
를 요청하고 각 행에 <Location>
요소를 반환합니다.
이 예에서 쿼리는 특정 제품 모델의 제조 지침 문서에 각 <Location
> 요소를 컨텍스트 노드로 설정합니다. 이러한 컨텍스트 노드를 사용하여 다음과 같은 값을 검색할 수 있습니다.
각 <
Location
>에서 위치 ID 찾기각 <
Location
>에서 제조 단계(<step
> 자식 요소) 검색
이 쿼리는 메서드에서 약어 구문 '.'
self::node()
이 지정된 query()
컨텍스트 항목을 반환합니다.
다음을 참고하십시오.
이
nodes()
메서드는 Instructions 열에 적용되고 행 집합T (C)
을 반환합니다. 이 행 집합에는 컨텍스트 항목으로/root/Location
이 포함된 원래 제조 지침 문서의 논리적 복사본이 포함됩니다.CROSS APPLY는
nodes()
테이블의 각 행에ProductModel
를 적용하고 결과 집합을 생성하는 행만 반환합니다.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> ...
다른 nodes() 메서드에서 반환된 행 집합에 nodes() 적용
다음 코드는 테이블 열 ProductModel
의 제조 지침에 Instructions
대한 XML 문서를 쿼리합니다. 이 쿼리는 제품 모델 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를 사용하여 쿼리에 네임스페이스 추가
XML 데이터 인스턴스 만들기
xml 데이터 형식 메서드