728x90

SQL Server 2005의 XQuery 소개



Prasadarao K. Vithanala - Microsoft Corporation


요약: 이 백서에서는 FLWOR 문, XQuery의 연산자, if-then-else 구문, XML 생성자, 기본 제공되는 XQuery 함수, 형식 캐스팅 연산자, 이러한 각 기능을 사용하는 방법에 관한 예제 등을 비롯하여 SQL Server 2005에서 구현된 XQuery의 다양한 기능을 소개합니다. 또한 SQL Server 2005에서 지원되지 않는 XQuery 기능과 해결 방법이 설명되고 XQuery가 유용하게 사용되는 세 가지 시나리오가 제공됩니다.


목차

소개
SQL Server 2005의 XML 데이터 형식
XQuery 소개
XQuery 식 구조
XQuery의 연산자
if-then-else 구문
XQuery를 사용하여 XML 생성
기본 제공 XQuery 함수
형식 관련 식
관계형 열과 변수 액세스
지원되지 않는 기능과 해결 방법
최상의 실행 방법 및 지침
XML 데이터 수정
XQuery 사용 시나리오
결론




소 개


XML은 문서 형식으로 사용하도록 개발되었습니다. 그러나 확장성, 국제화 지원, 구조적 및 반구조적 데이터 표시 기능, 시스템 및 사용자를 위한 향상된 가독성 등을 비롯한 추가 기능으로 인해 XML은 플랫폼에 독립적인 데이터 표현 형식으로 매우 널리 사용되고 있습니다. XML이 널리 보급됨에 따라 사용자들은 데이터 통합과 관련된 문제와 같은 복잡한 비즈니스 문제를 해결하기 위해 XML을 적용하고 있습니다.


많은 시나리오에서 정보를 테이블에 저장한 다음 해당 정보에서 XML 메시지를 작성하는 것보다는 정보를 XML 형식으로 저장하는 것이 권장됩니다. 이러한 시나리오에 대한 자세한 내용은 MSDN 기사 Microsoft SQL Server 2005를 위한 XML 최상의 실행 방법을 참조하십시오. 문서를 저장하고 반구조적 데이터를 표현하기 위해 XML을 적용하는 방법은 서버의 데이터 관리를 단순화하는 데이터 저장 형식으로 XML이 발전하게 된 원동력이 되어 왔습니다.


그러나 관계형 테이블에 저장된 XML 데이터에서 정보를 BLOB로 추출하려면 정보를 추출하여 XML로 표현할 수 있는 쿼리 언어가 필요하다는 문제가 대두되었습니다. Microsoft SQL Server 2000에서는 쿼리에 사용할 수 있는 OpenXML이 제공되었습니다. 그러나 OpenXML은 XML 데이터를 관계형 형식에 매핑하도록 설계되었기 때문에 XML 데이터 모델을 완전하게 지원하지 못했습니다(표 1 참조).


관계형 데이터 모델과 XML 데이터 모델은 여러 측면에서 다릅니다. 다음 표에는 두 데이터 모델의 주요 차이점이 나와 있습니다.


관계형 데이터 모델이 XML 문서를 기본적으로 저장하도록 확장되는 것은 여러 요인 중에서 특히 유형이 다른 구조적 데이터를 더 많이 처리해야 하는 요구가 커지고 암시적 순서를 유지해야 할 필요성이 증가했기 때문입니다. 또한 반구조적 또는 태그 정보 처리에 관한 SQL 언어의 한계로 인해 XQuery 언어가 개발되었습니다. XQuery 언어는 XML 데이터의 특성과 XML 데이터 처리와 관련된 문제를 고려하여 처음부터 새롭게 디자인되었습니다.


SQL Server 2005에서는 XML데이터 형식을 사용한 XML 데이터의 네이티브 저장이 기본적으로 지원됩니다. XQuery 1.0은 XML 데이터에 대한 쿼리를 공식화하기 위해 W3C(World Wide Web Consortium) XML Query Working Group에서 정의한 언어입니다. SQL과 마찬가지로 XQuery는 SQL 및 Xpath에 대한 기본 지식만으로 쉽게 이해할 수 있는 선언적 쿼리 언어입니다.

표 1 관계형 데이터 모델과 XML 데이터 모델의 차이점

기 능 관계형 데이터 모델 XML 데이터 모델
평면 구조적 데이터 평면 테이블을 사용하여 데이터를 열 형식으로 저장합니다. 평면 구조적 데이터를 저장하는 데 권장되는 방법입니다. 문서 순서를 유지해야 하거나 스키마가 유연하거나 알려지지 않은 경우 유용합니다.
반구조적 데이터 관계형 모델을 사용하여 반구조적 데이터를 모델링하는 것이 어렵습니다. 변수 또는 확장 스키마를 사용하여 반구조적 데이터를 표현할 수 있는 기능을 지원합니다.
태그 데이터 BLOB 저장소를 벗어나 태그 데이터를 저장하는 데 적합하지 않습니다. HTML, RTF 등과 같은 태그 데이터를 저장할 수 있는 기능을 지원합니다.
중첩 또는 계층 데이터 구조 외래 키로 여러 테이블을 연결하여 사용함으로써 중첩 데이터를 지원하지만 중첩 깊이가 증가하거나 알려지지 않은 경우에 관계형 형식으로 저장된 중첩 데이터를 검색하는 데 필요한 쿼리가 복잡해집니다. 중첩 또는 계층 데이터 구조를 표현할 수 있는 기능을 지원합니다.
데이터 순서 유지되지 않습니다. 유지됩니다.
입력 데이터 유형이 같습니다. 유형이 다릅니다.
결과 집합 유형이 같습니다. 유형이 다릅니다.


이 문서는 2004년 7월에 발표된 XQuery 초안에 기초하는 SQL Server 2005의 XQuery 1.0 구현을 기반을 두고 있습니다. 이 문서의 첫 번째 절에서는 새 XML 데이터 형식과 관련 기능에 대한 개요를 제공합니다. 뒤이어 나오는 절에서는 새 XQuery 언어와 이점, FLWOR 문, XQuery의 다양한 연산자, XQuery의 기본 제공 함수, 형식 관련 식, SQL Server 2005에서 지원되지 않는 기능 등을 소개합니다. 마지막 부분의 절에서는 최상의 실행 방법과 지침, XML 데이터 수정 및 XQuery 사용 시나리오를 제공합니다.



SQL Server 2005의 XML 데이터 형식


SQL Server 2005에서 소개된 새 XML 데이터 형식은 XML 문서와 단편을 데이터베이스에 저장할 수 있는 기능을 사용자에게 제공합니다. XML 데이터 형식을 사용하면 열, 저장 프로시저 또는 함수의 매개 변수, 변수 등을 만들 수 있습니다.


또한 사용자는 XML 형식 열을 XML 스키마 컬렉션과 연관시켜 형식 있는 XML 열을 만들 수 있습니다. 컬렉션의 XML 스키마는 XML 인스턴스의 유효성을 검사하고 형식화하는 데 사용됩니다.



형식 있는/형식 없는 XML 데이터 형식 비교


XML 데이터 형식을 XML 스키마 컬렉션과 연관시켜 XML 인스턴스에 스키마 제약 조건을 적용할 수 있습니다. XML 데이터가 XML 스키마 컬렉션과 연관된 경우 이를 형식 있는 XML이라고 부르고 그렇지 않은 경우 형식 없는 XML이라고 부릅니다.


SQL Server 2005 XML 데이터 형식은 ISO SQL-2003 표준 XML 데이터 형식을 구현합니다. 따라서 올바른 형식의 XML 1.0 문서뿐만 아니라 최상위 텍스트 노드와 임의 개수의 최상위 요소가 포함된 소위 XML 콘텐츠 단편도 저장할 수 있습니다. 데이터가 올바른 형식을 가지는지 검사되며(XML 데이터 형식이 XML 스키마에 바인딩될 필요는 없음) SQL-2003 콘텐츠 완화법에 따라 올바른 형식이 아닌 데이터는 거부됩니다.


스키마가 미리 알려지지 않은 경우에 형식 없는 XML이 유용합니다. 또한 스키마가 알려져 있지만 변경 속도가 빨라서 유지 관리하기 힘들거나 여러 스키마가 존재하며 외부 요구 사항에 기초하여 이러한 스키마가 나중에 데이터에 바인딩될 경우에 형식 없는 XML이 유용합니다. 이외에도 데이터베이스 엔진이 지원하지 않은 XML 스키마 구문(예: key/keyref, lax validation)이 XML 스키마에 포함된 경우에도 형식 없는 XML이 유용합니다. 이 경우 CLR(Common Language Runtime) 사용자 정의 함수에서 System.XML 유효성 검사기를 사용하여 유효성 검사를 제공할 수 있습니다.


XML 스키마 컬렉션에 XML 데이터를 설명하는 XML 스키마가 있을 경우 XML 스키마 컬렉션을 XML 열과 연관시켜 형식 있는 XML을 생성할 수 있습니다. XML 스키마는 데이터의 유효성을 검사하고 쿼리 및 데이터 수정 문의 컴파일 도중에 형식 없는 XML보다 정확한 형식 검사를 수행하며 저장소 및 쿼리 처리를 최적화하는 데 사용됩니다.


형식 있는 XML 열, 매개 변수 및 변수는 선언 시에 옵션으로 지정할 수 있는 XML 문서나 콘텐츠 단편을 저장할 수 있습니다(각각 DOCUMENT 또는 CONTENT 옵션으로 지정할 수 있으며 기본값은 CONTENT). 또한 XML 스키마 컬렉션을 제공해야 합니다. 각 XML 인스턴스에 정확하게 하나의 최상위 요소가 있을 경우 DOCUMENT를 지정하고 그렇지 않을 경우에는 CONTENT를 사용합니다. XQuery 컴파일러는 DOCUMENT 플래그 정보를 사용하여 정적 형식 유추 도중에 단일 최상위 요소를 유추합니다.



XML 데이터 형식의 메서드


XML 데이터 형식은 XML 인스턴스를 조작하는 데 사용할 수 있는 5개의 메서드를 지원합니다. XML 데이터 형식의 이러한 메서드는 다음과 같습니다.


query() 메서드는 XML 노드 목록으로 평가되는 XQuery 식을 가집니다. 이 메서드를 사용하면 XML 문서의 단편을 추출할 수 있습니다. 형식 없는 XML의 인스턴스가 결과로 반환됩니다.


value() 메서드는 XML 문서에서 스칼라 값을 관계형 값으로 추출하는 데 사용됩니다. 이 메서드는 단일 노드와 반환되는 원하는 SQL 형식을 식별하는 XQuery 식을 가집니다. XML 노드 값이 반환되어 지정된 SQL 형식으로 캐스팅됩니다.


exist() 메서드를 사용하면 XML 문서에서 검사를 수행하여 XQuery 식의 결과가 비어 있는지 여부를 확인할 수 있습니다. XQuery 식이 비어 있지 않은 결과를 반환하면 이 메서드의 결과는 1입니다. 결과가 비어 있으면 0이고 XML 인스턴스 자체가 NULL이면 결과도 NULL입니다.


XML 데이터 형식의 nodes() 메서드는 XML 문서를 관계형 데이터로 분해하는 작업을 용이하게 합니다. nodes() 메서드는 제공된 XQuery 식에서 식별하는 컨텍스트 노드를 각 행에서 나타내는 행 집합을 반환합니다. 또한 query(), value(), exist(), nodes() 등과 같은 XML 데이터 형식의 메서드를 nodes() 메서드에서 반환된 컨텍스트 노드에서 호출할 수 있습니다.


modify() 메서드를 사용하면 XML 문서의 내용을 수정할 수 있습니다. 이 메서드는 XML DML 문을 사용하여 XML 인스턴스에서 하나 이상의 노드를 삽입, 업데이트 또는 삭제합니다. NULL 값에 적용될 경우 오류가 발생합니다.


자세한 내용은 Microsoft SQL Server 2005의 XML 지원 백서를 참조하십시오.



XQuery 소개


XQuery는 XML 데이터를 쿼리하기 위한 새 언어이며 XPath 2.0에 기초한 탐색 액세스를 허용합니다. 이 절에서는 XQuery와 Xpath의 관계, XQuery를 사용할 경우의 이점, XQuery의 적용 영역, XQuery에서 XML 스키마의 역할 등을 비롯하여 XQuery 언어의 다양한 측면에 대한 개요를 제공합니다.



XPath 2.0 개요


W3C에 의해 정의된 XPath 1.0 (영문)은 XML 문서의 일부분을 찾기 위한 언어입니다. Xpath는 XML 문서에서 노드를 식별하기 위해 경로 기반 구문을 사용합니다. 또한 Xpath는 XSLT 1.0 (영문) 및 XPointer (영문)에 대한 핵심 구문을 정의합니다. XPath 1.0에는 문자열, 부울 값 및 부동 소수점 수를 처리하기 위한 기본 제공 함수가 있습니다. XPath 1.0은 필터링 기준을 지정하는 기능과 함께 노드 집합을 필터링하기 위한 구문을 정의합니다. 더 자세한 형식 시스템을 지원하고 더 많은 기능을 제공하기 위해 XPath 1.0은 XPath 2.0 (영문)으로 확장되고 있습니다. XQuery 1.0 (영문)은 XPath 2.0에 기반을 두며 XPath 2.0의 탐색 및 필터링 측면에 순서 지정, 형태 변경, 구성 및 유효성 검사 기능을 추가합니다.



XQuery 개요


XQuery는 XML 형식으로 저장된 데이터를 쿼리하려는 특별한 목적을 위해 XML Query Working Group에 의해 처음부터 새로 설계된 형식 있는 선언적 기능 언업니다. XQuery는 XPath 2.0 및 XSLT 2.0 (영문)과 같은 다른 XML 표준과 동일한 데이터 모델 및 XML 스키마 (영문) 기반 형식 시스템을 사용합니다. XQuery는 형식화되지 않았거나(즉, 데이터와 연관된 스키마가 없는) XML 스키마로 형식화된 XML 문서에서 작동하도록 설계되었습니다. 앞에서 언급한 것처럼 XQuery 1.0은 기본적으로 XPath 2.0의 상위 집합입니다. XPath 2.0의 기능 외에도 다음과 같은 기능이 있습니다.


* 문서 순서와 다른 순서로 정렬할 수 있도록 FLWOR 절에 order by 절을 추가합니다.

* 이후에 사용하기 위해 식 결과에 이름을 지정하기 위해 FLWOR 절에 let 절을 추가합니다(SQL Server 2005에서는 지원되지 않음).

* 쿼리 프롤로그에 정적 컨텍스트 항목을 지정하는 방법을 제공합니다(예: 네임스페이스 접두사 바인딩).

* 새 노드를 생성하는 기능을 제공합니다.

* 사용자 정의 함수를 정의하는 기능을 제공합니다(SQL Server 2005에서는 지원되지 않음).

* 모듈/라이브러리를 만드는 기능을 제공합니다(SQL Server 2005에서는 지원되지 않음).



XQuery의 이점


* SQL 및 Xpath에 대한 지식이 있는 경우 쉽게 배울 수 있습니다.

* 쿼리가 XQuery로 작성된 경우 XSLT로 작성된 쿼리보다 코드가 적게 필요합니다.

* XML 데이터가 형식화된 경우 XQuery를 강력한 형식의 언어로 사용할 수 있으며 이 경우 암시적 형식 캐스트를 방지하여 쿼리의 성능을 향상시키고 쿼리 최적화 수행 시에 사용할 수 있는 형식 보장을 제공할 수 있습니다.

* 형식 없는 데이터의 경우 높은 유용성을 제공하기 위해 Xquery를 약한 형식의 언어로 사용할 수 있습니다. SQL Server 2005는 강력한 형식 및 약한 형식 관계에 대한 지원을 사용하여 정적 형식 유추를 구현합니다.

* XQuery는 쿼리를 수행하는 데 필요한 코드가 XSLT보다 적기 때문에 유지 관리 비용이 적게 들어갑니다.

* XQuery는 W3C 권고가 되어가고 있으며 주요 데이터베이스 공급업체에 의해 지원될 것입니다.


이 문서를 작성할 시점에 XQuery 1.0 언어와 관련하여 다음과 같은 주의 사항이 있었습니다.

XQuery 사양은 현재 개발 중이며 이후에 변경될 수 있습니다. SQL Server 2005는 W3C 초안의 검증된 부분에 기반을 두고 구현되었습니다.



XQuery 적용 영역


XQuery의 적용 영역을 다음과 같이 넓게 구분할 수 있습니다.


* 쿼리/분석을 위한 XQuery : XQuery는 많은 양의 데이터를 쿼리하는 데 적합하며 필요한 정보를 필터링, 정렬, 순서 지정 및 재활용하는 기능을 제공합니다. 반구조적 정보를 나타내는 XML 문서, 이름/값 쌍 속성 모음, 잠재적 응용 프로그램 오류와 보안 문제를 식별하기 의한 응용 프로그램 로그, 트랜잭션 로그 및 감사 로그 분석 등을 쿼리하는 것을 일반적인 적용 예로 들 수 있습니다.


* 응용 프로그램 통합을 위한 XQuery : 많은 조직에서 독자적인 응용 프로그램 통합 접근 방법에서 벗어나 표준 기반의 응용 프로그램 통합 접근 방법을 채택하기 시작함에 따라 내부 응용 프로그램 특정 형식의 데이터를 표준 교환 형식으로 변환해야 하는 필요성이 중요해지고 있습니다. XML 데이터를 생성 및 변환하는 기능을 가진 XQuery는 이러한 요구를 충족합니다. 응용 프로그램 통합 영역에서 XQuery가 사용되는 일반적인 예로 네이티브 XML 데이터베이스/관계형 데이터 데이터 소스를 사용하는 특정 응용 프로그램에 사용되는 용어를 XML/관계형 데이터 형식을 사용하는 다른 응용 프로그램에 사용되는 언어로 변환하는 경우를 들 수 있습니다.



서버에서 XQuery를 사용할 경우의 이점


XQuery를 사용하여 서버에서 XML 처리를 수행하는 것은 클라이언트 쪽 XML 처리와 비교하여 많은 이점이 있습니다. 그 중에서 몇 가지 이점을 요약하면 다음과 같습니다.


* 네트워크의 트래픽 감소 :
XML 데이터가 서버에서 처리될 경우 결과만 클라이언트에게 전달됩니다. 결과적으로 네트워크에서 트래픽이 줄어듭니다.

* 보안 향상: 필요한 데이터만 클라이언트에게 보내지므로 클라이언트 쪽 XML 처리를 사용할 경우처럼 전체 데이터가 네트워크에 노출되는 위험이 방지됩니다.

* 향상된 관리 효율성 :
서버에서 XML을 처리하므로 클라이언트에서 코드가 브라우저에 독립적입니다. 결과적으로 클라이언트 쪽에서 관리 효율성이 향상됩니다.

* 향상된 성능 :
서버에서 XQuery를 사용하여 작성하는 쿼리는 SQL 쿼리 엔진의 최적화를 따릅니다. 따라서 클라이언트에서 전체 데이터를 검색하고 필터링할 때와 비교하여 성능이 향상됩니다. 또한 XML 데이터 형식 열에서 인덱스를 작성하여 성능 향상을 실현할 수 있습니다.



XQuery 구현에서 XML 스키마가 사용되는 방법


XML 데이터 형식과 연관된 XML 스키마 컬렉션은 다음과 같이 관계형 엔진에 사용됩니다.


* 삽입 작업 도중에 XML 인스턴스의 유효성을 검사하기 위해 사용됩니다.

* 수정 작업 도중에 XML 인스턴스의 유효성을 검사하기 위해 사용됩니다.

* 더 나은 쿼리 계획을 생성하고 많은 런타임 검사를 방지하여 오류를 조기에 감지하고 쿼리 성능을 향상시키기 위해 정적 형식 검사 도중에 XML 스키마에 포함된 형식 정보가 사용됩니다.

* SQL Server는 XML 스키마에 존재하는 형식 정보를 사용하여 저장소를 최적화합니다.



XQuery 식 구조


SQL Server 2005의 XQuery 식은 두 개의 섹션, 즉 프롤로그와 본문으로 구성됩니다. 프롤로그에는 네임스페이스 선언 하위 섹션이 포함될 수 있습니다. 네임스페이스 선언은 접두사와 네임스페이스 URI 간의 매핑을 정의하는 데 사용되므로 쿼리 본문에서 네임스페이스 URI 대신에 접두사를 사용할 수 있게 합니다. 또한 declare default namespace 선언을 사용하여 요소 이름에 대한 기본 네임스페이스를 바인딩하면 접두사 없이 요소 이름을 참조할 수 있습니다.


XQuery 식의 본문에는 쿼리의 결과를 정의하는 쿼리 식이 포함됩니다. 예를 들어, 본문은 서명 FLWOR 식(이 문서의 FLWOR 문 참조), XPath 2.0 식(이 문서의 XPath 2.0 식 참조) 또는 생성 식이나 산술 식과 같은 다른 XQuery 식이 될 수 있습니다.


예제: XQuery의 프롤로그 섹션에 기본 네임스페이스 지정


다음 쿼리는 JobCandidateID가 3인 후보의 모든 Employment 노드를 선택합니다. 이 쿼리는 기본 네임스페이스를 정의하며 네임스페이스 접두사가 사용되지 않습니다.


SELECT Resume.query(''
declare default namespace "http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
/Resume/Employment
'') as Result
FROM [HumanResources].[JobCandidate]
WHERE JobCandidateID = 3


예제: "WITH XMLNAMESPACES" 절을 사용하여 네임스페이스 지정


또한 SQL Server는 사용자가 SQL 쿼리 단위로 SQL WITH 절에서 XML 네임스페이스 바인딩을 선언할 수 있게 하는 SQL 2003 표준 확장을 지원합니다. 따라서 여러 XML 데이터 형식 메서드 호출에서 선언을 반복할 필요가 없습니다. 다음 쿼리는 앞 예제에 나온 쿼리의 수정된 버전을 보여 줍니다. 이 쿼리는 WITH XMLNAMESPACES 절을 사용하여 네임스페이스를 선언합니다.


WITH XMLNAMESPACES( ''http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume'' AS "RES")
SELECT Resume.query(''
/RES:Resume/RES:Employment
'') as Result
FROM [HumanResources].[JobCandidate]
WHERE JobCandidateID = 3



XPath 2.0 식


XQuery는 XPath 2.0 식을 사용하여 문서의 노드를 찾고 단일 문서나 여러 문서의 특정 위치에서 다른 위치로 탐색합니다. Xpath를 사용하여 정의하는 탐색 경로는 /로 구분된 일련의 단계로 구성됩니다. 단일 단계는 축, 노드 테스트 및 0개 이상의 단계 한정자로 구성됩니다.


축은 컨텍스트 노드를 기준으로 이동 방향을 지정합니다. SQL Server 2005에서 지원되는 축은 child, descendant, parent, attribute, self 및 descendant-or-self입니다.


노드 테스트는 단계에서 선택된 모든 노드가 충족해야 하는 조건을 지정합니다. 노드 이름이나 노드 유형에 기초하여 노드 조건을 지정할 수 있습니다.


단계 한정자는 조건자 또는 역참조를 사용하여 정의할 수 있습니다. 조건자는 노드 시퀀스에서 필터로 작동하고 대괄호 안에 지정되는 식입니다. 역참조는 노드 시퀀스의 요소 및/또는 특성을 참조되는 노드에 매핑합니다. 역참조에 입력으로 전달되는 노드 시퀀스는 IDREF 또는 IDREFS 형식의 요소나 특성을 포함해야 합니다. 역참조는 입력 시퀀스의 요소 및 특성에서 추출된 IDREF 값과 일치하는 ID 형식 특성 값을 가지는 요소 노드로 구성된 새 시퀀스를 생성합니다.


Xpath 식의 단계는 왼쪽에서 오른쪽으로 평가됩니다. 단계가 실행되면 다음 단계의 평가 컨텍스트 항목이 설정됩니다. 경로 식의 컨텍스트 항목은 Xpath 식의 단계가 실행된 결과로 선택된 노드입니다. 단계는 이전 단계에서 얻어진 컨텍스트 항목을 기준으로 평가됩니다. XPath 식의 결과는 경로 식에서 왼쪽에서 오른쪽으로 모든 단계를 순서대로 실행한 후에 얻어진 문서 순서를 따르는 노드 시퀀스입니다.


다음 예제 식은 경로 식의 개념을 보여 주기 위해 AdventureWorks 데이터베이스의 [HumanResources].[JobCandidate] 테이블에서 XML 형식의 Resume 열을 사용합니다. 이 경로 식에서는 주소 형식이 Home으로 설정된 모든 주소 노드가 선택됩니다.


//child::ns:Addr.Type[.="Home"]/parent::node()


위 경로 식에서

    child는 축 지정자입니다.

    ::은 축 구분자입니다.

    ns는 네임스페이스 접두사입니다.

    Addr.Type은 노드 테스트입니다.

    [.="Home"]은 조건자 식이며 .은 컨텍스트 노드를 나타냅니다.

또한 XQuery는 축을 지정하기 위한 축약 구문을 지원합니다. 다음 표에는 축과 해당 축약 구문이 나와 있습니다.



표 2 축의 축약 구문






축약 형식
Attribute @
Child  
descendant-or-self::node() //
parent::node() ..
self::node() .

예제: 고용 기록에서 조직 이름 선택


다음 XPath 식은 Resume/Employment 노드의 자식 노드인 Emp.OrgName 요소의 자식 텍스트 노드를 선택합니다. 여기서 Emp.OrgName 요소의 텍스트 노드를 선택하기 위해 text()가 사용됩니다.


/Resume/Employment/Emp.OrgName/text()



FLWOR 문


FLWOR 문은 XQuery의 핵심 식이며 SQL의 SELECT 문과 비슷합니다. "flower"라고 발음되는 머리 글자어 FLWOR는 FOR, LET, WHERE, ORDER BY, RETURN을 나타냅니다. XQuery의 FLWOR 식을 사용하면 선언적 반복, 변수 바인딩, 결과 필터링, 정렬 및 반환 등과 같은 작업을 지정할 수 있습니다. SQL Server 2005에서는 FOR, WHERE, ORDER BY 및 RETURN이 지원됩니다.



For


FLWOR 식의 for 절을 사용하면 입력 시퀀스에서 바인딩된 변수의 선언적 반복을 정의할 수 있습니다. XPath 식, 원자 값 시퀀스, 리터럴을 사용하여 생성된 시퀀스, 생성자 함수 등을 사용하여 입력 시퀀스를 지정할 수 있습니다. 따라서 SQL SELECT FROM 절과 비슷하지만 프로그래밍 언어 "for" 구문과는 다릅니다.


또한 변수 바인딩이 for 절에 지정됩니다.


예제: for 절을 사용하여 이력서에서 모든 집 주소 요소 선택


다음 쿼리는 주소 형식이 Home으로 설정되었으며 JobCandidateID가 3인 모든 Address 노드를 선택합니다.


SELECT Resume.query(''
declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
for $A in /RES:Resume/RES:Address/RES:Addr.Type[.="Home"]/..
return
$A
'') as Result
FROM [HumanResources].[JobCandidate]
WHERE JobCandidateID = 3



where


where 절은 where 절을 사용하여 지정된 식을 적용하여 반복 결과를 필터링합니다.


예제: where 절을 사용하여 모든 집 주소 요소 선택


다음 쿼리는 주소 형식이 Home으로 설정되었으며 JobCandidateID가 3인 모든 Address 노드를 선택합니다.


SELECT Resume.query(''
declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
for $A in /RES:Resume/RES:Address
where $A/RES:Addr.Type[.="Home"]
return
$A
'') as Result
FROM [HumanResources].[JobCandidate]
WHERE JobCandidateID = 3



order by


order by 키워드를 사용하면 반환된 결과 집합에서 값을 정렬할 수 있습니다. order by 키워드에는 원자 값을 반환해야 하는 정렬 식이 허용됩니다. 원하는 경우 오름차순 또는 내림차순 정렬 순서를 지정할 수도 있습니다. 기본 정렬 순서는 오름차순입니다.


