 |  |
|
난이도 : 중급 Vitor Rodrigues, DB2 pureXML 기술전도사,
IBM
2008 년 3 월 11 일 XMLTABLE은 SQL/XML 표준에서 가장 강력한 기능 중 하나며 z/OS®용 DB2 9뿐만 아니라 Linux®, Unix®, Windows®용 IBM® DB2® 9에서도 사용할 수 있습니다. 본 연재의 part 1에서는 관계형 포맷에서 XMLTABLE을 사용하여 XML 데이터를 찾아오는 방법, 반복 및 없어진 XML 요소를 처리하는 방법, XMLTABLE 기능의 이름 공간을 처리하는 방법을 다뤘습니다. Part 2에서는 일반적인 XMLTABLE을 사용해 XML을 분할하여(shredding) 관계형 테이블에 넣는 예제, 대형 문서를 작은 문서로 나누는 예제, XML 문서의 하이브리드 XML 관계형 저장소를 생성하는 예제, XML 데이터를 통해 관계형 뷰를 사용하는 예제 등을 시나리오 형태로 설명합니다. 이들 기술과 샘플은 DB2 9 pureXML로 강력한 XML 애플리케이션을 개발하는 데 도움이 될 것입니다.
샘플 데이터
이 글에서는 XMLTABLE 시나리오를 설명하기 위해 Part 1에서 사용한 것과 같은 샘플 테이블과 데이터를 사용하겠다. 테이블에는 XML 행 하나와 각각에 XML 문서를 갖는 열 두 개가 있다. 첫 번째 문서는 department 한 개와 employee 두 개를, 두 번째 문서는 department 한 개와 employee 한 개를 기술한다.
테이블 1. 샘플 테이블과 데이터
| create table emp (doc XML); |
<dept bldg="101">
<employee id="901">
<name>
<first>John</first>
<last>Doe</last>
</name>
<office>344</office>
<salary currency="USD">55000</salary>
</employee>
<employee id="902">
<name>
<first>Peter</first>
<last>Pan</last>
</name>
<office>216</office>
<phone>905-416-5004</phone>
</employee>
</dept>
|
|
<dept bldg="114">
<employee id="903">
<name>
<first>Mary</first>
<last>Jones</last>
</name>
<office>415</office>
<phone>905-403-6112</phone>
<phone>647-504-4546</phone>
<salary currency="USD">64000</salary>
</employee>
</dept>
|
|
XMLTABLE은 관계형 포맷에서 XML 데이터를 반환하는 기본 사용 외에 다양한 목적으로 사용될 수 있다.
큰 XML 문서를 작은 문서로 나누기
프로그래머들은 대부분 애플리케이션의 논리적인 비즈니스 객체와 우수한 접근성과 맞물리는 작은 XML 문서가 더 효율적이고 편하다는 것을 알고 있다. 예를 들어 P/O 당, 거래 당, 계약서 당, 연말정산 당, 고객 당 문서 하나로 정리되는 것이 더 좋다. 특히 XML 디자인과 저작 도구의 경우 큰 문서보다 작은 문서를 조작하기가 더 쉽다. 또한 인덱스된 접근과 데이터 찾아오기도 작은 문서가 더 빠르다.
하지만 FTP처럼 데이터베이스 밖에서 XML 데이터를 묶어 전송하는 경우 많은 수의 문서를 처리하는 것이 더 불편할 수 있다. 그러므로 독립 개체를 나타내는 많은 반복되는 블록을 포함하는 큰 XML 문서(그 중에는 파일 하나당 몇 백MB에 해당하는 것도 있다)를 받는 것이 일반적이다. 일반적으로 DOM 파싱이나 메모리 제한 때문에 이런 큰 XML 문서를 열 때 많은 외부 도구가 실패하거나 심각한 문제를 일으킨다.
DB2는 2GB까지 XML 문서를 소화할 수 있다. 또는 XMLTABLE 기능을 사용해 작은 문서로 나눌 수 있다. 예를 들어 문서 당 1개 이상의 employee가 들어간 테이블 1(employee 데이터가 department에 의해 취합된)을 사용하자. 질의 1은 INSERT 문에 끼워져 있고 department 문서에서 각 employee를 추출한다. 각 employee는 나눠진 열에 각각 나눠진 XML이 들어가듯 employee 테이블에 삽입된다.
질의 1. XMLTABLE을 사용해 문서를 작은 문서로 나누기
create table employee(doc XML)
INSERT INTO employee
SELECT X.* FROM
XMLTABLE ('$d/dept/employee' passing cast(? As XML) as "d"
COLUMNS
doc XML PATH 'document{.}') AS X
|
위 질의의 XMLTABLE 기능은 employee 당 한 열과 XML 유형의 한 행을 생산한다. passing 절의 "?"는 구문의 입력처럼 XML 문서를 제공하는 매개변수 마커를 나타낸다. cast (? as XML)는 XML을 삽입하기 위해 매개변수 마커를 던지는 데 쓰인다. 매개변수 마커를 사용하는 대신 본래의 XML 문서를 구문의 입력으로도 사용할 수 있다. 하지만 대개 매우 작은 문서에는 불편하고 비실용적이다. 매개변수 마커가 더 낫다.
XML 데이터 모델은 하나의 문서 노드(문서의 단일 루트 요소의 부모)를 갖기 위해 분석되고 형식을 잘 갖춘 XML 문서를 요구한다. 이 문서 노드는 XML 문서의 원래(연속적) 표현에서는 보이지 않는다. 입력 문서에서 추출한 employee 하위 트리는 문서 노드를 가지고 있지 않으므로 형식을 잘 갖춘 문서로 삽입될 수 없다. 그러므로 document{} 생성자는 추출된 각 employee에 문서 노드를 만든다.
XML 문서를 관계형 데이터로 분해하기
INSERT 문에서 XMLTABLE 질의를 사용하는 것은 XML 데이터를 관계형 테이블에 분해하거나 분할하는 또 다른 편리한 방법이다. 예를 들어 XML은 가끔 메시지 포맷으로만 사용되고 메시지를 받게 되면 더 이상 유지될 필요가 없다. XML을 포함한 메시지는 기존 관계형 테이블과 쉽게 매핑되어 SQL 애플리케이션에 피드된다. 그렇게 되면 XML을 관계형으로 분할하는 것이 올바른 접근이 된다. 하지만 복잡 다양한 XML 스키마 시나리오에서는 이 방식이 더 어려우므로 pureXML 저장소가 분할보다 더 나은 옵션이다.
이전 예를 따르자면 질의 2는 XMLTABLE로 employee 데이터를 분할하여 employee 당 열 하나와 employeeRel이라는 새 관계형 테이블에 넣는 방법을 보여준다.
질의 2. XMLTABLE을 사용해 XML 데이터를 분해해 관계형 포맷에 넣기
create table employeeRel(bldg integer, id integer, fname varchar(15),
lname varchar(15), office integer)
INSERT INTO employeeRel
SELECT X.* FROM
XMLTABLE ('$d/dept/employee' passing cast (? as XML) as "d"
COLUMNS
building INTEGER PATH '../@bldg'
empID INTEGER PATH '@id',
firstname VARCHAR(15) PATH 'name/first',
lastname VARCHAR(15) PATH 'name/last',
office INTEGER PATH 'office') AS X
|
이 시나리오에서는 문서의 요소 부분집합만 분할한다. phone과 salary 요소는 분할되지 않았지만 쉽게 추가할 수 있다. 지금은 employeeRel 테이블에서 SELECT 문이 다음 결과를 반환한다.
BLDG ID FNAME LNAME OFFICE
----- ------ -------------------- ------------------- -----
101 901 John Doe 344
101 902 Peter Pan 216
114 903 Mary Jones 415
3 record(s) selected.
|
또한 기존 XML 행에서 XML 문서를 분할할 수 있다. 질의 2에서 매개변수 마커 대신 행 이름을 열-생성식으로(본 연재 part 1의 대다수의 질의와 아래 질의 5에서 보는 것처럼) 간단히 전달한다.
하이브리드 접근: XML과 관계형
어떤 경우에는 관계형 포맷과 XML 포맷에 각각 데이터를 넣어야 할 때가 있다. 시간에 따라 변하지 않는, 구조화되고 고정된 데이터 아이템의 경우 관계형 행이 좋은 선택이 될 것이다. 데이터의 다른 부분은 약간 구조화되거나 다양하거나 본질적으로 계층적이므로 XML 행에 저장되는 것이 좋다. 입력 시간에 이런 하이브리드로 접근하는 일반적인 방법은 XML 문서에서 선택된 요소나 속성을 추출하고 이를 문서 전체를 입력하는 열과 같은 관계형 행에 넣는 것이다. 이렇게 되면 관계형 행에서 다중 행 인덱스(합성함수 키), 참조 무결성 제약(referential integrity constraints)이나 트리거를 정의할 수 있다. 이들 개념이 XML 행에만 있는 게 아니기 때문이다.
테이블에서 XML 행과 관계형 행을 파퓰레이트하는 데는 다양한 방법이 있다. 애플리케이션에서 값 추출을 할 수 있고 이를 XML 문서 모두에 피드하고 추출된 값을 SQL INSERT 문에 넣을 수 있다. 그러나 INSERT 문에서 XMLTABLE만 사용하는 것이 더 쉽고 간단하다. 이렇게 하면 애플리케이션에서 XML이 분석되는 것을 막을 수 있고 INSERT 문의 로직을 지킬 수 있다. 이후 변경이 필요하다면 애플리케이션 코드를 고치는 대신 이 구문(저장된 프로시저에서 캡슐화될 수 있는)만 고치면 된다.
질의 3은 테이블 1의 department 문서가 bldg 속성 추출과 함께 INTEGER 타입의 분리된 행에 삽입될 수 있는 방법을 보여준다. 여기서 열-생성식 $d는 그 어떤 탐색, 즉 XPath 단계를 포함하지 않음에 주의하자. 즉, COLUMNS 절의 컨텍스트는 문서 노드를 항상 포함하는 완벽한 문서라는 것을 의미한다.
질의 3. 관계형 행에 XML 데이터를 삽입하고 속성 하나를 추출하기
create table hybridDept(bldg integer, doc XML);
INSERT INTO emp1
SELECT X.* FROM
XMLTABLE ('$d' passing cast(? as XML) as "d"
COLUMNS
building INTEGER PATH ' @bldg',
doc XML PATH '.'
) AS X
|
질의 4는 관계형 행에 질의 3의 것과 같은 문서를 삽입하지만 employee ID, name, office number를 추출한다. 이는 department 문서를 분할하고 employee 당 XML 문서 하나와 열 하나를 생산한다. 새 문서는 입력 문서의 조각이므로 문서 노드를 생성해야 한다.
질의 4. 관계형 행에 XML 데이터를 삽입하고 다중 요소 저장하기
create table hybridEmp(id integer, fname varchar(25),
lname varchar(25), doc XML);
INSERT INTO emp1
SELECT X.* FROM
XMLTABLE ('$d/dept/employee' passing cast(? as XML) as "d"
COLUMNS
id INTEGER PATH ' @id',
first VARCHAR(25) PATH 'name/first',
last VARCHAR(25) PATH 'name/last',
doc XML PATH 'document{.}'
) AS X
|
XML 데이터를 통해 관계형 뷰 만들기
앞 부분에서 XMLTABLE을 사용해 XML 데이터를 관계형 테이블로 분할하거나 XML 데이터의 하이브리드 표현을 생산하는 방법을 다뤘다. 같은 XMLTABLE 식이 뷰 정의에 끼워질 수 있다. 이렇게 하면 XML 데이터의 관계형이나 하이브리드 뷰를 가진 애플리케이션을 갖게 되는데 이 때 각각의 포맷에는 실제 데이터가 저장되지 않는다.
질의 5는 뷰 정의에 끼워져 있고 관계형 포맷의 doc 행에서 XML 요소 및 속성의 부분집합을 보여준다. 실제 기본 데이터는 XML 포맷에 있음에도 애플리케이션은 이 뷰를 사용해 전통적 방식의 SQL 문으로 데이터를 질의할 수 있다.
질의 5. 관계형 포맷에서 뷰를 사용해 XML 데이터 보여주기
CREATE VIEW emp_rel (id, first_name ,last_name ,office)
AS
SELECT X.* FROM emp,
XMLTABLE ('$d/dept/employee' passing doc as "d"
COLUMNS
empID INTEGER PATH '@id',
firstname VARCHAR(5) PATH 'name/first',
lastname VARCHAR(5) PATH 'name/last',
office INTEGER PATH 'office') AS X
|
관계형 뷰에 익숙하다면 뷰 이름과 행을 정의하는 구문의 첫 번째 행을 쉽게 알아볼 수 있을 것이다. AS 절의 질의식은 뷰의 내용을 정의한다. 이 예에서 XMLTABLE은 XML 데이터의 각 employee 당 하나의 열을 생산한다. 각 열은 employee ID, first name, last name, office number를 각각 포함하는 네 개의 관계형 행으로 이뤄져 있다.
질의 6은 뷰에 대한 간단한 SQL 문(XML 확장 없이)을 실행하여 office 344의 employee ID와 이름을 얻는 방법을 보여준다.
질의 6. SQL을 사용해 XMLTABLE 뷰 질의하기
select id, first_name from emp_rel where office = 344;
ID FIRST_NAME
----------- ----------
901 John
1 record(s) selected.
|
XMLTABLE 뷰에 대해 이런 SQL 질의와 SQL 술어(predicate)를 실행할 때 DB2는 뷰의 모든 관계형 열을 생성한 후 SQL 술어를 평가함에 주의하자. 즉, XMLTABLE 기능은 SQL 질의가 하나의 특정 문서에서 가져온 데이터만을 원함에도 기본 테이블의 모든 문서에 적용된다는 의미다. 이렇게 되면 성능에 큰 타격을 입는다.
특히 DB2는 XML 인덱스를 사용해 SQL 술어를 평가하지 않는다. 술어는 기본 테이블에서가 아니라 뷰의 관계형 행에서 표현되기 때문이다. 즉, 보편적으로 데이터베이스 시스템에 직접 전달되지 않고 관계형 술어를 XML 술어로 변환한다는 뜻이다. 다음 절에서는 이 제한을 해결하면서 성능을 유지하는 방법에 대해 설명하겠다.
XMLTABLE 뷰에서의 성능 고찰
XMLTABLE 뷰를 통한 훌륭한 런타임 성능의 질의를 갖는 방법은 제대로 된 인덱스를 사용해 XMLTABLE 기능에 입력하는 XML 문서 수를 줄이는 것이다. 다음 두 방법으로 이를 실행할 수 있다.
- XML 술어와 XML 인덱스 사용하기
- 관계형 행과 인덱스에서 관계형 술어 사용하기
질의 6은 결과적으로 기본 XML 데이터의 요소인 office를 술어로 가짐에 따라, 기본 XML 행을 위해 /dept/employee/office에 인덱스를 만들어 질의 속도를 높이고자 할 것이다. 질의는 술어를 XML 술어로 나타내지 않는 한 이 인덱스를 사용하지 않는다. 그러므로 질의 7에서 볼 수 있는 것처럼 XML 행은 뷰 정의에 포함돼야 한다.
질의 7. XMLTABLE 뷰에 XML 행 포함하기
CREATE VIEW emp_rel (id, first_name ,last_name ,office, doc)
AS
SELECT X.* FROM emp,
XMLTABLE ('$d/dept/employee' passing doc as "d"
COLUMNS
empID INTEGER PATH '@id',
firstname VARCHAR(5) PATH 'name/first',
lastname VARCHAR(5) PATH 'name/last',
office INTEGER PATH 'office'
doc XML PATH 'document{.}'
) AS X
|
그리고 나서 질의 6과 XML 인덱스를 사용할 수 있는 XML 술어를 나타내 확실히 성능을 향상시킬 수 있다. 이는 질의 8에서 볼 수 있다. XML 술어가 사용됐지만 SELECT 목록은 여전히 관계형 뷰 행만을 참조해 관계형 포맷에서 질의 결과를 반환한다.
질의 8. XMLTABLE 뷰와 XML 술어 질의하기
select id, first_name from emp_rel
where xmlexists('$d/employee/[office = 344]' passing doc as "d")
ID FIRST_NAME
----------- ----------
901 John
1 record(s) selected.
|
기본 테이블이 관계형 행과 XML 행을 가지고 있다면(실제로 흔히 있는 일이다) XMLTABLE 뷰에 대항해 질의 속도를 높일 수 있다. 이런 경우 뷰 정의에 이들 추가 관계형 행을 포함시켜야 한다. 질의 9에서 deptID와 unit 행이 뷰에 포함됐다.
질의 9. XMLTABLE 뷰에 관계형 행 포함하기
CREATE TABLE emp(deptId integer, unit char(20), doc XML)
CREATE VIEW emp_rel (deptId, unit, empid, first_name ,last_name ,office)
AS
SELECT E.deptId, E.unit, X.*
FROM emp E,
XMLTABLE ('$d/dept/employee' passing doc as "d"
COLUMNS
empID INTEGER PATH '@id',
firstname VARCHAR(5) PATH 'name/first',
lastname VARCHAR(5) PATH 'name/last',
office INTEGER PATH 'office'
) AS X
|
deptID나 unit, 또는 둘 모두에서 employee 정보에 대한 질의가 술어를 포함할 가능성이 높다. 이들 술어가 충분히 선택적이라면 XMLTABLE 처리에 드는 비용이 확연히 줄 것이다. 질의 10에서 deptID의 술어가 추가됐다. DB2는 먼저 이 술어를 평가하여 XMLTABLE 기능이 department 9473의 employees에만 적용될 수 있도록 한다. 테이블 전체 크기에 비교하면 이는 매우 작은 부분이다. 이들 가운데 두 번째 술어가 office 344의 employee를 빨리 찾는다.
질의 10. 관계형 술어와 XMLTABLE 뷰 질의하기
select id, first_name from emp_rel
where deptID = 9473 and office = 344
ID FIRST_NAME
----------- ----------
901 John
1 record(s) selected.
|
문서에 생산된 열의 수
가끔 주어진 문서에 XMLTABLE이 생성하는 열의 수를 세는 행을 생성하고 싶을 것이다. 이렇게 하면 각 문서에 나타나는 값의 순서를 애플리케이션이 기억하는 데 도움이 된다. 이는 DB2 9.5에서 지원되는 "for ordinality" 절로 가능하다. 질의 11은 이 기능을 보여준다. XMLTABLE 기능에 입력되는 각 문서는 1부터 시작된다는 것을 기억하자.
질의 11. XMLTABLE 질의와 "for ordinality"에 의해 생산된 연속 수
SELECT X.*
FROM emp,
XMLTABLE ('$d/dept/employee' passing doc as "d"
COLUMNS
seqno for ordinality,
empID INTEGER PATH '@id',
firstname VARCHAR(20) PATH 'name/first',
lastname VARCHAR(25) PATH 'name/last') AS X
|
DB2에서 이 질의를 실행하면 다음 결과를 반환한다.
seqno empID firstname lastname
------- ----------- -------------------- -------------------------
1 901 John Doe
2 902 Peter Pan
1 903 Mary Jones
|
필드/값 짝 목록
또 다른 실생활의 XML 애플리케이션이 요구하는 것은 주어진 XML 문서에 존재하는 모든 필드/값 짝 목록이다. 이 때 구조나 속성 및 요소 이름을 추정하지 않아야 한다. 이는 XMLTABLE 기능으로 가능하다.
두 개의 행(tagname, value)을 포함하는 관계형 테이블을 생산하려면 XML 문서의 모든 요소와 속성을 살펴봐야 하고 각 요소 및 속성의 이름과 값을 추출해야 한다. 질의 12는 XML 데이터에서 모든 속성/값과 요소/값 짝을 반환하는 일반적인 방법을 보여준다. 이 일반적 질의는 더 특정한 필요성에 맞게 수정될 수 있다.
질의 12의 열-생성식인 $d//(*, @*)에 유의하자. 더블 슬래시(//)는 모든 레벨의 XML 문서를 재귀적으로 살핀다. $d//*나 $d//@* 같은 식은 모든 요소나 모든 속성을 각각 반환하지만 두 가지를 합쳐 연속적으로 반환하진 않는다. $d//(*, @*) 식은 모든 요소와 속성을 반환한다.
질의 12. 모든 속성과 요소를 값과 함께 나열하기
SELECT X.* FROM emp,
XMLTABLE ('$d//(*, @*)' passing doc as "d"
COLUMNS
tagname VARCHAR(20) PATH 'name()',
value VARCHAR(60) PATH 'data(.)'
) AS X
|
XML 데이터의 각 노드를 위해 질의 12는 관계형 열과 노드의 이름 및 값을 반환한다. XML 데이터 모델은 리프(leaf)가 아닌 노드 값이 모든 자손 텍스트 노드의 연속이라는 것을 정의한다. 이는 질의 12의 결과에서 볼 수 있다.
TAGNAME VALUE
-------------------- -----------------------------------------------
dept JohnDoe34455000PeterPan216905-416-5004
bldg 101
employee JohnDoe34455000
id 901
name JohnDoe
first John
last Doe
office 344
salary 55000
currency USD
employee PeterPan216905-416-5004
id 902
name PeterPan
first Peter
last Pan
office 216
phone 905-416-5004
dept MaryJones415905-403-6112647-504-454664000
bldg 114
employee MaryJones415905-403-6112647-504-454664000
id 903
name MaryJones
first Mary
last Jones
office 415
phone 905-403-6112
phone 647-504-4546
salary 64000
currency USD
29 record(s) selected.
|
연속 값은 매우 유용하지도 않고 다른 엔트리로 충분하므로 더 현명한 식으로 COLUMNS 절을 작성하여 더 정돈된 결과 세트를 생산할 수 있다.
질의 13. 문서의 모든 XML 노드에 모든 이름-유형-값 세 쌍 나열하기
SELECT X.* FROM emp ,
XMLTABLE ('$d//(*, @*)' passing doc as "d"
COLUMNS
tagname VARCHAR(16) PATH 'name()',
type VARCHAR(12) PATH 'let $i := (if (self::element())
then (if (./*) then (''ELEMENT'') else (''LEAF-ELEMENT''))
else (''ATTRIBUTE'')) return $i',
value VARCHAR(16) PATH '( .[self::element()]/text(),
.[self::attribute()]/data(.) )'
) AS X
|
질의 12와 질의 13의 차이는 행 vaule를 위한 새 행-생성식과 새 행으로 지정된 type이다. 열-생성식이 어떤 XQuery식이 될 수 있는 것처럼 행-생성식에서도 이들이 각각 부여된 SQL 데이터 유형을 던질 수 있는 스칼라 값을 반환하는 한 똑같이 적용된다.
이제는 vale 행에서 자손 텍스트 노드 연결 없이도 각 요소의 즉각적 텍스트 노드 자식만을 반환한다. 이는 text() 함수에 의해 가능하다. 속성 값이 분리된 텍스트 노드에 있지 않기 때문에 attribute 노드에서 text 대신 data() 함수를 사용한다. 본 글에서는 요소 노드에 data() 함수를 사용하지 않는데 이것이 요소의 자손 텍스트 노드도 반환하기 때문이다. (.[self::element()]/text(),.[self::attribute()]/data(.)) 절은 이를 위해 쓰인다. 현재 노드가 요소라면 텍스트 노드는 text() 함수를 사용해 반환된다. 현재 노드가 attribute라면 값을 반환하는 데 data() 함수가 쓰인다.
질의 13에 소개된 질의 12와의 또 다른 차이는 새 행 type이다. 행에서 현재 노드의 유형을 반환한다(즉 데이터 유형이 아닌 노드 종류다). 요소, 리프 요소, 속성이라는 세 가지 유형을 생각하자. 이들 세 개 유형은 기본적으로 다음 규칙을 기반으로 구별된다.
- 노드가 element() 유형이며 자식 노드를 가진다면(
./*는 참이 된다) ELEMENT 유형이다.
- 노드가 element() 유형이며 자식 노드가 없다면(
./*는 거짓이 된다) LEAF-ELEMENT다.
- 나머지 경우 노드는 ATTRIBUTE 유형이다.
이들 규칙만이 올바른 이유는 XML 문서에 다른 노드 유형이 없기 때문임에 유의하자. XML 데이터에 주석이나 프로세싱 안내가 있다면 위 규칙은 확장해야 한다.
질의 13을 실행하면 문서에 모든 XML 노드의 이름-유형-값 세 쌍을 포함하는 관계형 테이블을 결과로 얻는다.
TAGNAME TYPE VALUE
---------------- ---------------- ------------
dept ELEMENT -
bldg ATTRIBUTE 101
employee ELEMENT -
id ATTRIBUTE 901
name ELEMENT -
first LEAF-ELEMENT John
last LEAF-ELEMENT Doe
office LEAF-ELEMENT 344
salary LEAF-ELEMENT 55000
currency ATTRIBUTE USD
employee ELEMENT -
id ATTRIBUTE 902
name ELEMENT -
first LEAF-ELEMENT Peter
last LEAF-ELEMENT Pan
office LEAF-ELEMENT 216
phone LEAF-ELEMENT 905-416-5004
dept ELEMENT -
bldg ATTRIBUTE 114
employee ELEMENT -
id ATTRIBUTE 903
name ELEMENT -
first LEAF-ELEMENT Mary
last LEAF-ELEMENT Jones
office LEAF-ELEMENT 415
phone LEAF-ELEMENT 905-403-6112
phone LEAF-ELEMENT 647-504-4546
salary LEAF-ELEMENT 64000
currency ATTRIBUTE USD
29 record(s) selected.
|
질의 13에서 나온 결과의 유형 행으로 XML 문서의 각 종류에 몇 개의 노드가 있는지도 셀 수 있다. 이는 XMLTABLE 결과가 관계형 테이블이고 어떤 SQL 기능에도 삽입될 수 있기 때문에 가능하다. count()와 group by 절을 질의 13에 추가해 다음 질의를 할 수 있다.
질의 14. 각 유형의 XML 노드의 전체 수 세기
SELECT X."type", count(X."tagname") as count FROM test ,
XMLTABLE ('$d//(*, @*)' passing doc as "d"
COLUMNS
"tagname" VARCHAR(20) PATH 'name()',
"type" VARCHAR(22) PATH '(if (self::element())
then (if (./*) then (''NON-LEAF ELEMENT'') else (''LEAF-ELEMENT''))
else (''ATTRIBUTE''))',
"value" VARCHAR(12) PATH '(.[self::element()]/text(),.[self::attribute()]/data(.))'
) AS X group by X."type"
|
질의 14는 다음 요약 테이블을 생성할 것이다.
type COUNT
------------ -----------
ATTRIBUTE 7
NON-LEAF ELEMENT 8
LEAF-ELEMENT 14
3 record(s) selected.
|
이렇게 하면 데이터베이스에 저장된 XML 문서에 관한 자세한 통계를 쉽게 얻을 수 있다. XMLTABLE의 맨 위에서 SQL count()와 group by 절을 사용했던 것처럼 어떤 SQL 기능이라도 XMLTABLE이 생산하는 열 세트에 적용할 수 있다. 예를 들어 SQL order by 절을 사용해 XMLTABLE 기능의 결과를 정렬한다.
Summary
XMLTABLE 기능은 SELECT 문과 INSERT 문에서 XML 데이터를 처리하는 매우 유용한 도구다. 본 글을 통해 큰 XML 문서를 작은 문서로 나누기 위해, 간단한 XML 분할을 실행하기 위해, 또는 XML 데이터의 하이브리드 표현을 생산하기 위해 XMLTABLE을 어떻게 배치하는지 봤다. 본 XMLTABLE 연재에는 애플리케이션 개발에 템플릿으로 사용할 수 있는 다양한 SQL/XML문 샘플이 수록돼 있다.
감사의 글
본 글을 검토하고 유용한 의견을 나눠준 Cindy Saracco에게 감사한다.
참고자료 교육
- "XMLTABLE 예제, Part 1: 관계형 포맷으로 XML 데이터 가져오기 (한글)"(한국 developerWorks, 2007년 10월): 관계형 포맷에서 XMLTABLE을 사용해 XML 데이터를 찾아오는 방법을 배우자. 반복적이거나 빠진 XML 요소를 처리하는 방법과 XMLTABLE 기능에서 이름공간을 처리하는 방법을 찾아보자.
- "Native XML Support in DB2 Universal Database": 이 중요한 주제에 대해 더 배워보자.
- "SQL을 이용한 DB2 XML 데이터 쿼리 (한글)"(한국 developerWorks, 2006년 12월): SQL/XML을 사용해 XML 행에 저장된 데이터 질의하기
- "XQuery를 이용한 DB2 XML 데이터 쿼리 (한글)"(한국 developerWorks, 2007년 1월): XQuery를 사용해 XML 행에 저장된 데이터 질의하기
- "Querying XML data with namespaces"(developerWorks, 2006년 11월): 몇 가지 일반적인 시나리오를 통해 이름공간을 갖는 XML 데이터를 질의하는 방법을 배우자.
- "DB2 9의 pureXML: XML 데이터를 쿼리하는 방법은?"(developerWorks, 2006년 6월): XML 데이터를 질의하는 더 많은 예와 지침을 찾아보자.
-
DB2 pureXML Enablement Wiki: 풍부한 pureXML 자료를 찾아보자.
-
developerWorks Information Management 존: DB2에 대해 더 배워보자. 기술 문서, 실습, 교육, 다운로드, 제품 정보 등을 찾아보자.
-
developerWorks 기술 행사와 웹 캐스트로 최신 기술을 익히자.
제품 및 기술 얻기
- 이제 DB2를 무료로 사용할 수 있다. DB2 Express Edition과 같은 핵심 데이터 기능을 제공하고 애플리케이션 개발 및 배치의 기본을 제공하는 커뮤니티를 멤버를 위한 무료 버전의 DB2 Express Edition인 DB2 DB2 Express-C를 다운로드하자.
- developerWorks에서 직접 다운로드할 수 있는 IBM 시험판 소프트웨어로 다음 개발 프로젝트를 만들자.
-
DB2 Enterprise 9의 무료 시험판을 다운로드하자.
토론
필자소개  | 
|  | Vitor Rodrigues는 IBM 실리콘 밸리 랩에서 소프트웨어 개발자로 일하고 있다. 포르투갈에 있는 Minho 대학교에서 컴퓨터 공학 및 시스템 엔지니어링을 전공하고 2005년 IBM에 인턴으로 입사해 DB2 Everyplace와 DB2 9 pureXML 쪽 업무를 담당했다. pureXML을 위한 DB2 9 QA팀의 일원으로 일하면서 DB2 9의 XML 기능에 대한 깊이있는 지식을 쌓았다. 인턴쉽을 마치고 정사원이 되어 현재는 DB2 9 XML Enablement 팀에서 일하고 있다. |
기사에 대한 평가
|  |