예제: order by 절을 사용하여 고용 기록을 오름차순으로 선택


다음 쿼리는 JobCandidateID가 3인 후보에 대해 고용 시작 날짜의 오름차순으로 모든 Employment 노드를 선택합니다.


SELECT Resume.query(''
declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
for $EMP in /RES:Resume/RES:Employment
order by $EMP/RES:Emp.StartDate
return
$EMP
'') as Result
FROM [HumanResources].[JobCandidate]
WHERE JobCandidateID = 3



return


SQL의 SELECT 절과 비슷한 return 절을 사용하면 쿼리 결과를 정의할 수 있습니다. 모든 유효한 XQuery 식을 return 절에 지정할 수 있습니다. 또한 요소, 특성 등에 대한 생성자를 지정하여 return 섹션에서 XML 구조를 생성할 수 있습니다.


예제: return 절을 사용하여 고용 기록의 특정 요소 선택


다음 쿼리는 JobCandidateID가 3인 후보에 대해 Employment 노드의 StartDate, EndDate, OrgName, JobTitle 요소를 선택합니다.


SELECT Resume.query(''
declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
for $EMP in /RES:Resume/RES:Employment
order by $EMP/RES:Emp.StartDate
return

{ $EMP/RES:Emp.StartDate }
{ $EMP/RES:Emp.EndDate }
{ $EMP/RES:Emp.OrgName }
{ $EMP/RES:Emp.JobTitle }

'') as Result
FROM [HumanResources].[JobCandidate]
WHERE JobCandidateID = 3


현재 SQL Server 2005에서 구현된 XQuery는 let 절을 지원하지 않습니다. 이에 대한 자세한 내용은 이 문서의 뒤에 나오는 지원되지 않는 기능 및 해결 방법 부분에서 설명합니다.



FLWOR 식 및 XPath 식 비교


XPath 식을 사용하여 결과 시퀀스를 표현할 수 있는 경우 FLWOR 식을 사용하여 결과 시퀀스를 정의하면 성능이 저하됩니다. 이는 쿼리 계획에서 for 절의 본문과 for 변수 사이에 JOIN 작업이 포함되어 있기 때문입니다. 다음 조건 중 하나 이상을 충족할 경우에만 FLWOR 식을 사용하기에 적합합니다.


식 결과로 반환되는 값 시퀀스를 반복하려는 경우. 결과 집합의 연속된 값에 변수를 바인딩하는 for 절을 사용하여 이 작업을 수행합니다. for 절의 범위 내에서 새 요소를 생성하고 중복 요소를 유지하는 것을 예로 들 수 있습니다.
간단한 XPath 식을 사용하여 정의할 수 없는 조건자에 기초하여 for 절의 결과 집합을 필터링하려는 경우. 결과 집합에서 원치 않는 값을 제거하기 위해 where 절이 사용됩니다. 예를 들면 다음과 같습니다.


DECLARE @Result xml
SET @Result = ''''
SELECT @Result.query(''
for $i in (1, 2, 3), $j in (3, 4, 5)
where $i < $j
return sum($i + $j)
'') as Result


정렬 식에 기초하여 결과 집합을 정렬하려는 경우. order by 절을 사용하여 결과 집합에서 정렬을 정의합니다.
for 절에서 얻은 결과를 사용하여 반환된 결과 집합의 형태를 정의하려는 경우. 결과 집합의 형태 정의를 수행하기 위해 return 문이 사용됩니다.
다른 모든 경우에는 XPath 식을 사용하는 것이 좋습니다.



XQuery의 연산자


기능적 언어인 SQL Server 2005의 XQuery는 다음 범주로 그룹화할 수 있는 다양한 유형의 함수와 연산자를 지원합니다.

  • 산술 연산자

  • 비교 연산자

  • 논리 연산자

    표 3 SQL Server 2005에서 지원되는 연산자

    유형 연산자
    산술 연산자 +,-,*,div, mod
    일반 비교 연산자 =, !=, <, >, <=, >=
    값 비교 연산자 eq, ne, lt, gt, le, ge
    노드 비교 연산자 is
    노드 순서 비교 연산자 >>, <<
    논리 연산자 and, or


    산술 연산자


    SQL Server 2005에서는 5개의 산술 연산자인 +, b, *, div 및 mod가 지원됩니다. 현재 idiv는 지원되지 않습니다.

    예제: 상점 조사 정보의 선택된 값 변환


    다음 쿼리는 AdventureWorks 데이터베이스의 [Sales].[Store] 테이블에 기초합니다. 이 쿼리는 CustomerID가 3인 상점의 AnnualSales 및 AnnualRevenue 값을 엔화로 반환하고 상점 면적을 평방 미터로 반환합니다.


    SELECT Demographics.query(''
    declare namespace ST="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey";
    for $S in /ST:StoreSurvey
    return
    SalesInYen ="{ $S/ST:AnnualSales*106.8100 }"
    RevenueInYen = "{ $S/ST:AnnualRevenue*106.8100 }"
    StoreAreaInSqMeters = "{ $S/ST:SquareFeet*0.0929 }">

    '') as Result
    FROM [Sales].[Store]
    WHERE CustomerID = 3



    비교 연산자


    SQL Server 2005에서는 네 가지 유형의 비교 연산자가 지원됩니다. 이러한 연산자는 일반 비교 연산자, 값 비교 연산자, 노드 비교 연산자 및 노드 순서 비교 연산자입니다.



    일반 비교 연산자


    일반 비교 연산자를 사용하면 원자 값 또는 시퀀스나 이러한 두 값의 조합을 비교할 수 있습니다. 일반 비교 연산자는 =, !=, <, >, <=, 및 >=입니다. 일반 비교는 존재 여부를 수량화되는데 이는 일치하는 항목이 있을 경우 true가 반환된다는 것을 의미합니다.


    예제: 주소 형식이 Home으로 설정되지 않은 모든 주소 요소 선택


    다음 쿼리는 주소 형식이 Home으로 설정되지 않았으며 JobCandidateID가 3인 모든 Address 노드를 선택합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $A in /RES:Resume/RES:Address
    where $A/RES:Addr.Type[.!="Home"]
    return
    $A
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3



    값 비교 연산자


    값 비교 연산자를 사용하면 원자 값을 비교할 수 있습니다. SQL Server 2005에서 지원되는 값 비교 연산자는 eq, ne, lt, gt, le, 및 ge입니다. 현재의 XQuery 구현은 형식 없는 원자 값 승격과 관련하여 2004년 7월 발표된 XQuery 사양 초안을 따릅니다. 형식 없는 원자 형식은 XQuery 사양에 지정된 대로 xs:string 대신에 다른 피연산자 형식으로 승격됩니다. 이는 값 비교를 전이적인 것으로 만드는 것보다 일반 및 값 비교 연산자 사이에서 일관성을 유지하는 것이 더 중요하다고 간주되기 때문입니다.


    예제: GPA가 3.5보다 큰 모든 education 요소 선택


    다음 쿼리는 JobCandidateID가 2인 후보에 대해 GPA가 3.5보다 큰 모든 Education 노드를 선택합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $ED in /RES:Resume/RES:Education
    where xs:decimal($ED/RES:Edu.GPA) gt 3.5
    return
    $ED
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 2



    노드 비교 연산자


    노드 비교 연산자 is를 사용하여 두 개의 노드를 비교하면 해당 노드가 동일한 노드인지 여부를 확인할 수 있습니다. 노드 비교 연산자에는 노드 형식의 피연산자 두 개가 허용됩니다.


    예제: 두 개의 주소 노드를 비교하여 ID 검사


    다음 쿼리는 두 개의 address 노드를 비교하여 문서의 동일한 노드를 나타내는지 여부를 검사합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    if ( (/RES:Resume/RES:Address)[1] is (//RES:Address)[1] )
    then
    Nodes are equal
    else
    Nodes are not equal
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3



    노드 순서 비교 연산자


    노드 순서 비교 연산자를 사용하여 문서에 있는 두 노드의 순서를 확인할 수 있습니다. SQL Sever 2005에서 지원되는 노드 순서 비교 연산자는 >> 및 << 이며 두 연산자는 모두 두 개의 피연산자를 허용합니다. 문서 순서에서 왼쪽 피연산자가 오른쪽 피연산자보다 앞에 올 경우 >> 연산자는 true를 반환하고 문서 순서에서 왼쪽 피연산자가 오른쪽 피연산자 뒤에 올 경우<< 연산자는 true를 반환합니다.


    예제: 두 주소 노드의 순서 비교


    다음 쿼리는 JobCandidateID가 3인 후보에 대해 두 address 노드의 순서를 비교합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    if ( (/RES:Resume/RES:Address/RES:Addr.Type[.="Home"])[1] << (/RES:Resume/RES:Address/RES:Addr.Type[.="Permanent"])[1] )
    then
    Home address precedes Permanent address
    else
    Home address follows Permanent address
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3



    논리 연산자


    SQL Server 2005의 XQuery에서 지원되는 논리 연산자는 and 및 or입니다. 이러한 연산자를 사용하여 작성한 논리 식의 값은 true 또는 false가 될 수 있습니다.


    예제: and 연산자를 사용하여 논리 식 만들기


    다음 쿼리는 bachelor level business degree를 포함하는 후보의 education 요소를 반환합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    /RES:Resume/RES:Education[RES:Edu.Level="Bachelor" and RES:Edu.Major="Business"]
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3



    if-then-else 구문

    다른 기능적 언어와 마찬가지로 XQuery는 if-then-else 구문을 지원합니다. if-then-else 문을 사용하여 조건식 값에 기초한 작업을 수행할 수 있습니다.


    예제: 조건식 사용

    다음 쿼리는 JobCandidateID가 3인 후보의 이력서에 지정된 주소 유형을 표시합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $A in /RES:Resume/RES:Address
    return
    if ( $A/RES:Addr.Type eq "Home" )
    then
    Home Address
    else
    Other Address
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3



    XQuery를 사용하여 XML 생성


    XQuery 생성자를 사용하면 쿼리 내에서 XML 구조를 만들 수 있습니다. 요소, 특성, 처리 명령, 텍스트 노드 및 주석에 생성자를 사용할 수 있습니다.


    다음 예제는 XML을 생성하는 이러한 접근 방법을 보여 줍니다.


    예제: 상수 식 사용

    다음 쿼리는 상수 식을 사용하여 생성된 고용 기록 세부 정보를 표시합니다.


    SELECT Resume.query(''

    ABC Technologies
    Software Engineer
    2001-10-01
    2003-05-09

    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3


    예제: 동적으로 얻은 데이터 사용

    다음 쿼리는 JobCandidateID가 3인 후보에 대한 쿼리에서 얻은 결과를 사용하여 생성된 고용 기록 세부 정보를 표시합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $EMP in /RES:Resume/RES:Employment
    return

    { $EMP/RES:Emp.StartDate }
    { $EMP/RES:Emp.EndDate }
    { $EMP/RES:Emp.JobTitle }

    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3


    예제: 계산된 요소 및 특성 생성자에 상수 이름 사용

    다음 쿼리는 JobCandidateID가 3인 후보의 고용 기록을 표시합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $EMP in /RES:Resume/RES:Employment
    return
    element Employer
    {
    attribute Organization { $EMP/RES:Emp.OrgName },
    element StartDate { string($EMP/RES:Emp.StartDate) },
    element EndDate { string($EMP/RES:Emp.EndDate) },
    element JobTitle { string($EMP/RES:Emp.JobTitle) }
    }
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3



    XQuery 생성 수행 및 FOR XML을 사용한 형태 정의 비교


    일부 응용 프로그램에서는 행 집합에서 XML을 생성하는 것이 요구됩니다. 서버에서는 FOR XML 절이나 XQuery 생성 또는 XML DML 작업을 사용하여 XML을 생성할 수 있습니다. FOR XML 및 XQuery 생성자를 사용하여 XML을 생성할 경우의 권장 사항은 다음과 같습니다.


    여러 열과 여러 행에서 XML을 집계하려는 경우 FOR XML만 사용할 수 있습니다.
    단일 XML 인스턴스의 형태를 변경하려는 경우 FOR XML뿐만 아니라 XQuery를 사용할 수 있습니다. FOR XML의 경우 XML 인스턴스에서 XML 데이터 형식 메서드를 여러 번 호출해야 하므로 XQuery가 더 빠를 수 있습니다.
    여러 XML DML 문을 사용하여 XML 인스턴스를 생성할 수 있습니다. 이 방법은 XQuery 생성보다 훨씬 느립니다.
    FOR XML 쿼리의 결과를 XML 데이터 형식의 인스턴스로 생성하려면 SQL Server 2005의 FOR XML 절에서 사용할 수 있는 새 TYPE 지시문을 사용합니다.



    기본 제공 XQuery 함수


    SQL Server 2005의 XQuery 구현에서는 XQuery 1.0 및 XPath 2.0 기본 제공 함수의 하위 집합이 지원됩니다. 이러한 함수에는 데이터 접근자 함수, 문자열 조작 함수, 집계 함수, 컨텍스트 함수, 숫자 함수, 부울 함수, 노드 함수, 시퀀스 함수 등이 있습니다. 다음 절에서는 이러한 함수 중 몇 가지에 대해 설명합니다.



    데이터 접근자


    데이터 접근자 함수를 사용하여 노드의 값을 문자열 또는 형식 있는 값으로 추출할 수 있습니다. XQuery는 두 가지 유형의 데이터 접근자 함수를 지원합니다. 그 중 하나인 string()은 항목의 문자열 값을 추출하며 다른 하나인 data()는 형식 있는 값을 가져옵니다. 노드가 텍스트 노드, 특성 노드 또는 요소 노드가 아닌 경우 data() 함수는 정적 오류를 발생시킵니다. 노드가 형식 없는 XML 인스턴스의 문서 노드인 경우 data()는 문서의 문자열 값을 반환합니다. 노드가 복합 형식 요소인 경우 data() 함수는 정적 오류를 반환합니다.


    예제: string() 함수 사용


    string() 함수 및 계산된 요소 생성자를 사용하여 후보의 고용 기록을 생성하는 쿼리는 이 문서의 "XQuery를 사용하여 XML 생성" 절에서 예제: 계산된 요소 및 특성 생성자에 상수 이름 사용 예제를 참조하십시오.


    예제: data() 함수 사용


    다음 쿼리는 data() 함수 및 계산된 요소 생성자를 사용하여 후보의 고용 기록을 생성합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $ED in /RES:Resume/RES:Education
    where xs:decimal( data($ED/RES:Edu.GPA) ) gt 3.5
    return
    element Education
    {
    element Level { data($ED/RES:Edu.Level) },
    element Degree { data($ED/RES:Edu.Degree) },
    element GPA { data($ED/RES:Edu.GPA) },
    element GPAScale { data($ED/RES:Edu.GPAScale) }
    }
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 2



    문자열 조작


    XQuery는 다음 네 개의 문자열 조작 함수를 지원합니다.


    concat()를 사용하여 두 개 이상의 문자열을 연결할 수 있습니다.
    contains()를 사용하면 첫 번째 피연산자로 지정된 문자열이 두 번째 피연산자로 지정된 다른 문자열을 포함하는지 여부를 결정할 수 있습니다. 검색 문자열의 길이는 4,000개의 유니코드 문자로 제한됩니다.
    substring()을 사용하면 소스 문자열로 알려진 다른 문자열에서 문자열의 일부를 추출할 수 있습니다.
    string-length()를 사용하면 문자열 길이를 계산할 수 있습니다.
    현재 릴리스의 SQL Server 2005에서는 유니코드 코드 포인트 데이터 정렬만 지원됩니다.


    예제: concat() 및 substring() 함수 사용/p>

    다음 쿼리는 start date, end date, organization name 및 job title의 값을 연결하여 후보의 고용 기록을 생성합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $EMP in /RES:Resume/RES:Employment
    return

    {
    concat( substring(string($EMP/RES:Emp.StartDate),1,10)," to ",
    substring(string($EMP/RES:Emp.EndDate),1,10), ", ",
    string($EMP/RES:Emp.OrgName), ", ",
    string($EMP/RES:Emp.JobTitle) )
    }

    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3


    예제: contains() 함수 사용


    다음 쿼리는 Edu.Degree 요소의 값에 science 문자열을 포함하는 노드에 대한 Education 세부 정보를 표시하여 contains() 함수가 사용되는 방법을 보여 줍니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $ED in /RES:Resume/RES:Education
    where contains($ED/RES:Edu.Degree, "Science")
    return
    element Education
    {
    element Level { data($ED/RES:Edu.Level) },
    element Degree { data($ED/RES:Edu.Degree) },
    element GPA { data($ED/RES:Edu.GPA) },
    element GPAScale { data($ED/RES:Edu.GPAScale) }
    }
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 2



    집계 함수


    집계 함수는 항목 시퀀스에서 작동하여 시퀀스의 집계 값을 반환합니다. 현재 SQL Server 2005의 XQuery에서 지원되는 집계 함수는 count(), min(), max(), avg() 및 sum()입니다. min() 및 max() 함수에는 gt 연산자를 지원하는 기본 형식만 허용됩니다(예: 세 가지 기본 제공 숫자 기본 형식, 날짜/시간 기본 형식, xs:string, xs:boolean 및 xdt:untypedAtomic). 혼합된 형식의 시퀀스는 이러한 함수에서 지원되지 않습니다. 또한 xdt:untypedAtomic은 xs:double로 간주됩니다.


    avg() 및 sum()의 경우 전달된 식의 형식은 기본 제공되는 세 가지 숫자 기본 형식 중 하나 또는 untypedAtomic의 하위 형식이어야 합니다(혼합 형식은 허용되지 않으며 xdt:untypedAtomic은 xs:double로 간주됨).


    count() 함수는 시퀀스의 항목 수를 반환합니다.


    예제: count() 함수 사용


    다음 쿼리는 count() 함수를 사용하여 문서에 존재하는 employment, education 및 address 요소의 수를 표시합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    Element count is { count(/RES:Resume/RES:Address) },
    Element count is { count(/RES:Resume/RES:Education) },
    Element count is { count(/RES:Resume/RES:Address) }
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3

    예제: min() 함수 사용


    쿼리는 min() 함수를 사용하여 GPA 값아 최소인 education 요소를 표시합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $ED in /RES:Resume/RES:Education
    where $ED/RES:Edu.GPA = min(/RES:Resume/RES:Education/RES:Edu.GPA)
    return
    $ED
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 2


    예제: max() 함수 사용


    다음 쿼리는 max() 함수를 사용하여 GPA 값이 최대인 education 요소를 표시합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $ED in /RES:Resume/RES:Education
    where $ED/RES:Edu.GPA = max(/RES:Resume/RES:Education/RES:Edu.GPA)
    return
    $ED
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 2


    예제: avg() 함수 사용


    다음 쿼리는 avg() 함수를 사용하여 일주일 동안의 New York과 Boston의 최고 및 최저 온도 평균을 계산합니다.


    DECLARE @Weather xml
    SET @Weather = ''



















    ''

    SELECT @Weather.query(''


    { avg(/WeatherInfo/NewYork/Temp/@High) }
    { avg(/WeatherInfo/NewYork/Temp/@Low) }


    { avg(/WeatherInfo/Boston/Temp/@High) }
    { avg(/WeatherInfo/Boston/Temp/@Low) }


    '') as Result


    예제: sum() 함수 사용


    다음 쿼리는 sum() 및 count() 함수를 사용하여 일주일 동안의 New York과 Boston의 최고 및 최저 온도 평균을 계산합니다.


    DECLARE @Weather xml
    SET @Weather = ''



















    ''

    SELECT @Weather.query(''


    { sum(/WeatherInfo/NewYork/Temp/@High) div count(/WeatherInfo/NewYork/Temp/@High) }
    { sum(/WeatherInfo/NewYork/Temp/@Low) div count(/WeatherInfo/NewYork/Temp/@Low) }


    { sum(/WeatherInfo/Boston/Temp/@High) div count(/WeatherInfo/Boston/Temp/@High) }
    { sum(/WeatherInfo/Boston/Temp/@Low) div count(/WeatherInfo/Boston/Temp/@Low) }


    '') as Result



    컨텍스트 함수


    컨텍스트 함수를 사용하여 컨텍스트 항목의 컨텍스트 속성을 얻을 수 있습니다. SQL Server 2005는 두 개의 컨텍스트 함수인 last() 및 position()을 구현합니다. last() 함수를 사용하면 시퀀스의 항목 수를 확인할 수 있으며 position() 함수를 사용하면 컨텍스트 항목의 위치를 얻을 수 있습니다. 인수가 없는 last() 및 position() 함수는 SQL Server 2005에서 컨텍스트에 무관한 조건자의 컨텍스트(예: [] 안쪽)에서만 사용할 수 있습니다.


    예제: last() 함수 사용


    다음 쿼리는 last() 함수를 사용하여 후보의 마지막 address 요소를 검색합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    /RES:Resume/RES:Address[last()]
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3


    예제: position() 함수 사용


    다음 쿼리는 position() 함수를 사용하여 후보의 처음 두 개 address 요소를 검색합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    /RES:Resume/RES:Address[position()<=2]
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3



    형식 관련 식


    XQuery는 형식 정보에 기초하는 다양한 유형의 식이나 연산자를 지원합니다. 이러한 식은 형식 어설션 식, 형식 조사 식 및 형식 캐스팅 식으로 분류됩니다. 다음 절에서는 이러한 식에 대해 간략하게 설명합니다.



    형식 어설션 식


    as xs:for 문의TYPE 절

    as 절을 사용하여 for 문에 사용되는 바인딩 변수의 형식을 지정할 수 있습니다.

    바인딩 변수에 대한 형식이 선언된 경우 선언된 형식이 아닌 바인딩 값은 형식 오류를 야기합니다. xs:TYPE 절은 캐스트 식이 아니지만 형식 어설션으로 사용됩니다.


    예제: for 문과 함께 "as xs:TYPE" 절 사용


    다음 쿼리는 형식 요소(RES:Address)로 정의되는 변수 $A에 주소 노드 시퀀스를 바인딩합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $A as element(RES:Address) in /RES:Resume/RES:Address
    return
    $A
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 2



    형식 조사 식


    instance of xs:TYPE 연산자

    instance of 연산자를 사용하면 XML 문서에 있는 항목의 런타임 형식을 식별할 수 있습니다.


    예제: "instance of xs:TYPE" 연산자 사용


    다음 쿼리는 XPath 식으로 식별된 주소 노드의 형식이 element() 형식과 일치하는지 여부를 검사합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    if ( (/RES:Resume/RES:Address)[1] instance of element() )
    then
    Selected node is an Element
    else
    Selected node is not an Element
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3



    형식 캐스팅 식


    암시적 형식 캐스팅

    XQuery 엔진은 산술 연산 또는 함수 호출을 포함하는 식의 숫자 형식 및 untypedAtomic 값에 대한 암시적 형식 캐스팅을 수행합니다. 이 프로세스를 형식 승격이라고 합니다. 예상 숫자 형식과 호환되지 않은 숫자 형식이 식 결과로 얻어질 경우 형식 승격이 발생합니다. 결과 식을 필요한 형식으로 캐스팅하는 방법으로 형식 승격이 수행됩니다.


    예제: 암시적 형식 캐스팅


    다음 쿼리는 10진수 값과 double 값에서 산술 연산을 수행합니다. 현재 시나리오에서는 xs:decimal 값을 xs:double로 승격한 후에만 식 값이 추가됩니다.


    DECLARE @Result xml
    SET @Result = ''''
    SELECT @Result.query(''
    { xs:decimal("10.55") + xs:double(1.5e1) }
    '') as Result


    명시적 형식 캐스팅
    형식 있는 값 생성자

    XQuery는 XML 스키마 사양에 정의된 모든 기본 제공 형식에 대한 생성자 함수를 제공합니다. 이러한 생성자는 형식 있는 값을 생성하는 경우와 특정 형식의 값을 다른 형식으로 캐스팅하는 경우에 유용하게 사용됩니다. 또한 XQuery에서는 가져온 스키마에 정의된 형식에 대해 생성자를 사용할 수 있습니다.


    예제: 값 생성자를 사용하여 값 생성


    다음 쿼리는 xs:date 형식에 대한 생성자를 사용하여 생성한 값보다 큰 StartDate를 가지는 모든 Employment 노드를 반환합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $EMP in /RES:Resume/RES:Employment
    where $EMP/RES:Emp.StartDate gt xs:date("1995-01-01")
    return
    $EMP
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 3


    예제: 값 생성자를 사용하여 형식 캐스팅


    다음 쿼리는 JobCandidateID가 2인 후보에 대해 GPA가 3.8보다 크거나 같은 모든 Education 노드를 선택합니다. 이 쿼리는 Edu.GPA 값을 xs:string에서 xs:decimal로 형식 캐스팅하기 위해 xs:decimal에 대한 값 생성자를 사용합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $ED in /RES:Resume/RES:Education
    where xs:decimal( data($ED/RES:Edu.GPA) ) ge 3.8
    return
    element Education
    {
    element Level { string($ED/RES:Edu.Level)},
    element StartDate { string($ED/RES:Edu.StartDate)},
    element EndDate { string($ED/RES:Edu.EndDate)},
    element Degree { string($ED/RES:Edu.Degree)},
    element GPA { string($ED/RES:Edu.GPA)},
    element GPAScale { string($ED/RES:Edu.GPAScale)}
    }
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 2


    cast as xs:TYPE ? 연산자


    SQL Server 2005의 XQuery는 명시적 형식 캐스팅을 수행하는 데 유용한 cast as TYPE ? 연산자를 지원합니다. 또한 cast as TYPE ? 연산자보다 편리하게 작성할 수 있는 xs:TYPE() 생성자를 사용하여 명시적 형식 캐스팅을 수행할 수도 있습니다.


    예제: "cast as xs:TYPE ?" 연산자 사용


    다음 쿼리는 JobCandidateID가 3인 후보에 대해 Education 노드 집합에서 선택한 요소의 형식 있는 값을 포함하는 XML을 생성합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $ED in /RES:Resume/RES:Education
    return
    element Education
    {
    element Level { $ED/RES:Edu.Level cast as xs:string? },
    element StartDate { $ED/RES:Edu.StartDate cast as xs:date? },
    element EndDate { $ED/RES:Edu.EndDate cast as xs:date? },
    element Degree { $ED/RES:Edu.Degree cast as xs:string? },
    element GPA { $ED/RES:Edu.GPA cast as xs:decimal? },
    element GPAScale { $ED/RES:Edu.GPAScale cast as xs:decimal? }
    }
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 2


    예제: "xs:TYPE()" 연산자 사용


    다음 쿼리는 cast as xs:TYPE ? 연산자 대신에 xs:TYPE() 연산자를 사용하여 앞의 예제 쿼리와 동일한 결과를 생성합니다.


    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $ED in /RES:Resume/RES:Education
    return
    element Education
    {
    element Level { xs:string($ED/RES:Edu.Level) },
    element StartDate { xs:date($ED/RES:Edu.StartDate) },
    element EndDate { xs:date($ED/RES:Edu.EndDate) },
    element Degree { xs:string($ED/RES:Edu.Degree) },
    element GPA { xs:decimal($ED/RES:Edu.GPA) },
    element GPAScale { xs:decimal($ED/RES:Edu.GPAScale) }
    }
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = 2



    관계형 열과 변수 액세스


    XQuery를 사용하여 쿼리를 작성할 경우 쿼리에서 관계형 열과 변수에 액세스하는 것이 일반적으로 요구됩니다. SQL Server 2005는 두 개의 함수인 sql:column() 및 sql:variable()을 구현하여 이 요구 사항을 충족합니다.


    sql:column() 함수를 사용하면 쿼리에서 관계형 테이블에 있는 비 XML 열에 액세스할 수 있습니다. 이 함수는 하나 이상의 테이블에 있는 XML 및 비 XML 열에서 정보를 집계하거나 비 XML 열의 값을 사용하여 XQuery 결과를 필터링하는 등의 상황에 유용합니다. sql:column() 및 sql:variable() 함수는 datetime, CLR 사용자 정의 함수 또는 XML과 함께 사용할 수 없습니다.


    예제: sql:column() 함수 사용


    다음 쿼리는 비 XML 데이터 형식의 CustomerID 및 Name 열에 있는 값과 Demographics 열에 있는 YearOpened, NumberOfEmployees, AnnualSales 및 AnnualRevenue 요소의 값을 포함하는 XML을 생성합니다.


    SELECT Demographics.query(''
    declare namespace ST="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey";
    element CustomerInfo
    {
    element CustomerID { sql:column("Store.CustomerID") },
    element Name { sql:column("Store.Name") },
    element YearOpened { string((/ST:StoreSurvey/ST:YearOpened)[1]) },
    element NumberOfEmployees { string((/ST:StoreSurvey/ST:NumberEmployees)[1]) },
    element AnnualSales { string((/ST:StoreSurvey/ST:AnnualSales)[1]) },
    element AnnualRevenue { string((/ST:StoreSurvey/ST:AnnualRevenue)[1]) }
    }
    '') as Result
    FROM [Sales].[Store] Store
    WHERE Store.CustomerID = 4


    예제: sql:variable() 함수 사용


    다음 저장 프로시저는 XQuery where 절의 @AddrType 변수 값을 사용하여 쿼리 결과를 필터링함으로써 지정된 후보의 home address 노드를 반환합니다.


    CREATE PROCEDURE [GetCandidateAddress]
    @JobCandidateID [int],
    @AddrType [varchar](20)
    AS
    BEGIN
    SET NOCOUNT ON;

    SELECT Resume.query(''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    for $A in /RES:Resume/RES:Address
    where $A[ RES:Addr.Type = sql:variable("@AddrType") ]
    return
    $A
    '') as Result
    FROM [HumanResources].[JobCandidate]
    WHERE JobCandidateID = @JobCandidateID

    END


    예제: XML 데이터 형식의 exist() 메서드와 함께 sql:variable() 함수 사용


    다음 쿼리는 경영학 학사 학위를 가진 후보의 이력서를 반환합니다.


    DECLARE @EducationLevel varchar(20)
    SET @EducationLevel = ''Bachelor''

    DECLARE @Major varchar(20)
    SET @Major = ''Business''

    SELECT JobCandidateID, Resume
    FROM [HumanResources].[JobCandidate]
    WHERE Resume.exist (''
    declare namespace RES="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
    /RES:Resume/RES:Education[ RES:Edu.Level = sql:variable("@EducationLevel") and RES:Edu.Major = sql:variable("@Major") ]'') = 1



    지원되지 않는 기능과 해결 방법


    현재 SQL Server 2005에서 구현된 XQuery는 다음 기능을 지원하지 않습니다.


    * let 절: FLWOR 식의 일부인 let 절은 변수를 식 결과에 바인딩하는 데 유용합니다. 해결 방법 - let 절을 사용하는 대신에 인라인 식을 사용합니다.


    * 범위 식(to 연산자): 범위 식을 사용하면 to 연산자를 사용하여 연속된 정수 시퀀스를 생성할 수 있습니다. 예를 들어, (6 to 10)와 같은 범위 식을 사용하면 (6, 7, 8, 9, 10) 시퀀스를 생성할 수 있습니다. 해결 방법 - to 연산자를 사용하는 대신에 시퀀스의 모든 항목을 나열합니다.


    * 형식 정보: typeswitch, treat as, castable 및 validate 식과 같은 형식 시스템에 기반을 두는 일부 기능은 현재 지원되지 않습니다.

    • typeswitch 식 기능은 다른 프로그래밍 언어에서 사용할 수 있는 switch-case 구문과 비슷합니다. switch-case 문에서 branch/case는 스위치에 전달된 인수 값에 따라 선택됩니다. typeswitch 식에서 branch는 typeswitch에 전달된 인수 유형에 따라 선택됩니다. 해결 방법 ? if then else 및 instance of를 사용합니다.

    • treat as 식을 사용하면 식 결과의 정적 형식을 특정 정적 형식으로 변경할 수 있으며 식의 정적 형식이 지정된 형식과 일치하지 않을 경우 정적 형식 오류가 발생합니다. 식의 동적 형식이나 값은 변경되지 않습니다. 해결 방법 ? 없음

    • castable 식은 원자 값을 지정된 형식으로 캐스팅할 수 있는지 여부를 검사하는 데 유용합니다. 해결 방법 - "$x castable as T?" 식을 사용하는 대신에 "empty(data($x)) or not(empty(T($x)))" 식을 사용합니다.

    • validate 식은 현재 범위에 존재하는 스키마 정의에 기초하여 인수에 대한 유효성 검사를 수행합니다. 해결 방법 - validate 식을 사용하는 대신에 요청된 스키마 컬렉션에 대한 Transact-SQL 캐스팅을 사용합니다.

    * 재사용성: 다른 프로그래밍 언어에서와 마찬가지로 유용하고 복잡한 쿼리를 포함하는 사용자 정의 함수로 알려진 재사용 가능한 함수를 작성할 수 있습니다. 또한 사용자 정의 함수 컬렉션을 모듈로 패키지화할 수 있습니다. 쿼리는 모듈을 가져와 모듈에서 제공되는 함수를 사용할 수 있습니다. 쿼리의 프롤로그 섹션에 포함하여 모듈을 쿼리로 가져올 수 있습니다. 현재 SQL Server 2005에서는 해결 방법이 없습니다.


    * 기본 제공 함수: 현재 SQL Server 2005에서는 다음 기본 제공 함수가 지원되지 않습니다. 이러한 함수에 대한 자세한 내용은 W3C.org 웹 사이트에서 XQuery 1.0 및 XPath 2.0 함수 및 연산자 (영문)를 참조하십시오.

    • 접근자: fn:node-name(), fn:nilled(), fn:base-uri(), fn:document-uri().

    • 오류 함수: fn:error().

    • 추적 함수: fn:trace().

    • 숫자 값에 대한 함수: abs(), round-half-to-even().

    • 문자열 처리 함수: codepoints-to-string(), string-to-codepoints(), compare(), string-join(), normalize-space(), normalize-unicode(), upper-case(), lower-case(), translate(), escape-uri(), starts-with(), ends-with(), substring-before(), substring-after(), matches(), replace(), tokenize().

    • anyURI에 대한 함수 및 연산자: resolve-uri().

    • 기간, 날짜 및 시간에 대한 함수 및 연산자: years-from-duration(), months-from-duration(), days-from-duration(), hours-from-duration(), minutes-from-duration(), seconds-from-duration(), year-from-dateTime(), month-from-dateTime(), month-from-dateTime(), day-from-dateTime(), hours-from-dateTime(), minutes-from-dateTime(), seconds-from-dateTime(), timezone-from-dateTime(), year-from-date(), month-from-date(), day-from-date(), timezone-from-date(), hours-from-time(), minutes-from-time(), seconds-from-time(), timezone-from-time(), adjust-dateTime-to-timezone(), adjust-date-to-timezone(), adjust-time-to-timezone(), subtract-dateTimes-yielding-yearMonthDuration(), subtract-dateTimes-yielding-dayTimeDuration(), subtract-dates-yielding-yearMonthDuration(), subtract-dates-yielding-dayTimeDuration(). 또한 xdt:dayTimeDuration 및 xdt:yearMonthDuration 형식도 지원되지 않습니다.


    • Qnames와 관련된 함수: resolve-QName(), QName(), namespace-uri-for-prefix(), in-scope-prefixes().
    • 노드에 대한 함수: name(), lang(), root(). 해결 방법 - root() 대신 /을 사용합니다.
    • 시퀀스에 대한 함수 및 연산자: fn:boolean(), fn:index-of(), fn:exists(), insert-before(), remove(), reverse(), subsequence(), unordered(), zero-or-one(), one-or-more(), exactly-one(), deep-equal(), 두 개의 인수를 가지는 id(), idref(), doc(), collection() 함수 및 union, intersect 및 except 연산자. 해결 방법 ? fn:boolean() 대신 not(not())을, fn:exists() 대신 not(empty())을, zero-or-one() 또는 exactly-one() 대신 명시적 for iteration 또는 [1]을 사용합니다.
    • 컨텍스트 함수: current-dateTime(), current-date(), current-time(), default-collation(), implicit-timezone().


    *위치 변수: at 절을 사용하여 FLWOR 문의 일부로 위치 변수를 정의할 수 있습니다. 위치 변수는 식 결과에서 항목 위치를 식별하는 데 유용합니다.


    *순서 한정자: order by 절을 사용하여 지정된 순서 한정자 "empty greatest | least"는 지원되지 않습니다. ? 기타 기능: 다음 기능은 지원되지 않습니다.


    *기타 기능: The following features are not supported:

    • idiv 연산자.

    • 명시적 스키마 가져오기는 지원되지 않습니다.

    • 외부 변수는 지원되지 않습니다.

    • 경계 공백 유지 옵션은 지원되지 않습니다.

    • 노드 및 값과 같은 유형이 다른 시퀀스를 연결하는 기능은 지원되지 않습니다.

    • 표준 시간대 유지는 지원되지 않습니다.

    • 단순 형식 콘텐츠를 가진 요소의 텍스트 노드에 액세스하는 기능은 지원되지 않습니다.

    • 형식 있는 XML 데이터 형식 인스턴스의 xsi:* 특성에 액세스하는 기능은 지원되지 않습니다.


    최상의 실행 방법 및 지침


  • 형식 정보가 있는 경우 활용합니다. 형식 정보를 활용하면 성능이 향상되며 정적 형식 검사를 수행하여 오류를 발견할 수 있습니다.

  • XML 데이터 형식에서 일부 속성 값을 추출하여 관계형 쿼리에서 사용하려면 속성 승격을 위해 XQuery를 사용합니다. 성능 향상을 위해 자주 사용되는 속성이 관계형 열로 승격되고 인덱싱됩니다.

  • 카디널리티 불일치로 인한 정적 오류를 방지하기 위해 서수(예: [1]) 또는 명시적 FLWOR을 사용합니다.

  • 정적 형식 오류를 방지하기 위해 명시적 캐스트를 사용합니다.

  • 인덱스 사용: Xpath 식을 많이 사용하는 쿼리가 있을 경우 PATH 인덱스를 만듭니다. 부정확하게 알려진 경로(예: /a/* 또는 //b)를 가진 요소 또는 특성 값을 검색하는 작업이 포함된 Xpath 식이 XQuey 쿼리에 있는 경우 VALUE 인덱스를 사용합니다. XML 인스턴스에서 알려진 속성의 모든 경우를 쿼리에서 검색하는 경우에 PROPERTY 인덱스가 유용합니다.

  • 참조된 대부분의 형식이 단일 네임스페이스의 일부이면 기본 네임스페이스를 사용하여 그렇지 않으면 접두사를 사용합니다.


    최상의 실행 방법에 대한 자세한 내용은 MSDN 기사 Microsoft SQL Server 2005를 위한 XML 최상의 실행 방법 및 XML 데이터 형식을 위한 성능 최적화를 참조하십시오.



    XML 데이터 수정


    SQL Server 2005는 데이터베이스에 저장된 XML 인스턴스를 수정하는 것을 지원합니다. 최신 버전의 W3C XQuery 초안에는 XML 문서를 수정하기 위한 구문이 정의되어 있지 않습니다. XML 문서를 수정하기 위한 메커니즘을 제공하고 위해 Microsoft는 XML DML(Data Modification Language)을 개발했습니다. XML 데이터 형식의 modify 메서드를 사용하고 XML DML 문으로 수정을 지정하여 XML 문서를 수정할 수 있습니다.


    XML DML은 insert, delete 및 replace value of 키워드를 사용하여 XML 문서에서 삽입, 삭제 및 업데이트 작업을 지원합니다. 형식 있는 XML 인스턴스의 수정은 XML 데이터 형식에 정의된 스키마 제약 조건에 기반을 두는 유효성 검사를 따릅니다.


    다음 테이블과 XML 인스턴스는 XML DML 작업을 보여 줍니다.


    테이블:


    CREATE TABLE [CandidateInfoXMLDataType]
    (
    [JobCandidateID] [int] IDENTITY(1,1) NOT NULL,
    [Resume] [xml] NOT NULL,
    [ModifiedDate] [datetime] NOT NULL DEFAULT (getdate())
    )


    샘플 XML 인스턴스:




    Mike

    Chen


    34 181st Place SE
    Apt 3344
    Redmond
    WA
    US
    9870909023


    BS
    MS


    ASP.NET
    SQL



    ABC Technologies
    NY, US
    20/02/2000
    10/04/2004
    Project Leader
    Responsible for design,development,testing activities




    삽입 작업


    insert 키워드를 사용하여 하나 이상의 노드를 XML 문서에 삽입할 수 있습니다. insert 키워드에는 삽입할 노드를 식별하는 XQuery 식과 참조 노드를 지정하는 다른 XQuery 식이 허용됩니다.

    또한 참조 노드와 관련하여 새 노드를 위치를 지정하기 위해 into, after 및 before와 같은 키워드를 포함할 수 있습니다. into 키워드를 지정할 경우 새 노드가 참조 노드의 자식으로 삽입됩니다. into 키워드를 포함할 경우 참조 노드의 기존 자식 노드와 관련하여 삽입된 노드의 위치를 나타내는 as first 또는 as last 키워드도 지정해야 합니다. 또한 after 또는 before 키워드를 지정하여 참조 노드 뒤쪽이나 앞쪽에 새 노드를 형제 노드로 삽입할 수 있습니다.

    대상 식(Expression2)이 단일 노드를 정적으로 식별하지 않은 경우 삽입 작업이 실패하고 정적 오류가 발생합니다.


    구문:


    insert
    Expression1 (
    {{{as first | as last} into} | after | before}
    Expression2 )


    예제: 기술 삽입


    다음 저장 프로시저를 사용하면 지정된 후보에 대한 새 기술을 삽입할 수 있습니다. 이 저장 프로시저는 sql:variable() 함수를 사용하여 XML DML 문 안에 있는 Transact-SQL 변수에 액세스합니다. XML 안에서 비 XML 관계형 데이터를 바인딩하는 방법에 대한 자세한 내용은 관계형 열과 변수 액세스를 참조하십시오.


    다음 저장 프로시저는 사용자가 특정 기술의 문자열 값을 두 번째 인수로 저장 프로시저에 전달한다는 가정 하에 작성되었습니다. 하나 이상의 기술 요소를 포함하는 XML 단편을 허용하도록 이 저장 프로시저를 수정할 수 있습니다. 이렇게 하면 사용자는 한 번의 호출로 여러 기술 노드를 저장 프로시저에 삽입할 수 있습니다.


    /* Stored procedure to insert a new skill element for a candidate */
    CREATE PROCEDURE [InsertSkillInfo]
    @JobCandidateID [int],
    @Skill [varchar](200)
    AS
    BEGIN
    SET NOCOUNT ON;

    UPDATE [CandidateInfoXMLDataType]
    SET Resume.modify(''
    insert element Skill {sql:variable("@Skill")}
    as last
    into (/JobCandidate/Skills)[1]
    '')
    WHERE JobCandidateID = @JobCandidateID
    END



    삭제 작업


    delete 키워드를 사용하면 XML 인스턴스에서 하나 이상의 노드를 삭제할 수 있습니다. delete 키워드에서는 XML 문서에 삭제할 하나 이상의 노드를 식별하는 XQuery 식이 허용됩니다.


    구문:

    delete Expression


    예제: 기술 삭제

    다음 예제는 delete 키워드를 사용하여 지정된 후보의 기술을 삭제하는 방법을 보여 줍니다.


    다음 저장 프로시저는 사용자가 특정 기술의 문자열 값을 두 번째 인수로 저장 프로시저에 전달한다는 가정 하에 작성되었습니다. 하나 이상의 기술 요소를 포함하는 XML 단편을 허용하도록 이 저장 프로시저를 수정할 수 있습니다. 이렇게 하면 사용자는 저장 프로시저를 한 번 호출하여 여러 기술 노드를 삭제할 수 있습니다.


    /* Stored procedure to delete a specified skill element for a candidate */
    CREATE PROCEDURE [DeleteSkillInfo]
    @JobCandidateID [int],
    @Skill [varchar](200)
    AS
    BEGIN
    SET NOCOUNT ON;

    UPDATE [CandidateInfoXMLDataType]
    SET Resume.modify(''
    delete (/JobCandidate/Skills/Skill[.=sql:variable("@Skill")])
    '')
    WHERE JobCandidateID = @JobCandidateID
    END


    하나 이상의 기술 요소를 포함하는 XML 단편을 허용하도록 이 저장 프로시저를 쉽게 수정할 수 있습니다. 이 경우 사용자는 저장 프로시저를 한 번 호출하여 여러 기술 노드를 삭제할 수 있습니다.


    업데이트 작업


    replace value of 키워드를 사용하면 기존 노드의 값을 수정할 수 있습니다. 기존 노드의 값을 수정하려면 값을 업데이트할 노드를 식별하는 하나의 XQuery 식과 노드의 새 값을 지정하는 또 다른 식을 지정해야 합니다.


    형식 없는 XML 인스턴스를 수정하는 동안 대상 식은 단순 형식 노드를 반환해야 합니다. 형식 있는 XML 인스턴스의 대상 식은 소스 식과 동일한 형식 또는 하위 형식으로 평가되어야 합니다.


    구문:

    replace value of
    Expression1
    with
    Expression2


    예제: 기술 업데이트

    다음 예제는 replace value of 키워드를 사용하여 지정된 후보의 기존 기술 값을 업데이트하는 방법을 보여 줍니다.


    /* Stored procedure to update a specified skill element for a candidate */
    CREATE PROCEDURE [UpdateSkillInfo]
    @JobCandidateID [int],
    @SkillOld [varchar](200),
    @SkillNew [varchar](200)
    AS
    BEGIN
    SET NOCOUNT ON;

    UPDATE [CandidateInfoXMLDataType]
    SET Resume.modify(''
    replace value of (/JobCandidate/Skills/Skill[.=sql:variable("@SkillOld")]/text())[1]
    with sql:variable("@SkillNew")
    '')
    WHERE JobCandidateID = @JobCandidateID
    END


    delete 작업과 달리 update 및 insert 작업은 한 번의 작업으로 하나의 노드에만 영향을 줄 수 있습니다.



    XQuery 사용 시나리오


    시나리오 1: 성과 평가 시스템

    회사의 인사부에는 일반적인 평가 관련 활동을 처리하는 성과 평가 시스템이 필요합니다. 일반적으로 평가 레코드에는 평가 기간의 주요 목표와 비교하여 측정된 직원 성과, 다음 평가 기간에 사용할 주요 목표 정의, 직원 교육 요구 식별 등과 같이 주로 설명적인 특성을 가지는 정보가 포함됩니다. XML은 이러한 정보를 처리하는 데 가장 적합합니다. 직원에 대한 평가 정보가 XML 형식 열에 저장될 수 있으며 시스템 사용자는 XQuery를 사용하여 직원의 성과 기록을 쿼리 및 분석할 수 있습니다. 또한 XML DML을 사용하여 평가 레코드를 수정할 수 있습니다.


    회사의 교육 부서가 ASP.NET에 대한 교육 세션을 수행하고 있으며 이러한 교육을 요청했던 모든 직원을 초대하려고 한다고 가정해 보십시오. 다음 쿼리는 평가 프로세스 도중에 ASP.NET에 대한 교육 세션을 선택했던 모든 직원을 선택합니다.


    SELECT Appraisal.query(''
    for $PA in /PerformanceAppraisal,
    $Skill in $PA/TrainingNeeds/Technical/Skill
    where contains($Skill, "ASP.NET")
    return
    element Employee
    {
    element EmpID { data($PA/Employee/EmployeeID) },
    element EmpName { data($PA/Employee/EmployeeName) },
    element EMail { data($PA/Employee/EMailID) },
    element Skill { data($Skill) }
    }
    '') as Result
    FROM [EmployeePerformanceAppraisal]
    WHERE Appraisal.exist(''/PerformanceAppraisal/TrainingNeeds/Technical/Skill/text()[contains(.,"ASP.NET")]'') = 1



    시나리오 2: 의료 레코드 시스템


    병원에서는 환자와 관련된 의료 정보를 캡처할 수 있는 시스템이 필요합니다. 이 정보에는 환자 세부 정보, 보험 정보, 입원 세부 정보, 진단 정보, 치료 정보 등이 포함됩니다. 이 정보는 연구 또는 참조 목적에 사용될 것입니다. 증상, 실험실 보고서 및 치료 정보와 같은 환자 의료 데이터에는 설명 정보가 포함되어 있으므로 이 정보를 저장하기 위한 형식으로 XML이 선택됩니다. 환자 데이터는 XML 형식 열에 저장될 수 있습니다. 병원에서는 이 정보를 분석하기 위해 XQuery를 사용할 수 있습니다.


    다음 테이블과 XML 인스턴스는 환자 의료 레코드 시나리오에서 사용되는 XQuery를 보여 줍니다.


    테이블:

    CREATE TABLE [MedicalRecords](
    [PatientID] [int] IDENTITY(1,1) NOT NULL,
    [PatientRecord] [xml] NOT NULL,
    [ModifiedDate] [datetime] NOT NULL DEFAULT (getdate())
    ,
    PRIMARY KEY CLUSTERED
    (
    [PatientID] ASC
    ) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    CREATE PRIMARY XML INDEX idx_PatientRecord on [MedicalRecords] (PatientRecord)
    GO
    CREATE XML INDEX idx_PatientRecord_Path on [MedicalRecords] (PatientRecord) USING XML INDEX idx_PatientRecord FOR PATH


    샘플 XML 인스턴스:



    Robert
    Male
    5

    Blue Cross Blue Shield
    D8456798



    KK Hospital
    Pediatrics


    D4321
    2004-05-02
    2004-05-08



    Abdominal pain
    Dehydration

    Diarrhea

    Oral Rehydration Therapy

    Pepto-Bismol
    Electrolyte Solutions




    “고열”과 “복통” 증상으로 입원했던 환자에 대한 의료 레코드를 의사가 보고 싶어한다고 가정해 보십시오. 다음 쿼리는 “고열”과 “복통” 증상으로 입원했던 환자의 레코드를 검색합니다.


    SELECT PatientID, PatientRecord.query(''
    element PatientName { data(/PatientRecord/PatientDetails/Name) },
    element MedicalInfo { /PatientRecord/ProblemDetails }
    '') as Result
    FROM [MedicalRecords]
    WHERE PatientRecord.exist
    (''/PatientRecord/ProblemDetails/Symptoms/Symptom/text()[contains(.,"Fever")]'') = 1
    AND PatientRecord.exist
    (''/PatientRecord/ProblemDetails/Symptoms/Symptom/text()[contains(.,"Abdominal Pain")]'') = 1



    시나리오 3: 자산 관리 시스템


    회사의 IT 부서는 하드웨어 및 소프트웨어와 같은 자산을 관리할 수 있는 응용 프로그램을 개발해야 합니다. 이 응용 프로그램은 자산 ID, 사용자 세부 정보, 시스템 정보(예: 프로세서, 메모리, BIOS, 마더보드 및 비디오 카드 세부 정보), 시스템에 설치된 소프트웨어, 구매 정보, 보증 정보 등을 비롯하여 하드웨어 자산과 관련된 정보를 추적할 수 있어야 합니다.


    또한 이 응용 프로그램은 소프트웨어 유형, 구매한 라이센스 수 등과 같은 조직의 소프트웨어 자산과 관련된 정보를 유지 관리해야 하며 미래에 정의될 새 자산 유형을 처리하도록 확장할 수 있어야 합니다. 이 자산 관리 시스템은 하드웨어 사용 정보, 소프트웨어 라이센스 사용 정보, 유지 관리해야 할 하드웨어 항목 등과 같은 보고서를 생성하는 데 사용됩니다. 현재의 시나리오에서는 동일한 테이블 열의 다른 스키마를 따르는 정보를 저장하는 것이 필요합니다. 형식 없는 XML을 사용하여 다양한 스키마를 가진 정보를 저장할 수 있습니다. 또한 스키마 컬렉션이 있는 형식 있는 XML을 사용하여 이러한 정보를 저장할 수 있습니다. XML 데이터 형식으로 저장된 자산 정보는 XQuery를 사용하여 쿼리할 수 있습니다.


    IT 부서에서 Microsoft Windows XP와 Microsoft Office 2000이 모두 설치된 컴퓨터 시스템 목록을 선택하고 싶어한다고 가정해 보십시오. 다음 쿼리는 Windows XP와 Office 2000이 모두 설치된 하드웨어 자산의 레코드를 선택합니다.


    SELECT AssetID, AssetDetails.query(''

    {
    element UserName { data(/AssetInfo/UserInfo/Name) },
    element ComputerName { data(/AssetInfo/SystemInfo/ComputerName) },
    element OS { data(/AssetInfo/SystemInfo/OS) }
    }

    '') as Result
    FROM [Assets]
    WHERE Category = ''Hardware''
    AND AssetDetails.exist(''/AssetInfo/SystemInfo/OS/text()[contains(.,"Windows XP")]'') = 1
    AND AssetDetails.exist(''/AssetInfo/SoftwaresInstalled/Software/text()[contains(.,"Office 2000")]'') = 1



    결론


    SQL Server 2005와 관련하여 XQuery의 기본적인 내용을 배우고 싶은 사람들은 이 문서를 기초서로 사용할 수 있을 것입니다. 이 문서에서는 SQL Server 2005에서 구현된 XQuery 언어의 여러 기능과 지원되지 않는 기능에 대해 설명하고 XQuery 언어의 여러 기능을 사용하는 예제를 제공했습니다. 이 문서에 포함된 XQuery 사용 시나리오는 XQuery를 사용하기에 적합한 상황을 식별하는 데 도움이 될 것입니다.




    제공 : DB포탈사이트 DBguide.net

    출처명: 한국 마이크로소프트

  • 728x90

    Microsoft SQL Server 2005를 위한 최상의 XML 실행 방법


    저자: Shankar Pal, Vishesh Parikh, Vasili Zolotov, Leo Giakoumakis, Michael Rys Microsoft Corporation

    2004년 4월

    적용 대상:
    Microsoft SQL Server

    SQL Server 2005에서 XML 데이터 모델링 및 사용법에 대한 지침을 확인하고 자세한 예를 살펴봅니다. 이 문서를 최대한 활용하기 위해서는 SQL Server의 XML 기본 기능에 대해 이해해야 합니다. 기본 자료를 보려면 Microsoft Development Network에서 Microsoft SQL Server 2005의 XML 지원을 참조하십시오.


    소개

    SQL Server 2000 및 SQLXML 웹 릴리스는 강력한 XML 데이터 관리 기능을 제공합니다. 이러한 기능은 관계형 데이터 및 XML 데이터 간의 매핑에 중점을 둡니다. XML 데이터의 대량 로드, XML 데이터에 대한 쿼리 및 업데이트 기능을 지원하는 XML 중심 접근 방식을 제공하도록 주석 처리된 XSD(AXSD)를 사용하여 관계형 데이터에 대한 XML 뷰를 정의할 수 있습니다. Transact-SQL 확장은 FOR XML을 사용한 XML에 대한 관계형 쿼리 결과 매핑과 OpenXML을 사용한 XML로부터의 관계형 뷰 생성에 대한 SQL 중심 접근 방법을 제공합니다.

    Microsoft SQL Server 2005는 XML 데이터 처리에 대한 포괄적인 지원을 제공합니다. XML 값을 XML 데이터 형식 열에 원래대로 저장하여 XML 스키마 컬렉션에 따라 형식이 있거나 형식이 없는 상태로 유지할 수 있습니다. XML 열을 인덱싱할 수 있습니다. 또한 XQuery 및 XML DML을 사용하여 세밀하게 조정된 데이터 조작이 지원되며 XML DML은 데이터 수정을 위한 확장으로 사용됩니다.

    또한 SQL Server 2005에는 SQLXML, FOR XML 및 OpenXML 기능이 확장되었습니다. 네이티브 XML 지원이 새로 추가된 SQL Server 2005는 반구조적 및 구조화되지 않은 데이터 관리를 위한 다양한 기능의 응용 프로그램을 개발하기 위한 강력한 플랫폼을 제공합니다.

    추가된 모든 기능을 통해 사용자는 자신의 데이터 저장소 및 응용 프로그램 개발에 맞는 다양한 디자인 요소를 활용할 수 있습니다. 이 문서에서는 SQL Server 2005에서 XML 데이터 모델링 및 사용법에 대한 지침을 제공합니다. 이 문서는 다음 두 항목으로 나눠져 있습니다.

    ① 데이터 모델링
    SQL Server 2005에서 네이티브 XML 데이터 형식 및 테이블로 나눠진 XML 등의 여러 방식을 사용하여 XML 데이터를 저장할 수 있습니다. 이 항목에서는 XML 데이터 모델링에 적합한 항목을 선택하기 위한 지침을 제공합니다. 또한 XML 데이터 인덱싱, 속성 승격 및 XML 인스턴스 형식화에 대해 설명합니다.

    ② 사용법
    이 항목에서는 XML 데이터를 서버로 로드하고, 쿼리 컴파일 중에 유형을 유추하는 등의 사용법과 관련된 항목에 대해 설명하고 관련 기능 및 기능 간 차이점에 대해 설명하고 이러한 기능의 적합한 사용법을 권장합니다. 이러한 개념들을 도표로 설명합니다.

    데이터 모델링


    이 섹션에서는 SQL Server 2005에서 XML을 사용하는 이유에 대해 간단히 설명하고 네이티브 XML 저장소 및 XML 뷰 기술 간의 선택 지침을 제공하고 데이터 모델링 권장 사항을 제공합니다.

    관계형 데이터 또는 XML 데이터 모델

    데이터가 알려진 스키마를 사용하여 상당히 세부적으로 구조화된 데이터 저장소의 경우 관계형 모델이 가장 적합할 수 있습니다. Microsoft SQL Server는 사용자에게 필요한 필수 기능 및 도구를 제공합니다. 반면에 구조가 유연한 경우(반구조적 또는 구조화되지 않은)나 알 수 없는 경우에는 이러한 데이터의 모델링에 더욱 많은 주의가 필요합니다.

    구조적 및 의미적 태그를 사용하여 데이터의 이식성을 보장하기 위해 플랫폼에 의존하지 않는 모델이 필요한 경우에는 XML이 적합합니다. 또한 다음 속성 중 일부만 만족하는 경우에도 적합합니다.
    • 데이터가 산발적으로 되어 있고 데이터 구조를 모르거나 데이터 구조가 이후에 크게 바뀔 수 있습니다.
    • 데이터가 포함 계층(엔터티 간 참조와 반대)을 나타내고 재귀적일 수 있습니다.
    • 태그 및 값의 순서가 데이터에 내재적입니다.
    • 데이터 구조를 기준으로 데이터를 쿼리하거나 데이터 일부를 업데이트합니다.

    이러한 조건 중 어느 것도 충족되지 않으면 관계형 데이터 모델을 사용해야 합니다. 예를 들어 데이터가 XML 형식이지만 응용 프로그램이 단순히 데이터베이스를 사용하여 데이터를 저장 및 검색하는 경우에는 [n]varchar(max) 열만 필요합니다.

    데이터를 XML 열에 저장하면 엔진에서 데이터가 미리 지정된 XML 스키마에 따라 잘 형성되었거나 유효한지 확인할 수 있는 추가 장점이 있으며 XML 데이터에 대한 세밀하게 조정된 쿼리 및 업데이트가 지원됩니다.

    SQL Server 2005에 XML 데이터를 저장하는 이유

    다음은 파일 시스템에서 XML 데이터를 관리하는 것과는 반대로 SQL Server 2005에서 네이티브 XML 기능을 사용하는 일부 이유입니다.

    • 백업, 복구 및 복제와 같은 XML 데이터 관리를 위해 데이터베이스 서버의 관리 기능을 사용합니다.
    • XML 데이터를 효율적인 트랜잭션 방식으로 공유, 쿼리 및 수정합니다. 응용 프로그램에 세밀하게 조정된 데이터 액세스가 중요합니다. 예를 들어 XML 문서 내에서 일부 섹션을 추출하거나 전체 문서를 바꾸지 않고 새 섹션을 삽입합니다.
    • 관계형 데이터와 SQL 응용 프로그램이 있으며 응용 프로그램 내에서 관계형 데이터와 XML 데이터 간의 상호 운영이 필요합니다. 도메인 간 응용 프로그램에 대해 쿼리 및 데이터 수정을 위한 언어 지원이 필요합니다.
    • 서버에서 잘 형성된 데이터를 보장하고 선택적으로 XML 스키마에 따라 데이터의 유효성을 검사해야 합니다.
    • 효율적인 쿼리 처리 및 뛰어난 확장성을 위한 XML 데이터 인덱싱 및 최상의 쿼리 최적화 프로그램을 사용해야 합니다.
    • XML 데이터에 대한 SOAP, ADO.NET 및 OLE DB 액세스가 필요합니다.

    이러한 조건 중 어느 것도 충족되지 않으면 데이터를 [n]varchar(max) 또는 varbinary(max)와 같은 비-XML의 큰 개체 유형으로 저장하는 것이 좋습니다.

    XML 저장소 옵션

    SQL Server 2005에서 XML에 대한 저장소 옵션은 다음과 같습니다.

  • XML 데이터 형식의 네이티브 저장소:
    포함 계층, 문서 순서, 요소 및 특성 값과 같은 데이터의 XML 내용이 보존되는 내부 표현으로 데이터가 저장됩니다. 특히 XML 데이터의 InfoSet 내용이 보존됩니다(InfoSet에 대한 자세한 내용은 http://www.w3.org/TR/xml-infoset (영문) 참조). 이러한 데이터는 중요하지 않은 공백, 특성 순서, 네임스페이스 접두사 및 XML 선언과 같은 정보가 유지되지 않기 때문에 텍스트 XML의 정확한 복사본이 아닐 수 있습니다.
    형식 있는 XML 데이터 형식(즉, XML 스키마에 바인딩된 XML 데이터 형식)의 경우 Infoset에 유형 정보를 추가하는 PSVI(스키마 이후 유효성 검사) Infoset의 유형 관련 정보는 내부 표현으로 인코딩됩니다. 이러한 방식은 구문 분석 속도를 크게 향상시킵니다. 자세한 내용은 http://www.w3.org/TR/xmlschema-1 (영문) 및 http://www.w3.org/TR/xmlschema-2 (영문) 의 W3C XML 스키마 사양과 http://www.w3.org/TR/2005/WD-xpath-datamodel-20050211 (영문)의 XQuery 1.0 및 XPath 2.0 데이터 모델 초안을 참조하십시오.

  • XML과 관계형 저장소 간의 매핑:
    주석 처리된 스키마(AXSD)를 사용할 때 XML은 하나 이상의 테이블에 있는 열로 분해되어 관계형 수준에서 데이터의 정확도가 보존됩니다. 이 때 계층 구조는 보존되고 요소 간 순서는 무시됩니다. 스키마는 재귀적일 수 없습니다.

  • 큰 개체 저장소([n]varchar(max) 및 varbinary(max)):
    데이터의 정확한 복사본이 저장됩니다. 이 방법은 법률 문서와 같은 특별한 목적의 응용 프로그램에 유용합니다. 대부분의 응용 프로그램에는 정확한 복사본이 필요하지 않으며 XML 내용으로도 충분합니다(Infoset 정확도).

    일반적으로 이러한 접근 방법을 조합해서 사용해야 할 수 있습니다. 예를 들어 XML 데이터는 XML 데이터 형식 열에 저장하고 속성을 관계형 열로 승격해야 할 수 있습니다. 또는 매핑 기술을 사용하고 비재귀적인 부분을 비-XML 열에 저장하고 다른 재귀적 부분은 XML 데이터 형식 열에 저장할 수 있습니다.

    XML 기술 선택

    XML 기술의 선택(네이티브 XML과 XML 뷰)은 일반적으로 다음과 같은 요소에 달려 있습니다.
  •   저장소 옵션:
    XML 데이터가 큰 개체 저장소(예: 제품 설명서)에 더 적합하거나 관계형 열의 저장소(예: XML로 변환된 라인 항목)에 더 적합할 수 있습니다. 각 저장소 옵션은 문서 정확도를 유지하는 정도가 다릅니다.
  • 쿼리 기능:
    쿼리 특성과 XML 데이터를 쿼리하는 정도에 따라 적합한 옵션이 달라질 수 있습니다. XML 노드에 대한 조건문 평가와 같은 XML 데이터에 대한 세밀하게 조정된 쿼리는 두 가지 옵션의 여러 수준에 맞게 지원됩니다.

  • XML 데이터 인덱싱
    XML 쿼리 성능을 높이기 위해 XML 데이터를 인덱싱할 수 있습니다. 인덱싱 옵션은 저장소 옵션에 따라 다르며 자신의 작업을 최적화할 수 있는 적합한 옵션을 선택해야 합니다.

  • 데이터 수정 기능:
    일부 작업에는 세밀하게 조정된 XML 데이터 수정 기능(예: 문서 내에 새 섹션 추가)이 필요하지만 다른 작업(예: 웹 콘텐츠)은 그렇지 않습니다. 이 경우 응용 프로그램에 대한 데이터 수정 언어 지원이 중요할 수 있습니다.

  • 스키마 지원:
    XML 스키마 문서인지 여부에 관계 없이 스키마로 XML 데이터를 기술할 수 있습니다. 스키마 바인딩된 XML 지원은 XML 기술에 따라 달라집니다.

    물론 각 선택에 따라 성능 특성이 달라집니다.

    네이티브 XML 저장소

    서버에서 XML 데이터 형식 열에 XML 데이터를 저장할 수 있습니다. 이러한 방법은 다음 경우에 적합합니다.

  • 문서 순서 및 문서 구조를 유지하면서 서버에서 XML 데이터를 직관적으로 저장할 수 있는 방법이 필요합니다.
  • XML 데이터에 대한 스키마가 있거나 없을 수도 있습니다.
  • XML 데이터를 쿼리하고 수정해야 합니다.
  • 신속한 쿼리 처리를 위해 XML 데이터를 인덱싱합니다.
  • 응용 프로그램에 XML 데이터 및 XML 스키마 관리를 위한 시스템 카탈로그 뷰가 필요합니다.

    네이티브 XML 저장소는 구조 범위가 다양한 XML 문서나 관계형 구조로 매핑하기 어려운 복잡하거나 서로 다른 스키마를 기반으로 하는 XML 문서가 있는 경우에 유용합니다.

    예제: XML 데이터 형식을 사용하여 XML 데이터 모델링

    각 항목에 대한 별개의 장이 있고 각 장 안에 여러 섹션이 포함된 XML 형식의 제품 설명서를 가정해 보십시오. 섹션에는 하위 섹션이 포함될 수 있으므로
    은 재귀적 요소입니다. 제품 설명서에는 다양한 혼합된 내용, 다이어그램, 기술 자료 등이 포함되며 데이터는 반구조화된 상태입니다. 사용자는 자신이 원하는 항목을 문맥에 따라 검색할 수 있으며(예: "인덱싱" 장 내에서 "클러스터형 인덱스"에 대한 섹션 검색) 기술 수량을 쿼리할 수 있습니다.

    이러한 XML 문서에 적합한 저장소 모델은 XML 데이터 형식 열입니다. 이러한 형식은 XML 데이터의 Infoset 콘텐츠를 유지합니다. XML 열을 인덱싱하면 쿼리 성능이 향상됩니다.

    예제: XML 데이터의 정확한 복사본 유지

    정부 규제에 따라 XML 문서(예: 서명된 문서, 법률 문서 또는 주식 거래 주문)에 대한 정확한 텍스트 복사본을 유지해야 한다고 가정해 보십시오. 이 경우 문서를 [n]varchar(max) 열에 저장할 수 있습니다.

    쿼리를 수행하기 위해서는 데이터를 런타임에 XML 데이터 형식으로 변환하고 이에 대해 XQuery를 실행합니다. 문서가 큰 경우 런타임 변환은 특히 비용이 많이 듭니다. 쿼리를 자주 수행하는 경우 문서를 XML 데이터 형식 열로 중복해서 저장하고 인덱싱하면서도 [n]varchar(max) 열로부터 정확한 문서 복사본을 반환할 수 있습니다.

    XML 열은 [n]varchar(max) 열을 기준으로 계산된 열일 수 있습니다. 하지만 XML 계산된 열에는 XML 인덱스를 만들 수 없으며 [n]varchar(max) 또는 varbinary(max) 열에도 XML 인덱스를 작성할 수 없습니다.

    XML 뷰 기술

    XML 스키마와 데이터베이스의 테이블 간 매핑을 정의하여 영구적 데이터에 대한 "XML 뷰"를 만듭니다. XML 대량 로드 작업에서는 XML 뷰를 사용하여 기본 테이블을 채울 수 있습니다. XPath 1.0을 사용하여 XML 뷰를 쿼리할 수 있습니다. 이 쿼리는 테이블에 대한 SQL 쿼리로 변환됩니다. 비슷하게 업데이트도 이러한 테이블에 전파됩니다.

    이러한 기술은 다음과 같은 경우에 유용합니다

  • 기존 관계형 데이터에 대해 XML 뷰를 사용하는 XML 중심 프로그래밍 모델이 필요합니다.
  • 외부 파트너가 제공한 XML 데이터에 대한 스키마(XSD, XDR)가 있습니다.
  • 데이터 순서가 중요하지 않고, 쿼리 가능한 데이터가 재귀적이지 않거나, 최대 재귀 수준이 미리 알려져 있습니다.
  • XPath 1.0을 사용한 XML 뷰를 통해 데이터를 쿼리하고 수정해야 합니다.
  • XML 데이터를 대량 로드하고 이를 XML 뷰를 사용하여 기본 테이블로 분해해야 합니다.

    이러한 예로는 데이터 교환 및 웹 서비스를 위해 XML로 제공된 관계형 데이터와 고정 스키마가 포함된 XML 데이터가 있습니다. 자세한 내용은 http://msdn.microsoft.com/SQLXML (영문)을 참조하십시오.

    또한 FOR XML을 사용하여 서버에 저장된 관계형 데이터 및 XML 데이터로부터 XML을 게시할 수 있습니다. 자세한 내용은 이 문서의 FOR XML을 사용하여 행 집합으로부터 XML 생성을 참조하십시오.

    예제: 주석 처리된 XML 스키마(AXSD)를 사용하여 데이터 모델링

    XML로 조작하길 원하는 기존 관계형 데이터(예: 고객, 주문 및 라인 항목)가 있다고 가정해 보십시오. 관계형 데이터에 대해 AXSD를 사용하여 XML 뷰를 정의합니다. 이 XML 뷰를 사용하면 XML 데이터를 테이블에 대량 로드하고 XML 뷰를 사용하여 관계형 데이터를 쿼리 및 업데이트할 수 있습니다. 이 모델은 SQL 응용 프로그램을 방해 받지 않고 작동하면서 다른 응용 프로그램과 XML 태그가 포함된 데이터를 교환해야 할 경우에 유용합니다.

    혼합 모델

    관계형 및 XML 데이터 형식 열의 조합은 데이터 모델링에 적합한 경우가 많습니다. XML 데이터의 일부 값은 관계형 열에 저장하고 남은 값이나 전체 XML 값은 XML 열에 저장할 수 있습니다. 이렇게 하면 관계형 열에 생성된 인덱스를 완전히 제어하는 등의 더 나은 성능과 잠금 특성을 얻을 수 있습니다. 하지만 데이터 저장소 관리에 대한 책임이 늘어납니다.

    관계형 열에 저장되는 값은 작업에 따라 달라집니다. 예를 들어 경로 식 /Customer/@CustId를 기준으로 전체 XML 값을 검색하는 경우 CustId 특성의 값을 관계형 열로 승격하고 이를 인덱싱하면 더욱 빠른 쿼리 성능을 얻을 수 있습니다. 하지만 XML 데이터가 포괄적이고 비중복적으로 관계형 열에 분산되어 있는 경우 재조합 비용이 매우 커질 수 있습니다.

    구조화 수준이 높은 XML 데이터(예: 테이블 내용이 XML로 변환되어 있는 경우)의 경우 XML 뷰 기술을 사용하여 모든 값을 관계형 열로 매핑할 수 있습니다.

    XML 데이터 형식을 사용하여 데이터 모델링

    이 섹션에서는 네이티브 XML 저장소에 대한 데이터 모델링 항목에 대해 다룹니다. 여기에는 XML 데이터 인덱싱, 속성 승격 및 형식 있는 XML 데이터 형식이 포함됩니다.

    동일 테이블 또는 다른 테이블

    XML 데이터 형식 열을 다른 관계형 열이 포함된 테이블이나 기본 테이블에 대한 외래 키 관계에 있는 별개의 테이블에 만들 수 있습니다.

    다음 조건 중 하나에 해당하는 경우 동일 테이블에 XML 데이터 형식 열을 만듭니다.

  • 응용 프로그램이 XML 열에서 데이터 검색을 수행하고 XML 열에 대한 XML 인덱스는 필요하지 않습니다.
  • XML 데이터 형식 열에 XML 인덱스를 작성해야 하고 기본 테이블의 기본 키가 해당 클러스터링 키와 동일합니다. 자세한 내용은 XML 데이터 형식 열 인덱싱의 섹션을 참조하십시오 다음 조건에 해당하는 경우 별개의 테이블에 XML 데이터 형식 열을 만듭니다.

  • XML 데이터 형식 열에 XML 인덱스를 작성해야 하지만 기본 테이블의 기본 키가 해당 클러스터링 키와 동일하지 않거나 기본 테이블에 기본 키가 없거나 기본 테이블이 힙(즉, 클러스터링 키가 없음)입니다. 이 경우는 기본 테이블이 이미 있는 경우에 해당할 수 있습니다.
  • 행 내부 또는 행 외부에 저장되는지 여부에 관계없이 공간을 차지하는 테이블에 있는 XML 열로 인해 테이블 스캔이 느려지지 않아야 합니다.

    XML 데이터의 세분성

    XML 열에 저장된 XML 데이터의 세분성은 잠금 및 업데이트 특성에 중요한 요소입니다. SQL Server는 XML 데이터 및 비-XML 데이터에 대해 같은 잠금 메커니즘을 사용합니다. 따라서 행 수준의 잠금을 사용하면 해당 행에 있는 모든 XML 인스턴스가 잠깁니다. 세분성이 큰 경우 큰 XML 인스턴스를 업데이트를 위해 잠글 경우 다중 사용자 시나리오에서 처리량이 줄어듭니다. 고급 업데이트 시나리오에서 동시성을 향상시키기 위해서는 XML 데이터를 하나 이상의 테이블에서 관계형 열로 분해할 수 있습니다. 이렇게 분산 수준이 높은 경우 개체 캡슐화 및 XML 데이터의 구조가 손실될 가능성이 있으며 재조합 비용이 높아집니다.

    XML 인스턴스에 대한 업데이트는 즉각적이고 증분적으로 수행됩니다. 즉, 일반적으로 전체 XML 인스턴스를 바꾸는 경우가 거의 없습니다. 따라서 단일 특성 값의 업데이트를 XML 인스턴스의 크기에 관계없이 효율적으로 처리할 수 있습니다.

    데이터 모델링 요구 사항 및 잠금 특성 간의 균형은 훌륭한 디자인을 위한 중요한 요소입니다.

    형식 없는, 형식 있는, 제한된 XML 데이터 형식

    SQL Server 2005 XML 데이터 형식은 ISO SQL-2003 표준 XML 데이터 형식을 구현합니다. 따라서 올바른 형식의 XML 1.0 문서 뿐만 아니라 텍스트 노드와 임의 개수의 형식 없는 XML 열의 최상위 요소가 포함된 XML 콘텐츠 조각도 저장할 수 있습니다. 시스템은 데이터에 대한 올바른 형식을 검사하며, 열이 XML 스키마에 바인딩될 필요가 없고, 넓은 의미에서 올바른 형식이 아닌 데이터는 거부합니다. 이러한 경우는 형식 없는 XML 변수 및 매개 변수에 대해서도 적용됩니다.

    XML 데이터를 기술하는 XML 스키마가 있는 경우 이 스키마를 XML 열과 연결하여 형식 있는 XML을 만들 수 있습니다. XML 스키마는 데이터 유효성을 검사하고, 형식 없는 XML 이외의 데이터 수정 문과 쿼리를 컴파일 하는 동안 보다 정확한 유형 검사를 수행하고, 저장소 및 쿼리 처리를 최적화하는 데 사용됩니다.

    다음 조건에 해당하는 경우 형식 없는 XML 데이터 형식을 사용합니다.

  • XML 데이터에 대한 스키마가 없습니다.
  • 스키마는 있지만 서버에서 데이터의 유효성을 검사할 필요가 없습니다. 이러한 경우는 응용 프로그램이 데이터를 서버에 저장하기 전에 클라이언트측 유효성 검사를 수행하거나, 스키마에 유효하지 않은 XML 데이터를 일시적으로 저장하거나, 서버에서 지원되지 않는 XML 스키마 기능(예:key/keyref)을 사용하는 경우에 해당합니다.

    다음 조건에 해당하는 경우 형식 있는 XML 데이터 형식을 사용합니다.

  • XML 데이터에 대한 스키마가 있고 서버에서 XML 스키마에 따라 XML 데이터의 유효성을 검사해야 합니다.
  • 유형 정보에 따라 저장소와 쿼리 최적화를 활용합니다.
  • 정적 유형 오류와 같이 쿼리 컴파일 중에 유형 정보를 활용합니다.

    형식 있는 XML 열, 매개 변수 및 변수는 선언 시에 플래그(각각 DOCUMENT 또는 CONTENT)로 지정해야 하는 XML 문서 또는 콘텐츠를 저장할 수 있습니다. 또한 하나 이상의 XML 스키마를 제공해야 합니다. 각 XML 인스턴스에 정확히 하나의 최상위 요소가 있는 경우 DOCUMENT를 지정하고 그렇지 않으면 CONTENT를 사용하십시오. 쿼리 컴파일러는 쿼리 컴파일 중에 유형 검사에 DOCUMENT 플래그를 사용하여 단일 최상위 요소를 유추합니다.

    XML 열 형식화 외에도 형식 있는 또는 형식 없는 XML 데이터 형식 열에 관계형(열 또는 행) 제약 조건을 사용할 수 있습니다. 다음 조건에 해당하는 경우 제약 조건을 사용합니다.

  • XML 스키마로 비즈니스 규칙을 표현할 수 없습니다. 예를 들어 꽃집의 위치로부터 80km 이내에 있어야 하는 꽃집의 배달지는 XML 열에 대한 제약 조건으로 작성될 수 있습니다. 이 제약 조건에는 스칼라(테이블 값에 반대됨) 사용자 정의 함수 내의 XML 데이터 형식 메서드가 포함됩니다.
  • 이러한 제약 조건에는 테이블에 있는 다른 XML 또는 비-XML 열이 포함됩니다. 이에 대한 예로는 XML 인스턴스에 있는 고객 ID(/Customer/@CustId)를 관계형 CustomerID 열의 값과 일치하도록 강제로 적용하는 경우를 들 수 있습니다.

    DTD(문서 유형 정의)

    XML 데이터 형식 열, 변수 및 매개 변수는 DTD가 아닌 XML 스키마를 사용하여 형식화할 수 있습니다. DTD는 타사 도구를 사용하여 XML 스키마 문서로 변환할 수 있으며 XML 스키마를 데이터베이스에 로드할 수 있습니다.

    형식 없는 XML 인스턴스와 형식 있는 XML 인스턴스에 대해 인라인 DTD를 사용하여 기본값을 제공하고 엔터티 참조를 해당 확장 형식으로 교체할 수 있습니다.

    XML 데이터의 내부 저장소

    사용자가 제공한 XML 데이터는 내부적으로 이진 형식으로 저장되며 XML 데이터의 텍스트 표현보다 신속하게 구문 분석할 수 있습니다. 이러한 이진 형식은 일반적인 경우 약간의 압축을 제공하며 인스턴스당 2GB로 제한됩니다. 압축의 정도는 반복되는 태그의 길이 및 수와 XML 데이터에 있는 값의 유형에 따라 달라집니다. 다음 예제에서는 저장된 XML 데이터의 크기를 계산하는 방법을 보여 줍니다.

    예제: 저장된 XML 크기 계산

    여기에서는 이 문서에 있는 대부분의 예제에 사용된 형식 없는 XML 열이 있는 테이블 문서(pk INT PRIMARY KEY, xCol XML)가 사용되며 이러한 문서는 직관적인 방식으로 형식화된 XML로 확장될 수 있습니다(형식화된 XML 사용에 대한 자세한 내용은 SQL Server 2005 온라인 설명서 참조).

    CREATE TABLE docs (pk INT PRIMARY KEY, xCol XML)

    이해를 돕기 위해 XML 데이터 인스턴스에 대한 쿼리가 다음과 같이 설명됩니다.

    INSERT INTO docs VALUES (1,
    ''


    Michael
    Howard


    David
    LeBlanc

    39.99
    '')

    XML 열에서 XML 인스턴스의 저장 크기(바이트)는 DATALENGTH() 함수를 사용하여 찾을 수 있습니다.

    SELECT DATALENGTH (xCol)
    FROM docs

    행 내부 및 행 외부 저장소

    크기가 작은 XML 데이터 형식 인스턴스는 테이블의 일부 행 내에 저장됩니다. 디스크 페이지 내에 수용할 수 없는 보다 큰 값은 16바이트의 행 내부 포인터와 함께 행 외부에 저장됩니다.

    행 내부에 XML 값을 저장하면 레코드 밀도가 줄어들고 테이블의 비-XML 열에 대한 테이블 검색 속도가 느려집니다. 이러한 경우 시스템 저장 프로시저 sp_tableoption에서 "large value types out of row" 옵션을 지정하여 모든 큰 데이터 유형을 행 외부에 저장할 수 있습니다.

    XML 데이터 형식 열 인덱싱

    XML 데이터 형식 열에서 XML 인덱스를 만들 수 있습니다. 열에 있는 XML 인스턴스에 대한 모든 태그, 값 및 경로가 인덱싱되며 쿼리 성능이 향상됩니다. 다음과 같은 경우 XML 인덱스를 사용하면 응용 프로그램에 도움이 됩니다.

  • 작업에서 XML 열에 대한 쿼리가 일반적으로 사용됩니다. 데이터 수정 중의 XML 인덱스 유지 관리 비용을 고려해야 합니다.
  • XML 값이 비교적 크고 검색된 부분은 비교적 작습니다. 인덱스를 만들면 런타임시 전체 데이터의 구문 분석을 방지하고 효율적인 쿼리 처리를 위해 인덱스 조회 기능을 활용할 수 있습니다.

    XML 열에서 첫 번째 인덱스는 "기본 XML 인덱스"입니다. 이를 사용하여 XML 열에서 세 가지 유형의 보조 XML 인덱스를 만들면 아래에 설명된 대로 일반적인 쿼리 속도를 향상시킬 수 있습니다.

    기본 XML 인덱스

    이 인덱스는 XML 열의 XML 인스턴스 내에 있는 모든 태그, 값 및 경로를 인덱싱합니다. 기준 테이블(즉, XML 열이 있는 테이블)에는 테이블의 기본 키에 클러스터형 인덱스가 있어야 하며 기본 키는 기준 테이블의 행과 인덱스 행의 상관 관계를 지정하는 데 사용됩니다. 전체 XML 인스턴스는 XML 열로부터 검색됩니다(예: SELECT *). 쿼리에는 기본 XML 인덱스가 사용되며, 이 인덱스를 사용하여 스칼라 값 또는 XML 하위 트리를 반환합니다.

    예제: 기본 XML 인덱스 만들기

    다음 문에서는 테이블 문서의 XML 열 xCol에 idx_xCol이라는 기본 XML 인덱스를 만듭니다.

    CREATE PRIMARY XML INDEX idx_xCol on docs (xCol)

    보조 XML 인덱스


    기본 XML 인덱스를 만든 다음에는 보조 XML 인덱스를 만들어서 작업 내 여러 종류의 쿼리 속도를 높일 수 있습니다. 보조 XML 인덱스의 세 가지 유형인 PATH, PROPERTY 및 VALUE를 사용하면 각각 경로 기반 쿼리, 사용자 지정 속성 관리 시나리오 및 값 기반 쿼리에 큰 이점으로 작용합니다.

    PATH 인덱스는 열의 모든 XML 인스턴스에 대해 문서 순서에 있는 각 XML 노드의 경로 및 값 쌍에 B+-트리를 작성합니다. PROPERTY 인덱스는 각 XML 인스턴스 내의 PK, 경로 및 값 쌍에 클러스터된 B+-트리를 만들고, 여기서 PK는 기준 테이블의 기본 키입니다. 마지막으로 VALUE 인덱스는 열의 모든 XML 인스턴스에 대해 문서 순서에 있는 각 노드의 경로 및 값 쌍에 B+-트리를 만듭니다.

    다음은 이러한 인덱스를 하나 이상 만들기 위한 일부 지침입니다.


  • 작업에서 주로 XML 열에 대한 경로 식이 사용되는 경우 PATH 보조 XML 인덱스를 사용하면 작업 속도가 높아질 수 있습니다. 가장 일반적인 경우는 Transact-SQL의 WHERE 절에 있는 XML 열의 exist() 메서드를 사용하는 것입니다.
  • 작업에서 경로 식을 사용하여 개별 XML 인스턴스로부터 여러 값을 검색하는 경우 PROPERTY 인덱스의 각 XML 인스턴스 내에서 경로를 클러스터하는 것이 도움이 될 수 있습니다. 이 시나리오는 일반적으로 개체의 속성이 인출되고 해당 관계형 기본 키 값이 알려진 속성 모음 시나리오에서 발생합니다.
  • 작업이 XML 인스턴스 내의 값에 대한 쿼리를 포함하고 이러한 값이 포함된 요소 또는 특성 이름을 알 수 없는 경우 VALUE 인덱스를 만들 수 있습니다. 이 경우는 일반적으로 요소는 계층의 임의 수준에서 발생할 수 있고 검색 값(“Howard”)은 경로보다 선택적인 //author[last-name="Howard"]와 같은 하위 항목 축 조회에서 발생합니다. 또한 쿼리에서 “novel”이라는 값이 포함된 일부 특성의 요소를 조회하는 /book [@* = "novel"]과 같은 “와일드카드” 쿼리에서 발생합니다.

    예제: 경로 기반 조회

    아래 쿼리가 작업에서 일반적으로 사용된다고 가정해 보십시오.

    SELECT pk, xCol
    FROM docs
    WHERE xCol.exist (''/book[@genre = "security"]'') = 1

    경로 식 /book/@genre와 값 "security"는 PATH 인덱스의 키 필드에 해당합니다. 따라서 PATH 유형의 보조 XML 인덱스는 이 작업에 도움이 됩니다.

    CREATE XML INDEX idx_xCol_Path on docs (xCol)
    USING XML INDEX idx_xCol FOR PATH

    예제: 개체의 속성 인출

    테이블 문서의 각 행에서 책 저자의 이름을 검색하는 다음 쿼리를 보십시오.

    SELECT ref.value (''first-name'', ''nvarchar(64)''),
    ref.value (''last-name'', ''nvarchar(64)'')
    FROM docs CROSS APPLY xCol.nodes (''/book/author) R(ref)

    이 경우 속성 인덱스가 유용하고 다음과 같이 생성됩니다.

    CREATE XML INDEX idx_xCol_Property on docs (xCol)
    USING XML INDEX idx_xCol FOR PROPERTY

    예제: 값 기반 쿼리

    다음 쿼리에서 부분 경로는 //를 사용하여 지정되므로 ISBN 값 기반의 조회 시에는 VALUE 인덱스를 사용하는 것이 유용합니다.

    SELECT xCol
    FROM docs
    WHERE xCol.exist (''//book/@ISBN[. = "0-7356-1588-2"]'') = 1

    VALUE 인덱스는 다음과 같이 생성됩니다.

    CREATE XML INDEX idx_xCol_Value on docs (xCol)
    USING XML INDEX idx_xCol FOR VALUE

    여러 파일 그룹의 XML 인덱스

    XML 인덱스는 기준 테이블과 결합되어 XML 인덱스 행이 해당 기준 테이블 행과 동일한 파일 그룹 및 테이블 파티션에 저장됩니다. 이를 위해서는 XML 블롭에 대한 큰 파일 그룹과 결합된 해당 XML 인덱스가 필요할 수 있습니다. CREATE TABLE 문의 TEXTIMAGE_ON 사양은 지정된 파일 그룹에 XML 블롭을 저장하고 XML 인덱스 행은 계속 기준 테이블과 결합되며, 큰 XML 노드 값은 XML 블롭과 동일한 파일 그룹에 존재합니다. 이렇게 하면 개별 파일 그룹의 크기를 줄이고 데이터를 보다 편리하게 관리할 수 있습니다. 예를 들어 행에 있는 비-XML 데이터가 XML 데이터 크기에 비해 작은 경우 이 기술을 사용하면 저장소를 보다 균등하게 분산할 수 있습니다.

    XML 열의 전체 텍스트 인덱스

    XML 열에 전체 텍스트 인덱스를 만들 수 있습니다. 이렇게 하면 XML 태그를 무시하면서 XML 값의 콘텐츠를 인덱싱합니다. 특성 값은 태그의 일부로 간주되기 때문에 전체 텍스트 인덱싱되지 않으며 요소 태그는 토큰 경계로 사용됩니다. 일부 시나리오에서는 XML 인덱스 사용과 전체 텍스트 검색을 조합할 수 있습니다.

  • SQL 전체 텍스트 검색을 사용하여 필요한 XML 값을 필터링합니다.
  • XML 열에서 XML 인덱스를 사용하는 XML 인스턴스를 쿼리합니다.

    예제: 전체 텍스트 검색과 XML 쿼리 조합

    XML 열에 전체 텍스트 인덱스를 만드는 단계는 다른 SQL 유형 열에 전체 텍스트 인덱스를 만드는 단계와 동일합니다. DDL 문은 다음과 같으며, 여기서 PK__docs__023D5A04는 테이블의 단일 열 기본 키 인덱스입니다.

    CREATE FULLTEXT CATALOG ft AS DEFAULT
    CREATE FULLTEXT INDEX ON dbo.docs (xCol) KEY INDEX PK__docs__023D5A04

    XML 열에서 전체 텍스트 인덱스를 만든 후 다음 쿼리는 XML 인스턴스에 "Secure"라는 단어가 책 제목에 포함되어 있는지 검사합니다.

    SELECT *
    FROM docs
    WHERE CONTAINS(xCol,''Secure'')
    AND xCol.exist(''/book/title/text()[contains(.,"Secure")]'') =1

    CONTAINS() 메서드는 전체 텍스트 인덱스를 사용하여 문서 내 어느 곳에든 "Secure"라는 단어가 포함된 XML 인스턴스를 분리합니다. exist() 절은 "Secure"라는 단어가 책 제목에 있는지 보장합니다.

    CONTAINS() 및 XQuery contains()를 사용한 전체 텍스트 검색은 서로 다른 의미를 갖고 있습니다. 후자는 하위 문자열 일치 검사이며, 전자는 형태소 분석을 사용한 토큰 일치 검사입니다. 따라서 제목에서 "run"이라는 문자열을 검색하는 경우 "run", "runs" 및 "running"은 모두 전체 텍스트 CONTAINS()와 XQuery contains()에 만족하기 때문에 이 검색에 포함됩니다. 하지만 위 쿼리에서 제목에 있는 "UnSecured"라는 단어는 검색되지 않습니다(전체 텍스트 CONTAINS()는 실패하지만 XQuery contains()에는 만족). 또한 전체 텍스트 검색은 단어의 형태소 분석을 사용하지만 XQuery contains()는 문자열 검색을 수행합니다. 일반적으로 완전한 하위 문자열 검색의 경우 전체 텍스트 CONTAINS() 절을 제거해야 합니다. 이러한 차이점은 다음 예제에서 설명합니다.

    예제: 형태소 분석을 사용한 XML 값의 전체 텍스트 검색

    예제: XML 쿼리와 전체 텍스트 검색 조합에서의 XQuery contains() 검사는 일반적으로 제거할 수 없습니다. 다음 쿼리를 보십시오.

    SELECT *
    FROM docs
    WHERE CONTAINS(xCol,''run'')

    문서에서 "ran"이라는 단어는 형태소 분석 덕분에 검색 조건과 일치합니다. 또한 검색 컨텍스트는 XQuery를 사용하여 검사되지 않습니다.

    AXSD를 사용하여 전체 텍스트 인덱싱된 관계형 열로 XML을 분산할 경우 XML 뷰에 대한 XPath 쿼리는 기본 테이블에서 전체 텍스트 검색을 수행하지 않습니다.

    XML 열에 대한 전체 텍스트 인덱스에서 여러 언어 지원

    전체 열에 대해 하나의 단어 분리기만 포함할 수 있는 nvarchar 또는 varchar 열과 달리 XML 데이터 형식 열은 XML 요소에 대한 xml:lang 특성을 사용하여 여러 언어의 단어 분리기를 지원합니다. 지정된 언어의 단어 분리기는 해당 요소의 콘텐츠에서 사용됩니다. 하위 요소는 xml:lang 특성에 다른 언어를 지정할 수 있습니다. 따라서 여러 XML 인스턴스 뿐만 아니라 단일 XML 인스턴스에도 여러 단어 분리기가 포함될 수 있습니다.

    이를 통해 여러 가지 흥미 있는 가능성이 도출됩니다. 예를 들어 Word 2003 문서에는 여러 언어로 된 섹션이 포함될 수 있습니다. WordML XML 표현의 문서를 XML 데이터 형식 열로 저장할 수 있으며 전체 텍스트 인덱싱에 적합한 언어 단어 분리기를 사용할 수 있습니다.

    전체 텍스트 쿼리는 다음 예제에서와 같이 사용할 언어를 지정할 수 있습니다.

    예제: 전체 텍스트 검색의 언어 지정

    다음 쿼리는 전체 텍스트 검색이 독일어로 수행되도록 지정합니다.

    SELECT * FROM docs
    WHERE contains (xCol, ''Visionen'', LANGUAGE ''German'')

    속성 승격

    쿼리가 주로 작은 수의 요소 및 특성 값에 대해 만들어진 경우(예: 고객 ID로 고객 찾기, 즉 /Customer/@CustId 값이 지정된 경우) 이러한 값을 관계형 열로 승격할 수 있습니다. 이러한 방식은 전체 XML 인스턴스가 검색되는 동안 XML의 작은 부분에 대해서 쿼리가 실행되는 경우에 유용합니다. XML 열에 대한 XML 인덱스 생성까지는 필요하지 않으며 대신 승격된 열을 인덱싱할 수 있습니다. 쿼리는 승격된 열을 사용하도록 작성되어야 합니다. 즉, 쿼리 최적화 프로그램에서 XML 열의 쿼리를 승격된 열로 다시 대상화하지 않습니다.

    승격된 열은 같은 테이블이나 별개의 테이블의 계산된 열이거나 테이블에 있는 사용자 유지 관리 열일 수 있습니다. 이러한 방식은 단일 값(즉, 단일 값 속성)이 각 XML 인스턴스로부터 승격되는 경우에 적합합니다. 하지만 다중 값 속성의 경우 아래에 설명된 대로 속성에 대한 별개의 테이블을 만들어야 합니다.

    XML 데이터 형식 기반 계산된 열

    XML 데이터 형식 메서드를 호출하는 UDF(사용자 정의 함수)를 사용하여 계산된 열을 만들 수 있습니다. 계산된 열 유형은 XML을 포함한 임의의 SQL 유형일 수 있습니다. 이에 대해서는 다음 예제에서 설명합니다.

    예제: XML 데이터 형식 메서드 기반 계산된 열

    책의 ISBN에 대한 사용자 정의 함수를 만듭니다

    CREATE FUNCTION udf_get_book_ISBN (@xData xml)
    RETURNS varchar(20)
    BEGIN
    DECLARE @ISBN varchar(20)
    SELECT @ISBN = @xData.value(''/book[1]/@ISBN'', ''varchar(20)'')
    RETURN @ISBN
    END

    ISBN에 대한 테이블에 계산된 열을 추가합니다.

    ALTER TABLE docs
    ADD ISBN AS dbo.udf_get_book_ISBN(xCol)

    계산된 열은 일반적인 방식으로 인덱싱할 수 있습니다.

    예제: XML 데이터 형식 메서드 기반 계산된 열에 대한 쿼리

    ISBN이 0-7356-1588-2인 을 가져오기 위해 XML 열에 대한 다음 쿼리

    SELECT pk, xCol
    FROM docs
    WHERE xCol.exist (''/book[@ISBN = "0-7356-1588-2"]'') = 1

    이는 다음과 같이 계산된 열을 사용하도록 다시 작성될 수 있습니다.

    SELECT pk, xCol
    FROM docs
    WHERE ISBN = ''0-7356-1588-2''

    사용자 정의 함수를 만들어서 XML 데이터 형식을 반환하고 UDF를 사용하여 계산된 열을 만들 수 있습니다. 하지만 XML 계산된 열에 대해서는 XML 인덱스를 만들 수 없습니다.

    속성 테이블 만들기

    XML 데이터로부터 일부 다중 값 속성을 하나 이상의 테이블로 승격시키고, 해당 테이블에서 인덱스를 만들고, 이를 사용하도록 쿼리를 다시 대상화할 수 있습니다. 일반적인 시나리오는 적은 수의 속성으로 대부분의 쿼리 작업을 포괄하는 것입니다. 다음과 같이 할 수 있습니다.
    • 다중 값 속성을 유지하는 하나 이상의 테이블을 만듭니다. 테이블 당 하나의 속성을 저장하고 기준 테이블과의 백 조인을 위해 속성 테이블에서 기준 테이블의 기본 키를 복제하는 것이 편리합니다.
    • 속성의 상대적 순서를 유지하려면 상대적 순서에 대한 별개의 열을 사용해야 합니다.
    • 속성 테이블을 유지하기 위해 XML 열에 트리거를 만듭니다. 트리거 내에서 다음 중 하나를 수행하십시오.
      . nodes() 및 value()와 같은 XML 데이터 형식 메서드를 사용하여 속성 테이블의 행을 삽입하고 삭제합니다. nodes() 메서드에 대한 자세한 내용은 Value(), nodes() 및 OpenXML() 섹션을 참조하십시오.
      . CLR에서 스트리밍 테이블 값 함수를 만들어서 속성 테이블의 행을 삽입하고 삭제합니다.

    • 속성 테이블에 대한 SQL 액세스와 기준 테이블의 XML 열에 대한 XML 액세스를 위한 쿼리를 작성하고 기본 키를 사용하는 테이블 간 조인을 포함시킵니다.

    예제: 속성 테이블 만들기

    저자의 이름을 승격시키는 경우를 가정해 보십시오. 책에는 한 명 이상의 저자가 있으므로 이름은 다중 값 속성입니다. 각 이름은 속성 테이블의 별개의 행에 저장됩니다. 기준 테이블의 기본 키는 백 조인을 위해 속성 테이블에 중복됩니다.

    CREATE TABLE tblPropAuthor (propPK int, propAuthor varchar(max))

    예제: XML 인스턴스로부터 행 집합을 생성하기 위해 사용자 정의 함수 만들기

    아래의 테이블 값 사용자 정의 함수 udf_XML2Table은 기본 키 값과 XML 인스턴스를 받아들입니다. 이 함수는 요소의 모든 저자에 대한 이름을 검색하고 기본 키 및 이름 쌍이 포함된 행 집합을 반환합니다. 래퍼 사용자 정의 함수를 사용하지 않고 XML 데이터 형식 메서드 기반의 계산된 열을 인덱싱하는 방식은 SQL Server 2005에서 지원되지 않습니다.

    CREATE FUNCTION udf_XML2Table (@pk int, @xCol xml)
    RETURNS table WITH SCHEMABINDING
    AS RETURN(
    select @pk as PropPK, nref.value(''.'', ''varchar(max)'') as propAuthor
    from @xCol.nodes(''/book/author/first-name'') R(nref)
    )

    예제: 속성 테이블을 채우기 위해 트리거 만들기

    Insert 트리거: 속성 테이블에 행을 삽입합니다.

    CREATE TRIGGER trg_docs_INS on docs FOR INSERT
    AS
    BEGIN
    insert into tblPropAuthor
    select p.*
    from inserted as I CROSS APPLY
    dbo.udf_XML2Table(I.pk, I.xCol) as P
    END

    Delete 트리거: 삭제되는 행의 기본 키 값에 따라 속성 테이블에서 행을 삭제합니다.

    create trigger trg_docs_DEL on docs for delete
    as
    begin
    delete tblPropAuthor where propPK IN
    (select p.PropPK
    from deleted as D CROSS APPLY
    dbo.udf_XML2Table(D.pk, D.xCol) as P
    )
    end

    Update 트리거: 업데이트된 XML 인스턴스에 따라 속성 테이블에서 기존 행을 삭제하고 속성 테이블에 새 행을 삽입합니다.

    create trigger trg_docs_UPD
    on docs
    for update
    as
    if update(xCol) or update(pk)
    begin
    delete tblPropAuthor where propPK IN
    (select p.PropPK
    from deleted as D CROSS APPLY
    dbo.udf_XML2Table(D.pk, D.xCol) as P
    )
    insert into tblPropAuthor
    select p.*
    from inserted as I CROSS APPLY
    dbo.udf_XML2Table(i.pk, i.xCol) as P
    end

    예제: 저자의 이름이 "David"인 XML 인스턴스 찾기

    쿼리를 XML 열에 표현할 수 있습니다. 또는 아래와 같이 "David"라는 이름을 속성 테이블에서 검색하고 기준 테이블로 백 조인을 수행하여 XML 인스턴스를 반환할 수 있습니다.

    SELECT xCol
    FROM docs JOIN tblPropAuthor ON docs.pk = tblPropAuthor.propPK
    WHERE tblPropAuthor.propAuthor = ''David''

    예제: CLR 스트리밍 테이블 값 함수를 사용한 솔루션

    이 솔루션은 다음과 같은 단계로 구성됩니다.

    1. IEnumerator를 구현하고 XML 인스턴스에 간단한 경로 식을 사용하여 스트리밍 테이블 값 출력을 생성하기 위한 InitMethod 메서드가 포함된 CLR 클래스 CXmlStreamingTVF를 정의합니다.

    2. 어셈블리와 Transact-SQL UDF(사용자 정의 함수)를 만들어서 CLR 클래스를 호출합니다.

    3. UDF를 사용하여 삽입, 업데이트 및 삭제 트리거를 정의하여 속성 테이블을 유지 관리합니다.

    먼저 아래와 같이 스트리밍 CLR 함수를 만듭니다. XML 데이터 형식은 ADO.NET에서 관리 클래스 SqlXml로 제공되며 XmlReader를 반환하는 메서드 CreateReader()를 지원합니다.

    using System;
    using System.Xml;
    using System.IO;
    using System.Data;
    using System.Data.Sql;
    using System.Data.SqlClient;
    using System.Data.SqlTypes;
    using Microsoft.SqlServer.Server;
    using System.Collections;

    public class CXmlStreamingTVF : IEnumerator {
    private XmlReader m_reader;
    private SqlXml m_doc;
    private string m_name;
    private string[] m_path;
    private int m_pathLoc;

    public CXmlStreamingTVF (SqlXml doc, string simplePath) {
    m_doc = doc;
    m_reader = m_doc.CreateReader();
    m_path = simplePath.Split(new char[]{''/''});
    m_pathLoc = m_path.Length-1;
    }

    //Three IEnumerator methods.
    //Custom code for Navigating the document for a simple path.
    public bool MoveNext () {
    bool new_row = false;
    while (!new_row && !m_reader.EOF) {
    m_reader.Read();
    if (m_reader.LocalName==m_path[m_pathLoc] &&
    m_pathLoc==m_path.Length-1 &&
    m_reader.NodeType==XmlNodeType.Element) {
    m_name = m_reader.ReadString();
    new_row = true;
    }
    else if (m_reader.LocalName==m_path[m_pathLoc] &&
    m_reader.NodeType==XmlNodeType.Element &&
    m_reader.IsEmptyElement==false) {
    if (m_pathLoc==1 && m_reader.Depth!=0)
    continue;
    m_pathLoc++;
    }
    else if (m_pathLoc!=1 &&
    m_reader.LocalName==m_path[m_pathLoc-1] &&
    m_reader.NodeType==XmlNodeType.EndElement) {
    m_pathLoc--;
    }
    }
    return new_row;
    }

    public object Current { get { return this; } }
    public void Reset () {
    m_reader.Close();
    m_reader = m_doc.CreateReader();
    }

    [SqlFunctionAttribute (FillRowMethodName="CLROpenXml")]
    public static IEnumerator InitMethod (SqlXml doc, string simplePath)
    {
    return new CXmlStreamingTVF(doc, simplePath);
    }

    public static void CLROpenXml(Object obj, out string name) {
    CXmlStreamingTVF stream = (CXmlStreamingTVF) obj;
    name = stream.m_name;
    }
    }

    그런 다음 어셈블리 및 CLR 메서드 InitMethod()에 해당하는 Transact-SQL 사용자 정의 함수 SQL_streaming_xml_tvf를 만듭니다.

    CREATE ASSEMBLY CLRXML
    FROM ''C:\temp\StreamingTVF.dll''
    WITH PERMISSION_SET = SAFE

    CREATE FUNCTION SQL_streaming_xml_tvf (
    @xData XML, @xPath nvarchar(max))
    RETURNS table (FirstName nvarchar(max))
    AS
    EXTERNAL NAME [CLRXML].[CXmlStreamingTVF].[InitMethod]

    UDF는 행 집합 생성을 위해 테이블 값 함수 CLR_udf_XML2Table을 정의하는 데 사용됩니다.

    create function CLR_udf_XML2Table (@pk int, @xCol xml)
    returns @ret_Table table (FK int, FirstName varchar(max))
    with schemabinding
    as
    begin
    insert into @ret_Table
    select @pk, FirstName
    FROM SQL_streaming_xml_tvf (@xCol, ''/book/author/first-name'')
    return
    end

    마지막으로 CLR_udf_XML2Table replacing udf_XML2Table 함수로 "속성 테이블을 채우기 위한 트리거 만들기" 예제에서 표시된 대로 트리거를 정의합니다. 그러면 삽입 트리거가 다음과 같이 됩니다.

    create trigger CLR_trg_docs_INS on docs for insert
    as
    begin
    insert into tblPropAuthor
    select p.*
    from inserted as I CROSS APPLY
    dbo.CLR_udf_XML2Table(I.pk, I.xCol) as P
    end

    삭제 및 업데이트 트리거는 비-CLR 함수와 비슷하며 단순히 udf_XML2Table() 함수를 CLR_udf_XML2Table() 함수로 교체하면 얻을 수 있습니다.

    이러한 두 대안의 장단점

    속성 테이블에 행을 생성, 삭제 및 수정하는 데 사용된 함수 udf_XML2Table()이 CPU 사용량이 높은 경우 CLR 기반 접근 방식이 일반적으로 더 빠릅니다. 여기에는 매우 복잡한 구조의 XML 데이터가 포함되어 XML 구문 분석의 계산 비용이 높습니다. udf_XML2Table() 함수의 비용이 낮은 경우에는 차이점이 줄어듭니다. 크기가 작은 XML과 간단한 경로 식의 경우 컨텍스트 변환 비용은 CLR 기반 솔루션에 더욱 나쁜 영향을 줄 수 있습니다.

    Transact-SQL 및 XQuery 기반 솔루션과는 달리 CLR 기반 솔루션의 경로 식은 하드 코딩됩니다. 이러한 방식은 경로 식이 미리 알려져 있는 경우 제대로 작동합니다. 그 외 다른 모든 경우에는 Transact-SQL 및 XQuery 기반 솔루션이 유일한 방법입니다.

    XML 스키마 컬렉션

    XML 스키마 컬렉션은 관계형 스키마 범위에 포함되는 메타데이터 엔터티이며 를 통해 관련되거나 관련되지 않은 하나 이상의 XML 스키마가 포함됩니다. XML 스키마 컬렉션 내의 개별 XML 스키마는 해당 대상 네임스페이스를 사용하여 식별됩니다.

    XML 스키마 컬렉션은 CREATE XML SCHEMA COLLECTION 구문을 사용하여 생성되며 하나 이상의 XML 스키마를 제공합니다. 기존 스키마에 보다 많은 XML 스키마 구성 요소를 추가할 수 있으며 ALTER XML SCHEMA COLLECTION 구문을 사용하여 XML 스키마 컬렉션에 더 많은 스키마를 추가할 수 있습니다. XML 스키마 컬렉션은 SQL Server 2005의 보안 모델을 사용하여 모든 SQL 개체와 같은 방식으로 보안됩니다.

    다중 유형 열

    XML 스키마 컬렉션 C는 다중 XML 스키마에 따라 XML 열 xCol을 형식화합니다. 또한 DOCUMENT 또는 CONTENT 플래그는 XML 트리 또는 조각이 각각 xCol 열에 저장될 수 있는지 여부를 지정합니다.

    DOCUMENT의 경우 각 XML 인스턴스는 인스턴스의 유효성을 검사하고 형식 있는 해당 최상위 요소에 대한 대상 네임스페이스를 인스턴스에서 지정합니다. 반대로 CONTENT의 경우에는 각 최상위 요소가 대상 네임스페이스 중 하나를 C에서 지정할 수 있습니다. XML 인스턴스는 인스턴스에서 발생하는 모든 대상 네임스페이스에 따라 유효성이 검사되고 형식화됩니다.

    스키마 발전

    XML 스키마 컬렉션은 XML 열, 변수 및 매개 변수를 형식화하는 데 사용됩니다. XML 스키마 컬렉션은 XML 스키마 발전을 위한 메커니즘을 제공합니다. 대상 네임스페이스가 BOOK-V1인 XML 스키마를 XML 스키마 컬렉션 C에 추가한다고 가정해 보십시오. C를 사용하여 형식 있는 XML 열 xCol은 BOOK-V1 스키마를 준수하는 XML 데이터를 저장할 수 있습니다.

    응용 프로그램에서 복잡한 유형의 정의 및 최상위 요소 선언과 같은 새로운 스키마 구성 요소로 XML 스키마를 확장한다고 가정해 보십시오. 이러한 새 스키마 구성 요소를 BOOK-V1 스키마에 추가할 수 있으며 이 구성 요소에는 xCol 열에 있는 기존 XML에 대한 유효성 검사를 다시 수행할 필요가 없습니다.

    나중에 응용 프로그램에서 대상 네임스페이스 BOOK-V2를 선택하도록 XML 스키마의 새 버전을 제공한다고 가정해 보십시오. 이 XML 스키마를 C에 추가할 수 있습니다. XML 열은 BOOK-V1 및 BOOK-V2의 인스턴스를 모두 저장할 수 있으며 이러한 네임스페이스를 준수하는 XML 인스턴스에 있는 쿼리 및 데이터 수정을 실행합니다.

    와일드카드 섹션에 허용되지 않는 Lax 유효성 검사

    XML 스키마 프로세서는 와일드 카드 섹션(xs:any 및 xs:anyAttribute) 및 xs:anyType에서 lax 유효성 검사를 지원하지 않습니다. 와일드카드 섹션의 경우 XML 스키마는 processContents = "strict" 또는 processContents = "skip"을 지정할 수 있습니다. xs:anyType의 경우 엄격한 유효성 검사만 지원됩니다.

    엄격한 유효성 검사는 이러한 스키마 구성 요소를 인스턴스화하는 XML 노드와 관련된 보다 정확한 유형 정보가 유효성 검사 중에 알려지고 쿼리 컴파일 중에 사용되도록 보장합니다. 건너뛰기 의미는 형식화 정보가 손실되고 해당 노드는 형식 없는 상태로 취급됩니다(요소의 경우는 xdt:untyped 및 특성의 경우는 xdt:untypedAtomic).

    xs:anyType에 대한 건너뛰기 의미가 필요한 경우 아래와 같이 xs:any 및 processContents = "skip"이 포함된 xs:anyAttribute가 사용되는 새로운 복합 유형을 사용하십시오.






    xs:datetime, xs:date 및 xs:time 사용

    xs:datetime, xs:data 및 xs:time 유형의 값은 ISO 8601 형식으로 지정되어야 하며 표준 시간대가 포함되어야 합니다. 그렇지 않으면 이러한 값에 대한 데이터 유효성 검사가 실패합니다. 따라서 2005-05-27T14:11:00.943Z는 xs:datetime 유형에 대한 올바른 값이지만 2005-05-27 14:11:00.943Z는 날짜 및 시간 구분자인 "T"가 없고, 2005-05-27T14:11:00.943은 표준 시간대가 없고, 2005-05-27 14:11:00.943은 시간 구분자와 표준 시간대가 없어서 올바른 값이 아닙니다. 이와 비슷하게 2005-05-27Z는 올바른 xs:date 값이지만 2005-05-27은 표준 시간대가 지정되지 않아서 올바른 값이 아닙니다.

    형식 없는 XML 데이터에는 응용 프로그램이 SQL 유형의 dateTime 또는 smallDateTime으로 변환하려는 날짜, 시간 및 날짜/시간 값이 포함될 수 있습니다. 이러한 날짜, 시간 및 날짜/시간 값은 ISO 8601 형식을 준수하지 않거나 표준 시간대를 포함하지 않을 수 있습니다. 이와 비슷하게 형식 있는 XML에는 xs:date, xs:time 및 xs:dateTime 이외의 유형의 값(예: xs:string)이 포함될 수 있습니다. 두 경우 모두 값을 먼저 [n]varchar로 변환한 후 다음 예제에서와 같이 SQL datetime 또는 smalldatetime으로 변환해야 합니다.

    예제: 형식 없는 XML에서 날짜/시간 값 추출

    다음 데이터로부터 CreationTime 특성의 값을 가져오기 위해

    declare @var xml
    select @var =
    ''
    LastExecutionTime="2005-05-19 14:11:00.943"
    CreationTime="2005-05-19 14:11:00.913"/>




    ''

    value() 메서드가 사용되어 이후에 SQL datetime 유형으로 캐스트된 nvarchar(64) 값을 검색합니다.

    select cast (@var.value(
    ''(/QueryExecutionStats /GeneralStats/@CreationTime)[1]'',
    ''nvarchar(max)'') AS datetime) as creation_time

    사용법

    XML 데이터 로드

    SQL Server 2000에서 SQL Server 2005로 XML 데이터 전송
    XML 데이터는 여러 가지 방법으로 SQL Server 2005로 전송할 수 있습니다. 여기에서는 이에 대한 일부 옵션을 다룹니다.
  • 데이터가 SQL Server 2000 데이터베이스의 [n]text 또는 이미지 열에 있는 경우 DTS 등을 사용하여 테이블을 SQL Server 2005 데이터베이스로 가져옵니다. 열 유형을 각각 [n]varchar(max) 또는 varbinary(max)로 바꾼 다음 ALTER TABLE 문을 사용하여 XML로 바꿉니다.
  • bcp out을 사용하여 SQL Server 2000의 데이터를 대량 복사하고 bcp in을 사용하여 SQL Server 2005 데이터베이스로 대량 삽입합니다.
  • SQL Server 2000 데이터베이스의 관계형 열에 데이터가 있는 경우 [n]text 열로 테이블을 새로 만들고 필요에 따라 행 식별자에 대한 기본 키 열을 만듭니다. 클라이언트측 프로그래밍을 사용하여 서버에서 FOR XML로 생성된 XML을 검색하고 이를 [n]text 열에 기록합니다. 그런 다음 위에 언급한 기술을 사용하여 데이터를 SQL Server 2005 데이터베이스로 전송합니다. SQL Server 2005 데이터베이스의 XML 열로 XML을 직접 기록하도록 선택할 수도 있습니다.

    예제: 열 유형을 XML로 변경


    테이블 R에 있는 [n]text, [n]varchar, varbinary 또는 XML 열 XYZ를 XML 스키마 컬렉션 bookCollection을 사용하여 형식 있는 XML로 바꾼다고 가정해 보십시오. 다음 문은 이러한 유형 변환을 수행합니다.

    ALTER TABLE R ALTER COLUMN XYZ XML (bookCollection)

    XML 스키마 컬렉션이 지정되지 않은 경우 대상은 형식 없는 XML입니다.


    텍스트 인코딩


    SQL Server 2005는 XML 데이터를 유니코드(UTF-16)로 저장합니다. 서버에서 검색된 XML 데이터는 UTF-16 인코딩으로 되고 데이터 검색 시 다른 인코딩이 필요한 경우 응용 프로그램에서 검색된 UTF-16 데이터에 대해 필요한 변환을 수행해야 합니다.

    문자열 유형을 XML 데이터 형식으로 변환할 경우 SQL Server 2005는 원본 문자열의 데이터 정렬에 대한 코드 페이지를 사용하여 인코딩을 결정합니다. XML 인코딩 정보가 XML 선언(예: <?xml version="1.0" encoding="windows-1256"?>)에 있는 "encoding" 특성을 사용하여 지정된 경우 인코딩은 문자열의 코드 페이지와 호환되어야 합니다. 문자열 데이터는 이러한 두 데이터 정렬이 호환되는 한 XML 파서에서 제대로 구문 분석될 수 있습니다. 그렇지 않으면 오류가 발생하거나 잘못된 데이터가 로드됩니다. 클라이언트 응용 프로그램이 XML 데이터 형식으로의 변환을 위해 서버에 문자열 값을 보낼 때에도 같은 동작이 발생합니다.

    일부 경우에는 여러 인코딩의 XML 데이터가 있거나 인코딩에 대한 사전 지식이 없을 수도 있습니다. 이러한 경우의 권장 방법은 XML 데이터를 이진 데이터 형식(예: varbinary(max))으로 제공하는 것입니다. 서버는 데이터 스트림(0xFFFE는 UTF-16을 나타냄)의 바이트 순서 표시 또는 XML 선언으로부터(있는 경우) 인코딩을 파생합니다. 그 결과 XML 매개 변수에서 XML 인코딩 불일치를 피하기 위한 가장 쉬운 방법은 클라이언트로부터 데이터를 네이티브 XML(ADO.NET의 SqlXml 클래스 사용) 또는 이진 유형으로 보내거나 [var]binary 데이터 형식을 서버에서 XML로 변환하는 것입니다.

    이러한 규칙을 요약하면 다음과 같습니다.


  • 텍스트 XML이 유니코드(UCS-2, UTF-16)인 경우 이를 XML 열, 변수 또는 매개 변수로 할당해도 아무 문제가 발생하지 않습니다.
  • 인코딩이 유니코드가 아니고 원본 코드 페이지로 인해 내재적인 경우 데이터베이스의 문자열 코드 페이지는 로드하려는(필요한 경우 COLLATE 사용) 코드 포인트와 같거나 호환되어야 합니다. 이러한 서버 코드 페이지가 없으면 명시적 XML 선언을 추가하여 적합한 인코딩을 지정해야 합니다.
  • 명시적 인코딩을 사용하려면 코드 페이지와 상호 작용이 없는 varbinary 유형을 사용하거나 적합한 코드 페이지의 문자열 유형을 사용합니다. 그런 다음 데이터를 XML 열, 변수 또는 매개 변수로 할당합니다.

    그래서 UTF-8로 전달하려는 경우 varbinary(max)로 전달하는 것이 가장 안전합니다. UTF-16 데이터는 바이트 순서 표시가 필요하지 않은 nvarchar(max)로 전달하거나 UTF-16 인코딩을 표시하도록 처음 두 바이트로 바이트 순서 표시가 0xFFFE인 varbinary(max)로 전달할 수 있습니다.


    XML 데이터 대량 로드


    SQL Server의 대량 로드 기능인 BCP, OPENROWSET 및 BULK INSERT를 사용하여 XML 데이터를 서버로 대량 로드할 수 있습니다. OPENROWSET을 사용하면 데이터를 파일에서 XML 열로 로드할 수 있습니다. 다음 예제에서는 이러한 점에 대해 설명합니다.


    예제: 파일로부터 XML 로드


    이 예제에서는 행을 테이블 문서에 삽입하는 방법을 보여 줍니다. XML 열의 값은 C:\temp\xmlfile.xml 파일로부터 이진 LOB(BLOB)로 로드되고 pk 열에 값 10이 제공됩니다. 파일은 CLOB나 NCLOB 대신 BLOB으로 로드되어 XML 문서가 인코딩되는 모든 인코딩을 수용합니다.

    INSERT INTO docs
    SELECT 10, xCol
    FROM (SELECT *
    FROM OPENROWSET (BULK ''C:\temp\xmlfile.xml'', SINGLE_BLOB)
    AS xCol) AS R(xCol)


    비-이진 데이터 정렬


    XML 데이터 형식에 사용되는 XML 데이터 정렬은 이진 데이터 정렬이며 대/소문자를 구분합니다(유니코드 코드 포인트 데이터 정렬). 응용 프로그램은 대/소문자 구분 검색과 같은 서로 다른 요구 사항을 갖고 있습니다. 이러한 목표는 적합한 문자열 값을 적합한 데이터 정렬과 함께 varchar 유형의 계산된 열로 승격함으로써 달성할 수 있습니다. 데이터 정렬 종속 작업에 대한 계산 열을 쿼리합니다. 또한 XML 열에 독일어 및 중국어 데이터 문자열이 들어 있다고 가정합니다. 이러한 각 데이터 정렬에 관련된 작업을 각 언어별로 하나씩 두개의 계산된 열에서 사용할 수 있습니다.


    XQuery 및 유형 유추


    Transact-SQL에 포함된 XQuery(http://www.w3.org/TR/xquery/ (영문))는 XML 데이터 형식 쿼리를 위해 지원되는 언어입니다. 이 언어는 Microsoft를 비롯한 주요 데이터베이스 공급업체의 참여로 W3C(World Wide Web Consortium)에서 개발 중에 있습니다(현재 마지막 협의 중). 여기에는 탐색 언어로 XPath 2.0이 포함됩니다. 데이터 수정을 위한 언어 구성은 XML 데이터 형식에서도 사용할 수 있습니다. SQL Server 2005에서 지원되는 XQuery 구성, 함수 및 연산자에 대한 정보는 온라인 설명서를 참조하십시오.


    오류 모델


    컴파일 오류는 의미상 잘못된 XQuery 식 및 XML DML 문으로부터 반환됩니다. 컴파일 단계에서는 XQuery 식 및 DML 문의 정적 유형이 올바른지 여부를 검사하고 형식 있는 XML에 대한 유형 유추를 위해 XML 스키마를 사용합니다. 여기에서는 식이 유형 안전도 위반으로 인해 런타임에 식이 실패할 수 있는 경우 정적 유형 오류를 발생시킵니다. 정적 오류의 예로는 정수에 문자열 추가와 형식 있는 데이터에 대해 존재하지 않는 노드의 쿼리를 들 수 있습니다.

    W3C 표준과는 달리 XQuery 런타임 오류는 빈 시퀀스로 변환되며 호출 컨텍스트에 따라 쿼리 결과에 빈 XML 또는 NULL로 채워질 수 있습니다.

    적합한 유형에 대한 명시적 형변환을 통해 사용자는 런타임 캐스트 오류가 빈 시퀀스로 변환되더라도 정적 오류와 관련된 문제를 해결할 수 있습니다.

    다음 하위 섹션에서는 유형 검사에 대해 자세히 설명합니다.


    단일 검사


    단일 항목이 필요한 위치 단계, 함수 매개 변수 및 연산자(예: eq)는 컴파일러에서 단일 항목이 런타임에 보장되는지 확인할 수 없는 경우 오류를 반환합니다. 문제는 형식 없는 데이터에서 자주 발생하며 형식 있는 데이터의 경우에도 일부 문제가 발생합니다. 예를 들어 특성 조회를 위해서는 단일 부모 요소가 필요하며 단일 부모 노드의 순서별 선택이 적합합니다. 특성 값 추출을 위한 nodes()-value() 조합에 대한 평가(Value(), nodes() 및 OpenXML() 참조)에는 다음 예제에서와 같이 nodes() 메서드가 단일 컨텍스트 항목을 제공하기 때문에 순서 사양이 필요하지 않습니다.


    예제: 알려진 단일 항목


    이 예제에서 nodes() 메서드는 각 요소에 대한 별개의 행을 생성합니다. nodes() 메서드에 대한 자세한 내용은 Value(), nodes() 및 OpenXML() 섹션을 참조하십시오. 노드에서 평가된 value() 메서드는 특성으로서 단일 항목인 @genre의 값을 추출합니다.

    SELECT nref.value(''@genre'', ''varchar(max)'') Genre
    FROM docs CROSS APPLY xCol.nodes(''//book'') AS R(nref)

    XML 스키마는 형식 있는 XML의 유형 검사에 사용됩니다. 노드가 XML 스키마에서 단일 항목으로 지정된 경우 컴파일러는 이 정보를 사용하고 오류가 발생하지 않습니다. 그렇지 않으면 순서별 단일 노드 선택이 필요합니다. 특히 /book//title과 같은 하위 항목 축을 사용하면 XML 스키마에 지정된 경우에도

    출처명: 한국마이크로소프트

  • 728x90

    SQL Server 2005에서 XML 데이터 형식을 위한 성능 최적화


    Shankar Pal, Babu Krishnaswamy, Vasili Zolotov, Leo Giakoumakis _ Microsoft Corporation


    적용 대상:
    SQL Server 2005

    요약: 이 문서에서는 Microsoft SQL Server 2005에서 XML 데이터 형식의 쿼리 및 데이터 수정 성능을 향상시키기 위한 몇 가지 방법을 설명합니다. 이 문서를 최대한 활용하기 위해서는 SQL Server 2005의 XML 기능에 익숙해야 합니다. 배경 자료로 MSDN 기사 Microsoft SQL Server 2005에서 XML 지원Microsoft SQL Server 2005를 위한 최상의 XML 사용 방법을 참조하십시오.


    소개


    엔터프라이즈 응용 프로그램은 반구조적 데이터 및 구조화되지 않은 데이터 모델링에 XML을 점점 더 많이 사용하고 있습니다. Microsoft SQL Server 2005는 이러한 응용 프로그램 개발을 돕기 위해 XML 데이터 처리를 위한 광범위한 지원을 제공합니다. XML 데이터는 XML 데이터 형식 열에 원시적으로 저장되어, XML 스키마의 모음에 따라 형식화되거나 형식화되지 않은 상태로 남아 있을 수 있습니다. 그리고 Last Call 및 XML 데이터 조작 언어에서 현재 부상하고 있는 W3C 권장 사항인 XQuery를 통해 세분화된 데이터 조작이 지원됩니다. 쿼리 성능을 향상시키기 위해 XML 열을 인덱스할 수 있습니다. 엔터프라이즈 응용 프로그램은 반구조적 데이터 및 구조화되지 않은 데이터를 모델링하기 위해 점점 더 많이 XML을 사용하고 있으므로 SQL Server 2005의 XML 지원을 통해 이점을 얻게 될 것입니다.

    이 문서에서는 XML 데이터 형식을 사용하는 응용 프로그램의 저장소, 쿼리 및 데이터 수정을 최적화하기 위한 제안을 제공합니다. 이러한 제안은 코드 샘플을 통해 설명됩니다. XML 데이터 모델링 및 사용을 위한 최상의 실행 방법에 관한 설명은 관련 MSDN 기사 Microsoft SQL Server 2005를 위한 최상의 XML 사용 방법을 참조하십시오. 또한 매핑을 사용하는 XML 뷰 기술의 최적화에 관한 내용은 MSDN Library에서 SQLXML 성능 최적화 (영문)를 참조하십시오.

    이 문서에서는 우선, 데이터베이스 설계 원리를 포함하여 XML을 사용한 데이터 모델링 지침을 살펴본 다음 응용 프로그램의 성능 최적화를 위한 쿼리 및 데이터 수정 지침을 제공합니다.


    XML 데이터 형식을 이용한 데이터 모델링


    XML 데이터 형식은 기업 내의 반구조적 데이터 및 구조화되지 않은 데이터에 데이터 모델링 기능을 제공합니다. XML 저장소 및 쿼리 처리의 성능은 데이터베이스 스키마 설계에 좌우되며 XML 열에서 XML 데이터 및 속성 승격의 구조 및 단위와 같은 요소를 포함합니다.

    맨 처음 내려야 할 결정은 응용 프로그램에 XML 데이터 모델의 기능이 필요한지 여부입니다. 구조화된 데이터는 관계형으로 가장 잘 모델링되고 관계형 열을 가진 테이블에 저장됩니다. 문서 순서 및 포함 계층을 유지해야 하고 재귀 구조를 가진 반구조적 데이터 또는 태그 데이터를 사용하는 경우 XML 데이터 모델이 가장 적합합니다.

    XML 데이터 형식 열에 구조화된 데이터를 저장하면 유용한 경우가 종종 있는데, 예를 들면 데이터가 유연한 구조를 갖거나 구조가 사전에 알려져 있지 않은 경우입니다.

    이런 시나리오는 개체에 대한 메타 데이터 정보가 XML로 모델링되고 XML 데이터 형식 열에 저장되는 경우 속성 관리에서 발생합니다. 다른 구조 및 콘텐츠 모델을 사용하는 서로 다른 형식의 개체 속성이 같은 XML 열에 저장되고 서로 쿼리될 수 있습니다. 가장 자주 쿼리되는 속성은 동일한 테이블 또는 다른 테이블의 열로 승격됩니다. 승격된 속성을 인덱싱하고 쿼리할 수 있으며 쿼리 계획은 XML 열을 쿼리하는 것보다 더 단순합니다.

    또는 들어오는 XML 데이터는 테이블로 분해되어 SQL 언어를 사용하여 쿼리될 수 있습니다. XML 생성이 쿼리 작업 부하의 중요한 부분인 경우 XML 데이터 형식 열에 XML 데이터의 중복된 복사본을 저장하는 것이 유용할 수 있습니다. 중복된 복사본은 XML 생성의 런타임 비용을 방지합니다.

    XML 데이터 형식을 이용한 데이터 모델링에는 절대적인 규칙이 없습니다. 각 모델링 상황에서 장점과 단점을 신중하게 심사숙고해야 합니다. 그리고 형식화된 XML 열과 형식화되지 않은 XML 열 중에서의 선택 및 XML 태그가 데이터에 도입되는 방법도 마찬가지로 중요합니다. 이 섹션의 나머지 부분에 이에 대한 고려 사항과 기타 고려 사항이 논의되어 있습니다.


    XML 데이터의 구조

    동일한 데이터를 서로 다른 방식(예: 요소 중심, 특성 중심, 요소와 속성의 결합)으로 표시할 수 있습니다. 이 선택은 콘텐츠를 구성하는 것(요소 값) 및 메타 정보를 구성하는 것(특성 값)의 인식, 그리고 태그의 카디널리티(예: 요소의 다중 발생)에 의해 결정됩니다. 한 가지 방식으로 반구조적 데이터 및 구조화되지 않은 데이터에 XML 태그를 도입하는 것은 다른 저장 및 쿼리 처리 방법에 비해 더 효과적일 수 있습니다.


    구체적인 태그 사용

    일반적인 요소 이름을 사용하고 추가 특성을 이용하여 서로 다른 요소 형식들을 구별하는 것이 편리한 경우가 종종 있습니다. 하지만 이 방법을 이용하면 XML 인덱스 조회를 효율적으로 수행할 수 없기 때문에 이 방법은 쿼리에서 잘 작동하지 않습니다. (XML 인덱싱에 관한 자세한 설명은 XML 데이터 인덱싱을 참조하십시오.)

    한편 의미적으로 풍부한 구체적인 요소 이름은 더 읽기 쉽고 더 효과적인 쿼리 계획을 생성하는 데 도움이 되는 태그를 제공합니다. 반면 매우 장황한 태그는 저장소 비용도 증가시킵니다. 다음 예제는 이 두 가지 측면을 보여줍니다.


    예제: 일반적 태그와 구체적 태그의 비교

    도서 및 DVD 정보에 XML 태그를 사용하기를 원한다고 가정해 봅시다. 한 가지 선택은, 두 가지 항목 형식을 구별하기 위해 두 개의 값 "book"과 "DVD" 중 하나를 갖는 @type 특성을 가진 <item>이라는 일반 요소를 사용하는 것입니다. 도서 및 DVD는 다음과 같이 표시될 수 있습니다.


    <item type="book"><title>Writing Secure Code</title></item>
    <item type="DVD"><title>The Godfather</title></item>


    도서 및 DVD에 대한 경로 식은 각각 /item[@type = "book"] 및 /item[@type = "DVD"]로 작성될 수 있습니다. 한편 다음과 같이 <book> 및 <DVD> 는 더 직접적인 XML 태그입니다.


    <book><title>Writing Secure Code</title></book>
    <DVD><title>The Godfather</title></DVD>


    이 표시는 더 간단한 경로 식 /book/DVD를 제공합니다. 또한 @type 특성에서 술어가 제거되기 때문에 쿼리 계획도 더 간단하고 효과적입니다. 게다가 이 표시를 이용하면 형식화되지 않은 XML의 경우에, 주 XML 인덱스(XML 데이터 인덱싱에 관한 자세한 내용은 XML 데이터 인덱싱 참조)에 있는 행의 수가 4개( <item>, 에 한 행, @type 및 그 값에 한 행, <title> 에 한 행, 제목 값에 한 행)에서 3개( <book> 또는 <DVD>, 에 한 행, <title> 에 한 행, 제목 값에 한 행)로 줄어듭니다. 이로 인해 3개에서 2개 행으로 저장소 오버헤드가 감소되며 이는 상당한 절감입니다.


    특성 중심 태그

    특성의 값은 형식화된 XML 및 형식화되지 않은 XML 둘 다에 대한 주 XML 인덱스의 단일 행에 특성 태그와 함께 저장됩니다. 비교해 보면, 형식화되지 않은 XML의 단순한 값 요소의 값은 요소 태그와 별개의 행에 저장됩니다. 따라서 형식화되지 않은 XML 내의 특성 값을 사용함으로써 저장소가 더 적게 필요합니다.

    더구나 특성의 값이 주 XML 인덱스에 있는 태그로서 동일한 행에서 구해지기 때문에 술어의 평가가 더 효과적이므로, 값의 또 다른 행에 액세스할 필요가 없습니다. 이 내용은 다음 예제에 예시되어 있습니다.


    예제: 특성 중심 태그

    위 예제에서는 다음과 같이 제목이 요소 대신 특성으로 모델링될 수 있습니다


    <book title="Writing Secure Code"/>
    <DVD title="The Godfather"/>


    형식화되지 않은 XML의 경우, 이 방식을 이용하면 주 XML 인덱스에 있는 행의 수를 3개(<book>, <title>에 각각 한 행씩, 제목 값에 한 행)에서 2개(<book>에 한 행, @title 특성에 한 행)로 줄일 수 있습니다. DVD의 경우에도 유사합니다.

    경로 식 /DVD[title = "The Godfather"]는 제목이 제목에 대한 요소 중심 태그가 있는 "The Godfather"인 DVD를 찾습니다. 특성 중심 태그의 경우에는 동일한 쿼리가 /DVD[@title = "The Godfather"]로 작성되고 쿼리에 필요한 JOIN 수가 하나 줄어듭니다.


    형식화되거나 형식화되지 않은 XML

    형식화되지 않은XML(즉, XML 데이터가 XML 스키마에 의해 설명되지 않음)의 요소 및 특성 값은 내부적으로 유니코드 문자열로 저장됩니다. 형식화되지 않은XML에서 작업하는 경우에는 데이터를 적합한 형식으로 변환해야 합니다. 예를 들어, 경로 식 (/book/price)[1] > 19.99 가 평가될 때 <price> 의 문자열 값이 숫자 비교를 위해 십진수로 변환됩니다. 이와 같은 비교가 많으면 비용이 많이 들게 됩니다. XML 스키마가 제공하는 형식 정보는 여러 방식으로 데이터베이스 엔진에 의해 사용됩니다. 삽입 및 업데이트된 XML 데이터는 XML 스키마를 준수하는지 검증된 다음 이진 표시("XML blob")로 저장됩니다. 요소 및 특성 값은 XML 인스턴스 내에 형식화된 값으로 저장됩니다. 이렇게 하면 XML blob이 상응하는 텍스트 형식보다 더 효율적으로 구문 분석될 수 있습니다. 형식화된 값은 XML 인덱스에 저장되며 데이터 변환이 제거될 때마다 인덱스 사용을 허용합니다. 쿼리 컴파일은 형식 정보를 사용하여 XQuery 식 및 데이터 수정 문의 정적 형식 정확성을 검사합니다. 형식 불일치 오류는 컴파일 시에 탐지되며 명시적 형식 캐스트를 사용함으로써 피할 수 있습니다.

    또한 형식 추론에 기반한 쿼리 최적화가 수행됩니다(예: <book> 의 <price> 가 xs:decimal 형식인 경우, (/book/price)[1] 의 xs:decimal로의 변환이 제거됩니다). 이는 XML 인덱스 조회에 긍정적인 효과를 줄 수 있습니다. (/book/price)[1] < 19.99와 같은 범위 술어는 VALUE 형식의 보조 XML 인덱스에 범위 스캔을 수행합니다. (XML 데이터 인덱싱에 관한 자세한 내용은 이 문서의 XML 데이터 인덱싱 XML 데이터 인덱싱을 참조하십시오.) 형식화되지 않은 XML에 필요한 데이터 변환은 이러한 범위 스캔을 방지합니다. 또한 XML 스키마가 단일 <price> 요소를 지정하고 각 XML 인스턴스에서 단일 <book> 요소만을 허용하는 경우에는(/book/price)[1]의 서수 [1]이 필요하지 않습니다. 형식화된 XML에는 XML 데이터 삽입 및 수정 동안 유효성 검사가 필요합니다. 유효성 검사의 비용은 결코 사소하지 않으며 스키마 정의의 복잡성 및 XML 데이터에서 발생하는 태그의 수와 같은 요소에 따라 다릅니다.

    속성 승격

    쿼리 처리 동안 문서 순서 및 포함 계층과 같은 구조 정보가 XML 인스턴스에 보존됩니다. 따라서 쿼리 계획이 복잡해지는 경향이 있습니다. 스칼라 값을 XML 열에서 같은 테이블이나 다른 테이블의 관계형 열로 승격하고 이 열에 대해 직접적으로 쿼리를 작성함으로써 일부 쿼리에 대한 계획이 단순화될 수 있습니다. 승격된 속성은 인덱스할 수 있습니다. 속성 값을 구체화하고 인덱싱하면, 미리 계산된 값이 쿼리 성능을 높이는 방식과 같은 방식으로 XML 열에서 XQuery를 사용할 때보다 성능이 더 좋아집니다.

    속성 값을 검색하거나 속성 값을 필터로 사용하여 해당 XML blob을 검색하는 경우 속성 승격은 성능을 향상시킵니다. 후자의 경우 속성 값의 선택성이 중요한 요소입니다.

    단일값 속성은 계산 열과 동일한 테이블의 열로 승격할 수 있습니다. 단일값 속성 및 다중 값 속성은 둘 다 다른 테이블의 열로 승격할 수 있고 트리거를 사용하여 유지 관리할 수 있습니다. 아래에 이 두 가지 속성 승격 방법이 설명되어 있습니다.


    계산 열 사용

    XML 데이터 형식 메서드를 사용하여 스칼라 값을 추출하기 위해 먼저 Transact-SQL 사용자 정의 함수가 생성됩니다. 그런 다음 사용자 정의 함수에서 정의한 계산 열이 테이블에 추가됩니다. 각각의 승격된 속성에 대해 이 두 단계가 반복되고 필요에 따라 관계형 인덱스가 이들 열에 생성됩니다.

    XML 열에 대한 XQuery 식을 계산 열을 사용하는 SQL 문으로 다시 작성해야 하며, XML 인스턴스가 일치하는 행에서 검색됩니다. 쿼리 비용을 기준으로 쿼리 최적화 프로그램이 계산 열의 인덱스를 선택합니다. 계산 열은 미리 계산되므로, 승격된 속성은 XML 열을 직접 쿼리하는 것보다 더 빠른 성능을 낳습니다.

    열이 SELECT 목록에서만 사용되고 술어 평가에 사용되지 않는 경우 계산 열의 인덱싱을 피할 수 있습니다. 이 경우 성능상의 이점을 위해 계산 열의 지속성만으로도 충분합니다. 계산 열이 인덱스될 때, 계산 열 식이 정확하지 않거나 명확하지 않은 경우 계산 열이 계속 유지되어야 합니다.

    아래 예제는 속성 승격을 위한 계산 열의 사용을 보여줍니다.


    예제: 속성 승격을 위한 계산 열 사용

    ISBN을 계산 열로 승격하는 것이 시간과 노력을 들일 만한 일이 되도록, 지정된 ISBN에 따라 책을 조회하는 일반적인 작업 부하를 가정해 봅시다. 다음과 같이 ISBN을 검색하는 사용자 정의 함수를 정의합니다.


    CREATE FUNCTION udf_get_book_ISBN (@xData xml) RETURNS varchar(20)
    WITH SCHEMABINDING
    BEGIN
    RETURN @xData.value('(/book/@ISBN)[1]', 'varchar(20)')
    END


    ISBN을 위해 계산 열을 docs 테이블에 추가합니다.


    CREATE TABLE docs (id int PRIMARY KEY, xCol XML)
    ALTER TABLE docs ADD ISBN AS dbo.udf_get_book_ISBN(xCol)


    ISBN 열에 클러스터되지 않은 인덱스를 만듭니다.


    CREATE INDEX COMPUTED_IDX ON docs (ISBN)


    아래 쿼리를


    SELECT xCol
    FROM docs
    WHERE xCol.exist ('/book/@ISBN[. = "0-2016-3361-2"]') = 1


    계산 열을 사용하기 위해 다음과 같이 다시 작성합니다.


    SELECT xCol
    FROM docs
    WHERE ISBN = '0-2016-3361-2'


    ISBN 값의 추출이 미리 처리되어 있기 때문에 다시 작성한 쿼리는 더 간단한 쿼리 계획을 생성합니다.


    속성 테이블 사용

    별도의 속성 테이블은 유지 관리를 위해 삽입, 삭제 및 업데이트 트리거 설정이 필요합니다. 이 테이블은 속성 테이블의 각 행이 속성 값(피벗되지 않은 표시)을 포함하고 있는 경우의 다중값 속성에 적합합니다. 속성 테이블의 생성 및 유지 관리를 보여주는 예제를 관련 MSDN 기사 Microsoft SQL Server 2005를 위한 최상의 XML 사용 방법에서 찾을 수 있습니다.

    형제 항목의 관련 순서가 응용 프로그램에 중요한 경우 속성 테이블에 시퀀스 번호 열이 요구됩니다. 하지만 이로 인해, XML 하위 트리 삽입 및 제거의 경우 속성 테이블 유지 관리가 복잡해집니다.

    편의상 단일값 속성 열을 테이블에 추가할 수 있습니다. 이렇게 하면 열에서 중복이 발생하지만 두 속성이 모두 필요한 경우 JOIN이 제거됩니다.

    승격된 속성의 최대 카디널리티 N이 작고 사전에 알려진 경우, 별도의 속성 테이블 대신 N개의 계산 열을 생성하고 쿼리 프로세서가 이러한 열을 유지 관리하게 하는 것이 편리할 것입니다.


    XML 데이터 대량 로드


    SQL Server의 대량 로드 기능을 사용하여 XML 데이터를 XML 데이터 형식 열에 대량 로드할 수 있습니다. 여기에는 BCP IN, BULK INSERT 및 OPENROWSET 메서드가 포함됩니다.

    BCP 입력은 가능한 경우 XML 데이터의 중간 복사본을 회피하도록 최적화되었습니다. 따라서 XML 열에 행 또는 열 제약 조건이 없는 경우 BCP가 세 개의 대체 방법들 중에서 최상의 성능을 갖습니다.


    OpenRowset 사용

    OPENROWSET는 파일에서 XML 데이터를 XML 열, 변수 및 매개 변수로 로드하는 편리한 방법입니다. 변수 또는 매개 변수에서 XML 데이터를 여러 번 쿼리하면 파일에서 같은 횟수만큼 데이터를 가져올 수 있습니다. 아래 예제에서와 같이 XML 데이터를 XML 변수로 한 번 읽어 들여 이를 여러 번 쿼리하는 것이 더 낫습니다.


    예제: OPENROWSET의 출력 쿼리

    다음 쿼리에서 XML 데이터는 파일에서 테이블 식 XmlFile의 [Contents] 열로 읽혀 들어갑니다. nodes() 메서드는 XML 인스턴스에서 <author> 요소를 찾습니다. 각 value() 메서드는 파일에서 XML 데이터를 매번 로드하는, <author> 요소에 관련된 경로 식을 평가합니다.


    WITH XmlFile ([Contents]) AS (
    SELECT CONVERT (XML, [BulkColumn])
    FROM OPENROWSET (BULK N'C:\Filedata.xml', SINGLE_BLOB) AS [XmlData]
    )
    SELECT nref.value('first-name[1]', 'nvarchar(32)') FirstName,
    nref.value('last-name[1]', 'nvarchar(32)') LastName
    FROM [XmlFile] CROSS APPLY [Contents].nodes('//author') AS p(nref)


    다시 작성된 아래 쿼리에 나타난 대로 성능 향상을 위해 파일 데이터를 한 번만 로드하면 됩니다. 즉, 파일 내용이 XML 변수 @xmlData로 한 번만 읽혀 들어 가고 SELECT 문에서 다시 사용됩니다.


    DECLARE @xmlData XML;
    SELECT @xmlData = CONVERT (XML, [BulkColumn])
    FROM OPENROWSET (BULK N'C:\Filedata.xml', SINGLE_BLOB) AS [XmlData];

    SELECT nref.value('first-name[1]', 'nvarchar(32)') FirstName,
    nref.value('last-name[1]', 'nvarchar(32)') LastName
    FROM @xmlData.nodes ('//author') AS p(nref)


    XML 데이터 인덱싱


    XML 인덱스

    XML 열로의 세분화된 쿼리의 경우 XML 열에 주 XML 인덱스를 만드는 것이 좋습니다. 주 XML 인덱스는 형식화된 XML 열 및 형식화되지 않은 XML 열 모두에서 생성될 수 있고 전체 XML 열 내의 모든 경로 및 값을 인덱스합니다. 주 XML 인덱스는 XML 열에 XML 인스턴스의 분할된(shredded) 표시를 기준으로 B+트리를 만듭니다. XML 열에 XML blob뿐만 아니라 이 B+트리가 만들어지고 그 크기는 XML 열의 XML blob을 모두 합친 크기보다 더 큽니다. B+트리는 XML 데이터 형식 메서드를 이용하여 XML 데이터를 쿼리하는 데 사용됩니다. XML blob은 전체 XML blobSELECT * FROM docs와 같은 기본 테이블에서 검색되는 경우를 최적화하는 데 사용됩니다. 이렇게 하면 더 작은 크기와 직렬화 비용 덕분에 주 XML 인덱스에서 XML 콘텐츠를 직렬화할 때보다 더 빨라집니다.

    보조 XML 인덱스는 쿼리 최적화 프로그램이 더 나은 계획을 제안하도록 추가 옵션을 제공합니다. 응용 프로그램은 PATH, PROPERTY, VALUE 형식의 보조 XML 인덱스를 사용함으로써 성능이 보다 더 향상될 수 있습니다.

  • PATH 인덱스는 XML 데이터 형식에서 /book[@ISBN = "0-2016-3361-2"]와 같은 경로 식이 발생하는 경우에 항상 유용합니다. 긴 경로 식일수록 그 이점은 더 큽니다. PATH 인덱스는 전반적으로 상당한 속도 증가를 제공합니다.
  • PROPERTY 인덱스는 XML 인스턴스의 여러 속성이 SELECT 문 내에서 검색되는 경우에 유용합니다. 각 XML 인스턴스의 속성을 함께 클러스터링하면 성능이 보다 더 향상될 수 있습니다.

  • VALUE 인덱스는 하위 항목 축(예: //-operator) 및 와일드카드(예: /book[@* = "novel"])를 포함하는 경로 식에 유용합니다. 하나 이상의 보조 XML 인덱스가 도움이 되는지 여부를 결정하기 위해서는 쿼리 작업 부하의 분석이 필요합니다. 또한 XML 데이터 인덱스의 전체적인 혜택을 측정하는 데 인덱스 유지 관리 비용을 고려해야 합니다.

    대부분의 응용 프로그램은 예상되는 쿼리 작업 부하를 알고 있으며 쿼리에서 발생하는 경로만을 인덱싱하여 이점을 얻을 수 있습니다. 이 경로는 이 문서의 후반부 "속성 승격"에 설명된 대로 속성으로 승격될 수 있습니다.

    부분적 XML 업데이트

    XML 데이터 형식의 인플레이스 업데이트는 세분화된 데이터 수정 동안 상당한 성능 향상을 제공합니다. 새 상태(데이터 수정 후) 및 이전 상태(데이터 수정 전) 간의 차이점이 처리되고 XML 열 저장소를 비롯하여 주 XML 인덱스에 적용됩니다. 또한 주 XML 인덱스의 변경 사항이 보조 XML 인덱스에도 전파됩니다. 이렇게 하면 저장소에서 업데이트되는 데이터의 양이 더 적고 그에 따라 트랜잭션 로그가 절감되므로 성능 혜택을 얻을 수 있습니다. 대부분의 경우 이러한 절감은 새 상태 및 이전 상태를 비교하는 비용을 상쇄합니다.

    이 경우에 가장 적합한 시나리오는 XML DML에서 명령문의 "값 대체"를 이용한 특성 또는 요소 값의 수정입니다. 이렇게 하려면 XML 열에 있는 각각의 주 XML 인덱스 및 보조 XML 인덱스에서 행을 하나씩 업데이트해야 합니다. 또한 이 업데이트는 업데이트된 특성 또는 요소를 포함하는 XML blob의 디스크에 있는 페이지에 로컬입니다. 물론 이전 값을 큰 값으로 대체하면 새 디스크 페이지가 기록됩니다. 다음은 업데이트가 매우 효율적인 경우의 예제입니다.


    예제: 특성 값 업데이트

    이 예제에 나타난 대로 <book> 의 <price> 수정은 XML 인스턴스 및 XML 인덱스의 인플레이스 업데이트를 수행합니다.


    UPDATE docs
    SET xCol.modify ('replace value of (/book/price/text())[1] with 29.99')


    특성, 요소 또는 하위 트리 삽입의 경우, 새로 삽입된 노드 및 이 노드를 따르는 형제 항목이 해당 하위 트리와 함께 업데이트되거나 삽입됩니다. XML blob에서도 이와 비슷한 변경이 발생합니다. 노드 삭제의 경우에도 이와 유사하며 삭제 지점 위의 형제 항목이 업데이트됩니다.

    최악의 시나리오는 노드를 XML 데이터 형식 인스턴스의 가장 왼쪽 조각으로서 삽입하거나 루트 요소의 가장 왼쪽 자식(child)을 삽입하는 동안 발생합니다. 이렇게 하면 전체 XML 인스턴스가 업데이트됩니다. 이 상황은 노드를 XML 인스턴스의 가장 오른쪽 조각 또는 루트 요소의 가장 오른쪽 자식(child)으로 삽입함으로써 피할 수 있습니다.

    루트 요소의 가장 왼쪽 조각 또는 가장 왼쪽 자식(child)의 삭제에도 이와 비슷한 비용이 듭니다. 요소가 자주 삽입되고 삭제되는 경우에는 요소를 가장 오른쪽 조각 또는 루트 요소의 가장 오른쪽 자식(child)으로 삽입하는 편이 더 낫습니다. 다음 예제는 비용이 많이 드는 경우를 보여줍니다.


    예제: 비용이 많이 드는 업데이트

    <publisher> 요소가 <book> 요소의 가장 왼쪽 자식(child)으로 삽입되어 <book> 의 모든 하위 요소가 업데이트됩니다.


    UPDATE docs
    SET xCol.modify ('
    insert <publisher>Microsoft Press</publisher>
    before (/book/title)[1]')


    <publisher> 를 <book> 의 가장 오른쪽 자식(child)으로 삽입하면 더 효율적입니다.


    UPDATE docs
    SET xCol.modify ('
    insert <publisher>Microsoft Press</publisher> into (/book)[1]')


    XML 스키마 제약 조건은 삽입 지점을 결정할 수 있고 새 노드를 가장 오른쪽의 가능한 위치에 삽입하면 최상의 성능을 얻을 수 있습니다.


    형식의 결합으로 인한 최적화 저해

    암시적 캐스트를 요구하는 union 형식의 값은, 보조 XML 인덱스가 경로를 일치시키는 데 사용될 수 있는 경우에도 값에 대한 보조 XML 인덱스의 조회를 막습니다. 이와 같이 union 형식의 값은 범위 스캔이 VALUE 보조 XML 인덱스에서 발생하지 못하게 합니다. 자세한 내용은 이 문서의 "범위 제약 조건"을 참조하십시오. 같은 추론이 <xs:anyAttribute>에도 적용됩니다.

    모델 그룹(<xs:choice> 및 <xs:all> ), 대체 그룹 및 와일드카드 섹션(xs:any)은 컨텐츠 모델로서 형식의 결합을 갖습니다. 정확한 형식이 쿼리 컴파일 및 최적화 동안 알려지지 않는 경우 런타임 형식 캐스트가 그 값에 대해 작업하기 위해 필요할 수 있습니다. 이렇게 하면 쿼리 속도가 느려집니다. 따라서 성능상의 이유로 가능한 경우 이러한 XML 스키마 구조 및 데이터 형식을 피해야 합니다.

    요소의 단일 발생을 나타내는 스키마 구조를 사용하면 쿼리 최적화에 도움이 됩니다. 이러한 이유로 <xs:choice> 구조가 선택적 요소가 있는 <sequence> 에 비해 선호됩니다.


    XML 인덱스 선택 비활성화

    XML 인덱스가 제약 조건을 평가하기 전 또는 후에 수정되도록 쿼리 최적화 프로그램이 보장하지 않기 때문에 XML 인덱스 선택은 check 제약 조건에서 비활성화됩니다. 이 문서의 성능 지침을 따라 제약 조건이 XML blob 상에서 효율적으로 평가될 수 있도록 하기 위해 충분한 주의를 기울여야 합니다. 뿐만 아니라 XML 인덱스 선택은 CHECK OPTION이 있는 뷰에서 비활성화됩니다.


    XML 열의 전체 텍스트 인덱스

    XML 열의 XML 인덱스와는 독립적으로 이 열에 전체 텍스트 인덱스를 만들 수 있습니다. 전체 텍스트 인덱스는 요소 콘텐츠를 인덱싱하고 XML 태그 및 특성 값을 무시하며 태그를 토큰 경계로 사용합니다.

    XQuery 함수 fn:contains()가 리터럴, 부분 문자열 일치의 의미론을 갖는 반면 CONTAINS()를 사용하는 전체 텍스트 검색은 형태소 분석을 이용한 토큰 일치를 사용합니다. 따라서 이들의 의미론은 상이합니다. 차이점을 예로 들어 보자면, 단어 "data"를 검색하면 XQuery에서는 단어 "database"와 일치하지만 전체 텍스트 의미론에서는 일치하지 반면, 단어 "drove"를 검색하면 전체 텍스트 의미론에서는 단어 "driving"과 일치하지만 XQuery에서는 일치하지 않습니다. 게다가 전체 텍스트 검색은 특성 값 검색에 사용할 수 없고, 한편 XQuery 식은 혼합 콘텐츠를 검색하기 위해 집계 함수 fn:string()을 사용해야 합니다.

    전체 텍스트 인덱스가 XML 열에 존재하는 경우 다음 작업을 수행하는 것이 좋습니다.

  • 전체 텍스트 검색을 사용하여 관심 있는 XML 값을 필터링합니다.
  • 선택한 XML 인스턴스를 XML 데이터 형식 메서드를 사용하여 쿼리합니다. 이 단계 동안 XML 열의 XML 인덱스가 사용됩니다. 이렇기 때문에 전체 텍스트 인덱스 및 XML 인덱스를 모두 사용하게 됩니다. 전체 텍스트 검색에서 검색 단어 또는 구의 높은 선택성은 XQuery 검색을 위한 추가 처리 범위를 기본 테이블에 있는 비교적 적은 행의 수로 좁혀줍니다. 이로 인해 쿼리의 속도가 상당히 빨라질 수 있습니다. 이 접근 방법은 검색 구가 키워드 경계와 일치하는 어간으로 이루어진 경우에 사용할 수 있습니다.

    예제: XQuery 일치와 전체 텍스트 결합

    다음 쿼리는 키워드 'data'에 대한 전체 텍스트 검색을 수행하고 단어 "data"가 <book>의 <title>요소의 컨텍스트에서 나타나는지 확인합니다. 이 쿼리는 전체 텍스트 contains() 메서드를 사용하여 검색 단어를 포함하고 있는 XML 인스턴스를 찾습니다. 즉, XML 데이터 형식 메서드 exist()는 XML 인스턴스가 올바른 컨텍스트에서 부분 문자열을 포함하는지 확인합니다.


    select *
    from docs
    where contains(xCol, 'data')
    AND xCol.exist('/book/title/text()[contains(.,"data")]') = 1


    예제: 전체 텍스트에서 접두사 검색 사용

    전체 텍스트 인덱스에서 접두사 검색을 수행할 수 있습니다. "database"와 같은 "data"로 시작하는 모든 키워드와 일치하는 쿼리에 대해, 위 쿼리는 다음과 같이 다시 작성될 수 있습니다. XQuery 검색은 "database"와도 일치합니다.


    select *
    from docs
    where contains(xCol, '"data*"')
    and xCol.exist('/book/title/text()[contains(.,"data")]') = 1


    전체 텍스트 contains() 메서드에서 큰따옴표의 사용에 주의하십시오.


    스냅샷 격리 및 XML 인덱스

    XML 데이터 수정은 이전 XML 인스턴스를 새 XML 인스턴스로 업데이트합니다. 이러한 변경은 주 XML 인덱스 및 보조 XML 인덱스에 전파됩니다. 기본 테이블 및 XML 인덱스에서 수정된 행은 잠겨지고 행 및 페이지 잠금이 쿼리 분석기의 결정에 따라 테이블 잠금으로 에스컬레이션될 수 있습니다. 특히 작업 부하에서 수정이 잦은 경우에는 잠금 에스컬레이션으로 인해 동시성이 나빠집니다.

    SQL Server 2005에서 스냅샷 기반 격리는 "스냅샷"이라는 새로운 격리 수준과 새로운 read-committed 격리 수준의 구현을 도입했습니다. 이에 대한 자세한 내용은 SQL Server 온라인 설명서에서 찾아볼 수 있습니다. 이들은 데이터베이스를 스냅샷 격리에 사용할 수 있는 경우 판독기와 작성기 사이의 잠금 경합을 제거하는 내부 버전 관리 메커니즘에 기반합니다. 잠금 경합이 감소되면 처리량이 더 높아질 수 있습니다.

    스냅샷 기반 격리 하에서 읽기 작업은 동시 업데이트에서 차단되지 않고서 버전 관리되는 데이터에 액세스할 수 있습니다. 이렇게 차단이 감소되면 동시 작업 부하에서 트랜잭션 처리량이 잠재적으로 향상됩니다.

    스냅샷 격리를 사용하면 업데이트 시 XML 열 값과 해당 주/보조 XML 인덱스 행이 버전 관리됩니다. 이렇게 하면, XML이 아닌 열의 수정으로 인해 포함하는 행이 버전 관리되는 경우 XML 열의 불필요한 버전 관리를 피할 수 있습니다. 이 최적화는 XML 처리에 있어 스냅샷 격리를 매우 유용하게 만듭니다.


    쿼리 및 데이터 수정

    인덱스된 XML에 대한 여러 value() 메서드 실행 병합

    인덱스된 경우에 더 빠른 실행을 위해, SELECT 목록의 동일한 형식화된 XML 열에서 여러 value() 메서드의 실행을 결합할 수 있습니다. 실행을 결합할지 여부는 쿼리 분석기가 쿼리 비용을 기반으로 결정합니다. 이로 인해 속도가 현저히 향상됩니다. 아래에 예제가 나와 있습니다.


    예제: 여러 value() 메서드 실행 결합

    XML 스키마 모음 bookCollection에 있는 XML 스키마 이름 공간 "http://www.microsoft.com/book"에 의해 요소의 콘텐츠 모델이 정의된다고 가정합시다. 또한 이 예제에서 XML 열 xDoc이 docs 테이블에 추가되고 bookCollection을 사용하여 형식화된다고 가정합시다. XML 스키마 정의는 아래와 같습니다.


    CREATE XML SCHEMA COLLECTION bookCollection AS
    '<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://www.microsoft.com/book"
    targetNamespace="http://www.microsoft.com/book">
    <xsd:element name="book" type="bookType" />
    <xsd:complexType name="bookType">
    <xsd:sequence>
    <xsd:element name="title" type="xsd:string" />
    <xsd:element name="author" type="authorName"
    maxOccurs="unbounded"/>
    <xsd:element name="price" type="xsd:decimal" />
    </xsd:sequence>
    <xsd:attribute name="subject" type="xsd:string" />
    <xsd:attribute name="releasedate" type="xsd:integer" />
    <xsd:attribute name="ISBN" type="xsd:string" />
    </xsd:complexType>
    <xsd:complexType name="authorName">
    <xsd:sequence>
    <xsd:element name="first-name" type="xsd:string" />
    <xsd:element name="last-name" type="xsd:string" />
    </xsd:sequence>
    </xsd:complexType>
    </xsd:schema>'
    GO

    ALTER TABLE docs ADD COLUMN xDoc XML (DOCUMENT bookCollection)
    GO


    아래 쿼리에서는, value() 메서드가 동일한 XML 열에서 호출되고 <title> 및 <price> 요소의 단일 카디널리티가 XML 스키마에서 정적으로 추론되기 때문에 value() 메서드의 실행을 결합합니다.


    WITH XMLNAMESPACES ('http://www.microsoft.com/book' AS "bk")
    SELECT xCol.value ('/bk:book/bk:title', 'nvarchar(128)') Title,
    xCol. value('/bk:book/bk:price', 'decimal(5,2)') Price
    FROM docs


    최적화가 발생하려면 다음 조건이 유지되어야 합니다.

  • 열을 형식화하는 XML 스키마 모음에서 노드의 단일 카디널리티를 추론할 수 있도록 XML 열을 형식화해야 합니다. 해당되는 경우 열 옵션 DOCUMENT을 사용하여 XML 열을 선언해야 합니다. 그렇지 않으면 nodes() 메서드를 사용하여 단일 노드 참조를 생성해야 합니다. 또한 nodes() 메서드가 단일 요소를 보장하는 데 사용되고 value() 메서드가 그러한 요소에서 특성 값을 추출하는 경우 형식화되지 않은 XML에 대해서도 최적화가 작동합니다.
  • 최적화가 발생하려면 전체 경로를 지정해야 합니다. 와일드카드(*), 하위 항목 축(// operator), 상위 항목 축(..), XPath 함수 및 노드 테스트(예: node())를 포함하는 경로는 이러한 최적화의 발생을 막습니다.
  • value() 메서드의 경로 식은 술어 또는 서수를 포함하지 않을 수 있습니다.
  • nodes() 메서드에서 얻은 컨텍스트 항목과 관련된 경로 식에 대해 최적화가 발생하는데, 이러한 경우 value() 메서드의 첫 번째 인수는 위 제약과 더불어 전체 상대 경로여야 합니다.
  • value() 메서드 호출이 병합되려면 SELECT 목록에서 연속적으로 나타나야 합니다. 불연속적인 value() 메서드의 실행은 결합될 수 없습니다.

    또한 xCol.value(…) = xCol.value(…)와 같은 술어에 대해 T-SQL WHERE 절의 value() 메서드에서 최적화가 발생할 수 있습니다. xCol.value(…) = constant의 술어에서는 최적화가 발생하지 않습니다.

    존재 확인을 위해 exist() 메서드 사용

    보다 나은 성능을 위해 가능한 경우 XML 데이터 형식의 value() 메서드 대신 exist() 메서드를 사용하십시오. exist() 메서드는 SQL WHERE 절에서 사용하는 경우 가장 유용하며 value() 메서드보다 XML 인덱스를 더 효과적으로 활용합니다. XQuery 식에서 sql:variable() 및 sql:column()을 사용하는 경우에도 마찬가지입니다.

    예를 들어, exist() 메서드를 사용하여 "Writing Secure Code"라는 제목의 책을 검색하는 다음 쿼리를 살펴봅시다.


    SELECT *
    FROM docs
    WHERE xCol.exist('(/book/title/text())[.="Writing Secure Code"]') = 1


    PATH 또는 VALUE 보조 XML 인덱스가 이들 인덱스에서의 값 조회(이 예제에서 "Writing Secure Code")를 포함하여 경로 식((/book/title/text())[.="Writing Secure Code"])을 평가하여 반환할 XML 인스턴스를 산출하기 위해 사용됩니다. 경로 및 검색 값의 선택성이 높은 경우 결과 실행이 열의 모든 XML blob에 대해 경로 식을 평가하는 것보다 훨씬 더 빠를 수 있습니다. 검색 값은 sql:variable() 또는 sql:column()을 사용하여 제공할 수 있습니다. 자세한 내용은 이 문서의 "XQuery 및 XML DML 식 매개 변수화"를 참조하십시오.

    아래와 같이 value() 메서드를 사용하여 작성한 쿼리는


    SELECT *
    FROM docs
    WHERE xCol.value('(/book/title)[1]', 'varchar(50)') = 'Writing Secure Code'


    먼저 모든 책 제목을 평가한 다음 필터 "Writing Secure Code"를 적용합니다. 이렇게 하면 XML 인덱스 조회에서 필터 값 "Writing Secure Code"가 사용되지 않기 때문에 쿼리 실행의 효율성이 떨어집니다. SQL 변수 또는 또 다른 value() 메서드를 사용하여 지정한 필터 값도 유사한 동작(behavior)을 나타냅니다.

    nodes()-value() 결합 사용
    nodes() 메서드는 value() 메서드 내에서 사용할 수 있는 내부 노드 참조의 행 집합을 생성하여 이들 노드에서 스칼라 값을 추출합니다. 이들 메서드를 함께 사용하여 XML 데이터를 관계형 형식으로 표시할 수 있습니다.

    아래 예제에서 보는 대로, value() 메서드에서 컨텍스트 노드의 특성을 선택하는 데 사용되는 서수 술어가 제거될 수 있도록 nodes() 메서드의 출력에서 각 행은 단일 참조를 표시합니다. 또한 nodes() 메서드가 정확히 하나의 참조를 제공할 경우 nodes() 메서드를 완전히 제거하면 쿼리가 더 빠르게 수행됩니다. 이러한 최적화는 XML 변수 및 매개 변수에 가장 유용합니다.


    예제: nodes() 메서드로 서수 술어 제거

    이 쿼리는 docs테이블의 xCol 열에 있는 각 책의 인스턴스에서 ISBN 특성을 추출합니다. nodes() 메서드는 각 개별 <book> 요소(컨텍스트 노드)에 대한 별도의 참조를 내보내고 컨텍스트 노드에는 최대 하나의 @ISBN 특성이 있을 수 있습니다.


    SELECT ref.value('@ISBN', 'nvarchar(32)')
    FROM docs CROSS APPLY xCol.nodes('/book') AS node(ref)


    각 XML 인스턴스에서 요소가 하나만 발생할 경우 다음의 다시 작성된 쿼리가 더 빠릅니다.


    SELECT xCol.value('(/book/@ISBN)[1]', 'nvarchar(32)')
    FROM docs


    XML blob을 위한 최적화


    XML 변수 및 매개 변수의 더 나은 확장성을 위한 여러 개의 tempDB 파일

    XML 변수 및 매개 변수는 그 값이 작은 경우에는 주 메모리를 저장소로 사용합니다. 단, 큰 값은 tempdb 저장소에서 백업합니다. 다중 사용자 시나리오에서 많은 수의 대형 XML blob이 발생할 경우 tempdb 경합이 충분한 확장성을 위해 병목 상태를 일으킬 수 있습니다. 여러 개의 tempdb 파일을 만들면 저장소 경합이 감소되고 확장성이 훨씬 더 좋아집니다. 다음 예제는 여러 개의 tempdb 파일을 만들 수 있는 방법을 보여줍니다.


    예제: 여러 개의 tempdb 파일 만들기

    이 예제에서는 각각 처음 크기가 8MB인 두 개의 tempdb용 추가 데이터 파일과 각각 처음 크기가 1MB인 두 개의 로그 파일을 만듭니다.


    USE TEMPDB
    GO

    ALTER DATABASE tempdb ADD FILE
    (NAME = 'Tempdb_Data1',
    FILENAME = 'C:\temp\Tempdb_Data1.MDF', SIZE = 8 MB),
    (NAME = 'Tempdb_Data2',
    FILENAME = 'C:\temp\Tempdb_Data2.MDF', SIZE = 8 MB)
    GO

    ALTER DATABASE tempdb ADD log FILE
    (NAME = 'Tempdb_Log1',
    FILENAME = 'C:\temp\Tempdb_Log1.LDF', SIZE = 1 MB),
    (NAME = 'Tempdb_Log2',
    FILENAME = 'C:\temp\Tempdb_Log2.LDF', SIZE = 1 MB)
    GO


    이 파일은 ALTER DATABASE tempdb REMOVE FILE 명령을 사용하여 제거될 수 있습니다. 자세한 내용은 SQL Server 2005용 SQL Server 온라인 설명서를 참조하십시오.


    XML 데이터 형식으로의 추가 캐스트 제거

    XML 형식의 입력 인수를 가진 inlinable 함수에서 호출자는 XML 데이터 형식으로 암시적으로 변환되는 텍스트 또는 이진 값을 제공할 수 있습니다. 호출 수신자의 본문에서 XML 인수의 각 사용은 입력 값을 XML 데이터 형식으로 캐스트합니다. 이 비용은 인수를 XML 데이터 형식 변수(XML 데이터 형식으로 한 번의 인수 값 변환 유발)로 복사함으로써 피할 수 있고 XML 변수는 함수 또는 저장 프로시저의 본문에서 여러 번 사용할 수 있습니다. 다음 예제는 이러한 특징을 예시합니다.


    예제: 변환 제거

    책의 제목 및 ISBN을 반환하는 아래 GetTitleAndIsbnOfBook() 함수를 살펴봅시다.


    CREATE FUNCTION GetTitleAndIsbnOfBook (@book XML)
    RETURNS TABLE AS
    RETURN
    SELECT @book.value ('(/book/@ISBN)[1]', 'nvarchar(32)') ISBN,
    @book.value ('(/book/title)[1]', 'nvarchar(128)') title


    함수가 문자열 값으로 호출되면 각 value() 메서드 호출에 대해 XML 데이터 형식으로의 변환이 발생합니다. 함수는 XML 데이터 형식으로의 인수 변환이 한 번만 발생하도록 다음과 같이 다시 작성될 수 있습니다. 하지만 다중 명령문 테이블 반환 함수에 필요한 테이블 변수 @retTab으로 인해 추가 비용이 발생하는데, 이 비용은 XML 데이터의 크기가 큰 경우 XML 변수에 대한 충분한 횟수의 액세스로 상쇄될 수 있습니다.


    CREATE FUNCTION GetTitleAndIsbnOfBookOpt (@book varbinary(max))
    RETURNS @retTab TABLE (ISBN nvarchar(32), title nvarchar(128)) AS
    BEGIN
    DECLARE @xbook XML
    SET @xbook = @book
    INSERT INTO @retTab
    SELECT @xbook.value ('(/book/@ISBN)[1]', 'nvarchar(32)'),
    @xbook.value ('(/book/title)[1]', 'nvarchar(128)')
    RETURN
    END


    단일 요소 지정

    단일 카디널리티 평가는 쿼리 및 데이터 수정 문에서 서수를 지정할 필요성을 제거합니다. 이로 인해 쿼리 계획이 간소화되고 효율적인 JOIN 작업이 생성됩니다. 일반적으로 단일 카디널리티 평가에는 중첩 루프 조인에서 내부 및 외부 루프에 대한 적절한 선택이 수반됩니다.

    형식화된 XML에서 기본적으로 요소는 minOccurs 및 maxOccurs의 값을 사용하여 재정의되지 않는다면 XML 스키마 구조의 단일 카디널리티를 갖습니다. 또한 형식화된 XML 열, 변수 및 매개 변수의 DOCUMENT 제약 조건은 XML 데이터 형식 인스턴스에서 정확히 하나의 최상위 요소를 보장합니다.

    형식화되지 않은 데이터의 경우 또는 스키마에 여러 형제 요소가 허용되는 경우, 아래 예제에 나타난 대로 경로 식을 만족시키는 노드를 정확하게 하나만 선택하는 서수 값을 사용하여 노드의 단일 카디널리티가 경로 식에 표시될 수 있습니다. 서수 [1]은 Transact -SQL TOP 1 오름차순을 사용하여 평가되는 반면 서수 last()는 TOP 1 내림차순으로 평가됩니다. 또한 nodes() 메서드는 결과 XML 인스턴스 각각에 대해 단일 컨텍스트 항목을 설정합니다.

    단일 노드의 선택이 생략된 경우 쿼리 최적화 프로그램이 지나치게 높을 수 있는 기본 카디널리티 평가를 사용합니다. 예를 들면, 이는 술어를 처리해야 하는 경우 중첩 루프 조인에서 내부 및 외부 루프에 대해 차선책을 선택하게끔 유발할 수 있습니다. 그 효과는 XML 인덱스가 존재하지 않고 보다 효율적인 카디널리티 평가를 위해 사용할 수 있는 통계 정보가 없는 XML blob의 경우에 더욱 크게 나타납니다.


    예제: 형식화되지 않은 XML의 단일 카디널리티 지정

    xCol 열의 각 XML 인스턴스가 <title> 하위 요소를 하나만 갖는 최상위 요소를 하나만 포함한다고 가정합시다. 다음 쿼리를 살펴봅시다.


    SELECT xCol.query ('/book/title')
    FROM docs


    쿼리 최적화 프로그램은 <title> 요소에 기본 카디널리티 평가를 사용합니다. 각 <book>은 <title>이 단일 요소가 되도록 하나의 제목을 갖지만 최적화 프로그램의 평가는 그에 비해 훨씬 더 높습니다. 다시 공식화한 다음 쿼리는


    SELECT xCol.query ('(/book/title)[1]')
    FROM docs


    올바른 카디널리티를 최적화 프로그램에 전달합니다. 비슷한 모양의 경로 식 (/a/b)[1]과 /a/b [1] 간의 의미론적 차이점이 MSDN 기사 Microsoft SQL Server 2005를 위한 최상의 XML 사용 방법에 설명되어 있습니다.


    XML 데이터 형식 메서드의 다중 실행 제거

    다음 쿼리는


    SELECT case isnumeric (xCol.value ('(/book/price)[1]', 'nvarchar(32)'))
    when 1 then xCol.value ('(/book/price)[1]', 'decimal(5,2)')
    else 0
    end
    FROM docs


    책의 <price>를 계산한 다음 가격이 숫자 형식인 경우 가격을 십진수(5, 2)로 변환합니다. 이 논리는 응용 프로그램에서 숫자가 아닌 가격 값이 발생할 수 있는 경우에 유용합니다.


    SELECT case isnumeric(Price)
    when 1 then CAST (Price AS decimal(5,2))
    else 0
    end
    FROM (SELECT xCol.value ('(/book/price)[1]', 'nvarchar(32)') Price
    FROM docs) T


    동일한 최적화가 NULLIF()와 같은 다른 곳에서도 사용될 수 있습니다.


    SELECT NULLIF (Title, '')
    FROM (SELECT xCol.value ('(/book/title)[1]', 'nvarchar(64)') Title
    FROM docs) T


    NULLIF()에서 value() 메서드를 사용하면 이 메서드가 비어 있지 않은 문자열을 반환할 경우 value() 메서드가 두 번 처리됩니다.


    Data(),text() 및 string() 접근자

    XQuery는 노드에서 형식화된 원자 값을 추출하기 위한 fn:data() 함수, 텍스트 노드를 반환하기 위한 노드 테스트 text() 및 노드의 문자열 값을 반환하기 위한 fn:string() 함수를 제공합니다. 이들의 사용은 혼동될 수 있습니다. SQL Server 2005에서 이를 올바로 사용하기 위한 지침이 XML 인스턴스 <age>12</age>를 사용하여 아래에 예시되어 있습니다.

  • 형식화되지 않은 XML: 경로 식 /age/text()는 값이 “12”인 <age> 아래에 텍스트 노드를 반환합니다. fn:data(/age) 함수는 fn:string(/age)처럼 문자열 값 “12”를 반환합니다.
  • 형식화된 XML: /age/text() 식은 SQL Server 2005에서 모든 단순한 형식화된 <age> 요소에 대한 정적 오류를 반환합니다. <age>가 단순한 정수 콘텐츠를 갖는 경우에는 fn:data(/age)가 정수 12를 반환하는 반면, fn:string(/age[1])은 문자열 “12”를 산출합니다. 이들 함수는 서로 다른 성능 특성을 갖습니다. Fn:string()은 컨텍스트 노드 아래의 모든 텍스트 노드를 재귀적으로 집계합니다. 컨텍스트 노드가 단일값인 경우 이 방식은 과도하며, 이 경우에는 fn:data() 및 text()로도 충분할 뿐만 아니라 더 효과적입니다.

    형식화되지 않은 XML의 경우 노드의 값이 필요할 때, text()를 사용하여 텍스트 노드를 반환하는 것이 fn:data()를 사용하여 반환하는 것보다 더 빠릅니다. 경로 식 /book/text()는 <book> 요소의 텍스트 노드 자식(child)을 반환합니다. query() 메서드 내에서 이러한 텍스트 노드는 직렬화되고 텍스트 노드 값의 연결로 나타납니다. 반면, fn:data()는 <book> 요소의 하위 트리에 있는 모든 값을 집계합니다. 이 집계는 간단한 콘텐츠를 가진 요소의 경우일지라도 fn:data()의 계산이 text()의 계산보다 비용이 더 많이 소요되게 만듭니다.

    형식화되지 않은 XML에서 텍스트 집계

    XQuery 의미론에 따라, 형식화되지 않은 XML에서 다음과 같은 두 쿼리는 술어를 평가하기 위해 <title> 요소 아래의 모든 텍스트 노드를 집계해야 합니다. 이 때문에 검색 문자열에 대한 XML 인덱스 조회가 억제됩니다.


    SELECT xCol.value ('(/book/title[.="Writing Secure Code"])[1]',
    'nvarchar(64)')
    FROM docs


    또는


    SELECT xCol.value ('(/book/title
    [fn:string()="Writing Secure Code"])[1]'), 'nvarchar(64)')
    FROM docs


    <title> 요소에 텍스트 노드가 하나만 있는 경우 더 효율적인 쿼리 작성 방법은 아래와 같이 텍스트 노드의 술어를 평가하는 방법입니다.


    SELECT xCol.value ('(/book/title/text())[1]
    [. = "Writing Secure Code"]', 'nvarchar(64)')
    FROM docs


    이 경우에는 "Writing Secure Code" 값에 대한 XML 인덱스 조회가 발생합니다.


    XQuery 및 XML DML 식 매개 변수화

    XQuery 및 XML DML 식은 자동으로 매개 변수화되지 않습니다. 따라서 두 XQuery 식이 매개 변수의 값만 다른 경우, 동적 SQL 문을 사용하는 대신 sql:column() 또는 sql:variable()을 사용하여 XQuery 또는 XML DML 식에 매개 변수 값을 제공하는 것이 더 좋습니다. 이들 함수를 사용하면 쿼리가 자동으로 매개 변수화됩니다.

    아래 예제는 저장 프로시저 실행을 보여줍니다. 이 기법은 쿼리, 함수/메서드 호출 또는 데이터 수정 문의 매개 변수화에 적용할 수 있습니다.

    예를 들어, 아래 저장 프로시저는 입력 인수보다 낮은 가격의 책을 찾습니다.


    CREATE PROC sp_myProc
    @Price decimal
    AS
    SELECT *
    FROM docs
    WHERE 1 = xCol.exist('(/book/price)[. < sql:variable("@Price")]')


    ADO.NET 및 OLEDB에서 @Price의 입력 값을 매개 변수에 바인딩합니다. 이렇게 하면 매개 변수가 서로 다른 값에 바인딩될 때 쿼리를 다시 컴파일할 필요가 없습니다. sql:column()을 사용하면 이와 비슷한 이점을 얻을 수 있습니다.

    다음 Visual Basic.NET 코드는 저장 프로시저 호출에서 매개 변수 바인딩을 보여줍니다.


    'myConn is the connection string
    SqlCommand cmd = New SqlCommand("sp_myProc", myConn)
    cmd.CommandType = CommandType.StoredProcedure

    'Parameter binding
    Dim myParm As SqlParameter = cmd.Parameters.Add("@Price", _
    SqlDbType.Decimal)
    myParm.Direction = ParameterDirection.Input
    myParm.value = 2

    'Invoke the stored procedure
    SqlDataReader myReader = cmd.ExecuteReader()

    'Invoke the stored procedure a second time
    myParm.value = 49.99
    SqlDataReader myReader = cmd.ExecuteReader()


    자세한 내용은 Microsoft Visual Studio.NET 설명서 (영문)를 참조하십시오.


    예제: 데이터 수정에서 sql:variable() 사용

    ISBN이 "0-2016-3361-2"인 <book>의 <price>가 10% 할인되었다고 가정합시다. 할인과 ISBN 둘 다 XML 데이터 수정 문에 매개 변수로 전달될 수 있고 이 문은 다른 책 또는 다른 할인에 대해 똑같이 유지됩니다.


    DECLARE @discountFactor decimal, @sqlisbn nvarchar(32)
    SET @discountFactor = 0.9
    SET @sqlisbn = N'0-7356-1588-2'

    UPDATE docs
    SET xCol.modify('replace value of (/book/price/text())[1] with
    sql:variable("@discountFactor")*(/book/price/text())[1]')
    WHERE xCol.exist('/book[@ISBN = sql:variable("@sqlisbn")]') = 1


    예제 : 요소 구성에서 sql:variable() 사용

    아래에 나와 있는 modify() 메서드는 구성된 요소 내에서 값을 제공하기 위한 sql:variable()의 사용을 보여줍니다.


    DECLARE @name nvarchar(64)
    SET @name = 'Microsoft Press'
    UPDATE docs
    SET xCol.modify ('
    insert < publisher Name = "{sql:variable("@name")}"></publisher>
    into (/book/title)[1]')


    술어 및 서수의 최적화

    노드 테스트 또는 분기가 없는(즉, 경로의 중간 노드에 술어 또는 서수가 없는) 전체 경로(즉, 루트 노드로부터 자식(child) 및 자신의 축만을 포함하는 선택한 노드에 이르는 절대 위치 경로)는 분기가 있는 경로 식보다 효율적으로 평가할 수 있습니다. 인덱스된 경우에 전체 경로는 인덱스 탐색에 사용될 수 있습니다. XML blob의 경우, 이러한 경로의 구문 분석은 분기 또는 와일드카드(*)가 있는 경로의 구문 분석보다 더 빠릅니다.

    경로 끝부분의 노드 테스트 및 술어는 선택한 노드에서 필터로 사용됩니다. 인덱스가 사용됩니다. XML blob의 경우 구문 분석이 효율적입니다. 아래에 예제가 나와 있습니다.


    예제: 전체 경로 평가

    이름이 Davis인 저자가 쓴 책을 선택하는 경로 식을 생각해 봅시다.


    SELECT xCol.query ('/book[author/first-name = "Davis"]')
    FROM docs


    술어가 <book> 요소에 직접 존재하지 않더라도 축소 경로 /book/author/first-name을 사용하여 위치한 <first-name> 노드는 값 "Davis"에 의해 필터링됩니다. 반환된 <book> 요소는 주어진 술어를 충족하는 것들입니다.

    경로 기반 조회는 /book//first-name과 같이 술어 또는 서수가 없는 부분적으로 지정된 경로에도 효율적입니다. 쿼리 컴파일러는 XML 인덱스에서 이러한 경로를 일치시키기 위해 LIKE 연산자를 사용합니다. 그러므로 가능한 한 경로의 많은 부분을 지정하는 것이 보다 효율적인 처리에 도움이 됩니다.

    /book[@ISBN = "1-8610-0157-6"]/author/first-name에서와 같이 분기(즉, 경로 식의 중간에 있는 노드 테스트 및 서술어)는 경로 식 /book[@ISBN = "1-8610-0157-6"] 및 /book/author/first-name을 평가하고 <book> 요소의 두 집합 사이의 교집합을 취합니다. 따라서 분기 없는 경로 식보다 실행이 느려집니다. 경로 식의 중간에 노드 테스트 및 술어를 사용하는 것을 가능한 한 피하는 것이 효과적입니다. 이는 “일반적 태그와 구체적 태그의 비교” 예제에 설명된 대로, 데이터 모델링 시 신중한 주의를 기울임으로써 가능한 경우가 종종 있습니다.


    경로의 끝으로 서수 이동

    정적 형식의 정확성을 위해 경로 식에 사용되는 서수는 경로 식의 끝부분에 넣을 수 있는 좋은 후보입니다. 경로 식 book[1]/title[1]은 (/book/title)[1]과 동일합니다. 후자는 문서 순서에서 <book> 요소 아래의 첫 번째 <title> 요소를 확인함으로써 XML 인덱스 및 XML blob 두 경우 모두에 대해 모두 더 빠르게 평가될 수 있습니다. 이와 유사하게 경로 식 (/book/@ISBN)[1]은 /book[1]/@ISBN보다 더 빠른 실행을 가져옵니다.


    컨텍스트 노드를 사용한 술어 평가

    술어, 서수 및 노드 테스트를 경로 식의 끝으로 이동하는 것 외에도 컨텍스트 노드를 사용하여 이러한 조건을 평가하면 한층 더 나은 성능을 얻을 수 있습니다. 아래에 이에 대한 쿼리 재작성 예제가 나와 있습니다.


    예제: 컨텍스트 노드를 사용한 술어 평가

    아래 쿼리는 “security”라는 제목의 책을 검색합니다. 이 쿼리에는 두 경로 식, /book 및 /book/@subject의 평가와 후자 경로에 대한 “security” 값 확인이 필요합니다.


    SELECT *
    FROM docs
    WHERE xCol.exist ('/book[@subject = "security"]') = 1


    다시 작성된 아래 쿼리는 단일 경로 /book/@subject를 평가하고 이 경로에 "security" 값이 있는지 확인합니다. 이렇게 하면 위 쿼리보다 쿼리 계획이 더 단순해지고 실행이 훨씬 더 빨라집니다.


    SELECT *
    FROM docs
    WHERE xCol.exist ('/book/@subject[. = "security"]') = 1


    범위 조건

    범위 조건은 형식화된 XML의 사용을 통해 이점을 얻습니다. XML 열 및 XML 인덱스에 저장된 데이터는 XML 스키마에 지정된 형식 정의에 따라 형식화됩니다. 값 비교는 데이터의 런타임 변환을 피하고 VALUE 보조 XML 인덱스에 대한 범위 스캔을 허용합니다. 또한 이를 위해서는 다음 예제에 나타난 대로, 효율적인 액세스를 위해 범위 조건에 컨텍스트 노드(.)를 지정해야 합니다.


    예제: 범위 조건의 컨텍스트 노드

    $9.99와 $49.99 범위에 있는 가격대의 책을 찾는 쿼리를 고려해 봅시다.


    SELECT xCol
    FROM docs
    WHERE xCol.exist ('/book[price > 9.99 and price < 49.99]') = 1


    경로 식 /book/price > 9.99 및 /book/price < 49.99가 각각 따로 평가됩니다. <book> 요소 아래에 여러 <price> 요소가 존재할 수 있기 때문에 쿼리 최적화 프로그램은 <price> 요소가 동일하다는 사실을 알지 못합니다. 이 때문에 VALUE 보조 XML 인덱스에 대한 범위 스캔이 억제됩니다. 아래에 다시 작성된 쿼리는 <price>에 동일한 컨텍스트 노드를 사용하고 9.99와 49.99 사이의 값에 대해 VALUE 보조 XML 인덱스의 범위 스캔이 발생하도록 보장합니다. 이로 인해 성능이 더 좋아집니다.


    SELECT xCol
    FROM docs
    WHERE xCol.exist ('/book/price[. > 9.99 and . < 49.99]') = 1


    동적 쿼리

    XQuery 식은 XML 데이터 형식 메서드 내에서 리터럴로 지정됩니다. 이들의 평가는 사용 가능한 경우 쿼리 최적화 프로그램에서 선택한 XML 인덱스를 사용합니다.

    XQuery 식을 리터럴 대신 동적으로 지정할 수 있으면 응용 프로그램 개발이 편리합니다. 이는 다음 방식으로 가능합니다.

    쿼리 구성
    쿼리를 문자열로 작성하고 sp_executesql을 사용하여 실행합니다. EXEC와 달리, 이렇게 하면 컴파일된 쿼리 계획이 캐시되어 최적화 프로그램이 컴파일된 계획을 다시 사용할 수 있습니다. 쿼리는 문자열로 구성되므로 매개 변수화될 수 있고 포함된 매개 변수를 포함할 수 있습니다. SQL 주입 공격을 피하려면 충분한 주의를 기울여야 합니다.

    XPath 함수 사용
    XPath 식의 각 위치 단계를 name() 함수 또는 local-name() 및 namespace-URI() 함수로 대체합니다. 이렇게 하면 노드 이름 및 검색 값으로 전달할 수 있는 쿼리가 만들어집니다. "XQuery 또는 XML DML 식 매개 변수화" 예제에 설명된 대로 추가적으로 매개 변수화할 수 있습니다. 이와 같은 매개 변수화된 쿼리는 응용 프로그램 개발에 편리합니다. 하지만 컴파일 시에 구체적인 경로가 알려지지 않으므로, 이에 대해 생성된 쿼리 계획은 XML 인덱스를 무시합니다.

    쿼리 구성 접근 방법은 경로 식 매개 변수화보다 더 능률적으로 작동하지만 런타임 쿼리 컴파일 비용이 들기 때문에, 전체 쿼리를 리터럴로 지정하는 것보다 더 느려집니다. 사용자가 전달한 실제 쿼리는 SQL 주입 공격을 피하기 위해 유효성이 검사되어야 합니다. 그렇지 않으면, 쿼리의 매개 변수화(이 문서의 “XQuery 및 XML DML 식 매개 변수화")를 위해 이 접근 방법을 사용하지 말아야 합니다. 다음 예제는 이 접근 방법을 예시합니다.

    노드 이름을 사용하여 노드 테스트를 지정하는 두 번째 접근 방법은 SQL 주입 문제를 방지합니다. 하지만 쿼리 계획이 복잡해지고 원래 쿼리보다 훨씬 더 비능률적으로 수행됩니다. 이 접근 방법은 두 번째 예제에 나와 있습니다.


    예제: sp_executesql를 사용한 쿼리

    다음 쿼리를 동적으로 작성하여 매개 변수를 사용하여 @subject의 검색 값을 전달하기를 원한다고 가정합시다.


    SELECT *
    FROM docs
    WHERE xCol.exist('/book[@subject = "security"]') = 1


    동적 쿼리를 아래에 나타난 대로 작성하고 실행할 수 있습니다. 쿼리 문자열은 @SQLString 변수에 만들어지고 exist() 메서드에서 사용된 포함된 변수 @bksubj를 포함합니다. @subj 변수는 매개 변수의 런타임 값을 제공합니다. @SQLString을 사용하여 전달된 동적 쿼리는 SQL 주입 공격을 피하기 위해 유효성이 검사되어야 합니다(아래에는 표시되어 있지 않습니다).


    DECLARE @SQLString NVARCHAR(500)
    DECLARE @subj NVARCHAR(64)
    DECLARE @ParmDefinition NVARCHAR(500)
    --- Build the SQL string once
    SET @SQLString =
    N'SELECT *
    FROM docs
    WHERE xCol.exist(''/book[@subject=sql:variable("@bksubj")]'')=1'
    SET @ParmDefinition = N'@bksubj NVARCHAR(64)'
    --- Execute the string with the first parameter value
    SET @subj = 'security'
    EXECUTE sp_executesql @SQLString, @ParmDefinition,
    @bksubj = @subj


    예제: local-name()을 사용한 쿼리

    위 쿼리를 다음과 같이 태그 이름을 리터럴로 사용하도록 다시 작성할 수 있습니다.


    DECLARE @elemName nvarchar(4000), @attrName nvarchar(4000)
    DECLARE @subjValue nvarchar(4000)
    SET @elemName = N'book'
    SET @attrName = N'subject'
    SET @subjValue = N'security'
    SELECT *
    FROM docs
    WHERE xCol.exist('/*[local-name() = sql:variable("@elemName") and
    @*[local-name() = sql:variable("@attrName") and
    . = sql:variable("@subjValue")]]') = 1


    다시 작성된 쿼리는 와일드카드(*)와 노드 이름을 사용하는 노드 테스트를 포함하므로 효과적으로 최적화하기가 어렵습니다. 결과적으로 원래 쿼리 및 쿼리 구성 접근 방법에 비해 훨씬 더 비능률적으로 수행됩니다.


    XML 데이터에서 행 집합 생성

    일부 응용 프로그램은 하나 이상의 속성을 행 집합의 열로 승격함으로써 XML 데이터에서 행 집합을 생성해야 합니다. 예를 들어, 응용 프로그램은 책의 저자를 쿼리하고 성 및 이름에 대해 두 개의 열을 포함하는 테이블로 결과를 표시할 수 있습니다. 이러한 행 집합 생성은 서로 다른 성능 특성을 지닌 서버 또는 클라이언트에서 모두 수행될 수 있습니다.

  • 서버에서 다음 메커니즘 중 하나를 사용하십시오.
    • XML 데이터 형식의 nodes() 및 value() 메서드의 결합
    • OpenXML
    • CLR(공용 언어 런타임)에서 테이블 반환 함수 스트리밍
  • 또한 XML 결과가, 클라이언트 쪽 프로그래밍(예: DataSet)을 사용하여 데이터를 행 집합으로 변환하는 클라이언트에게 반환됩니다. 클라이언트 쪽 행 집합 생성은 서버의 부하를 덜어주므로 서버에서 클라이언트로 전송된 거의 전체 데이터가 행 집합으로 매핑되는 경우에 유용합니다. 그렇지 않은 경우에는 데이터 제공 비용이 클라이언트 쪽 처리 이점보다 더 클 수 있습니다.

    서버 쪽 행 집합 생성은 서버에서 들어오는 XML 데이터로부터의 행 집합 생성에 유용합니다. 이 방식은 서버에 저장된 XML 데이터의 일부분만이 행 집합의 열로 승격되는 경우에 일반적으로 더 바람직합니다. 서버 쪽 접근 방법들의 상대적 장점 및 단점에 관한 자세한 설명은 MSDN 기사 Microsoft SQL Server 2005를 위한 최상의 XML 사용 방법에서 찾을 수 있습니다.


    제공 : DB포탈사이트 DBguide.net
  • + Recent posts