IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  Information Management | WebSphere  >

WebSphere Federation Server Version 9.1을 사용하여 XML 데이터 통합하기 (한글)

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.


제안 및 의견
피드백

난이도 : 중급

Aakash Bordia, Staff Software Engineer, IBM
Eileen Lin, Senior Technical Staff Member, IBM Silicon Valley Lab
Ioana Ursu, Advisory Software Engineer, IBM Silicon Valley Lab
Sebastian Hahnel, Software Engineering Intern, IBM

2007 년 4 월 10 일

WebSphere® Federation Server Version 9.1의 pureXML™ 지원으로 로컬 및 원격 XML 스토어 데이터를 통합할 수 있게 되었습니다. 또한 새로운 SQL/XML과 XQuery 언어를 사용하여 새로운 애플리케이션에서 XML 데이터를 쿼리 할 수 있습니다. 이러한 모든 기능들을 통해 어떤 효용을 누릴 수 있는지를 알아봅시다.

머리말

IBM WebSphere Federation Server는 분산된 데이터 소스에 실시간, 가상화 액세스를 제공한다. 새로운 프로젝트를 시장에 빠르게 진입시키고, 특수한 쿼리를 허용하도록 창고(warehouse)도 확장하며, 엔터프라이즈 데이터를 한번에 볼 수 있는 통합된 뷰(VIEW)도 제공한다.

DB2® 9의 pureXML 지원으로, WebSphere Federation Server Version 9.1로 하나의 데이터베이스에 관계형 데이터베이스와 XML 데이터를 통합할 수 있다. 고객들은 네이티브 XML 스토리지에 있는 새로운 XML 데이터를 연합 데이터베이스로 통합할 수 있다. 아직, 원격 XML 데이터 유형에 대한 직접적인 지원은 없지만 XML 뷰를 사용하여 원격 XML 데이터를 통합할 수도 있다.

이 글에서는 로컬 및 원격 XML 스토어 데이터를 WebSphere Federation Server Version 9.1과 통합하는 방법을 설명한다. BOOKSTORE 예제를 사용하여, 새롭게 향상된 SQL/XML과 새로운 XQuery 언어를 사용하여 로컬 XML 스토어 데이터를 다루는 방법을 설명하겠다. 그리고, 원격 XML 스토어 데이터들을 통합하는 과정도 설명한다. BOOKSTORE 예제를 분산 BOOKSTORE로 확장하면서 설정을 다양한 데이터 소스에 적용하는 방법을 설명한다. SQL/XML과 XQuery 언어를 사용하여 이와 같은 시스템을 쿼리하는 방법을 나타내는 쿼리 예제도 제공한다. 이러한 향상된 부분들이 여러분의 작업에 어떤 혜택을 주는지를 함께 알아보자.

로컬 XML 스토어 데이터 통합하기

DB2는 기본 쿼리 언어로서 SQL과 XQuery를 지원한다. 각각의 데이터 모델에 대해 작동하며 독립적으로 사용될 수 있지만, 데이터베이스 애플리케이션은 DB2가 지원하는 이 두 가지 언어를 통합하면 더 큰 효용을 누릴 수 있다. 많은 애플리케이션들이 기존의 관계형 데이터와 XML을 동시에 다루기 때문에 쿼리는 이 두 가지 유형의 데이터를 결합 및 상호 연관 지을 수 있어야 한다. 통합을 위해 DB2 9은 다음과 같은 기능을 제공한다.

  • 애플리케이션이 SQL에 있는 XML 데이터에 액세스 할 수 있도록 해주는 SQL/XML 함수와 술어.
  • 애플리케이션이 XQuery의 관계형 데이터에 액세스 할 수 있도록 해주는 db2-fn:sqlquery 같은 함수들.

DB2는 연합(federation)을 사용하여 이기종의 관계형 데이터로 액세스 할 수 있기 때문에 SQL/XML과 XQuery로 지정된 관계형 테이블들은 닉네임(nickname)이 될 수 있다.

이 섹션에서는 SQL/XML과 XQuery를 사용하여, 닉네임으로 로컬 XML 컬럼을 쿼리하는 방법을 설명하겠다. 시나리오는 그림 1에 묘사되어 있다.


그림 1. BOOKSTORE 시나리오

그림 2는 이 시나리오의 구성 모습이다.


그림 2. Bookstore 시나리오 구성

SQL로 로컬 XML 데이터와 별칭 쿼리하기

DB2는 XMLQUERY, XMLEXISTS, XMLTABLE 같은 새로운 SQL/XML 함수와 술어를 제공함으로써, SQL 문에서 XML 데이터의 검색과 쿼리를 지원한다. 간단한 예제로 시작해 보도록 하자. 다음 쿼리는 책에 대한 정보, 재고량, ISBN이 "69"로 끝나는 책을 보유한 창고가 있는 도시 등을 검색한다.

SELECT b.xmlinfo, i.quantity, w.city  
FROM bookstore b, inventory i, warehouse w  
WHERE b.isbn = i.isbn 
  AND i.warehouse_id = w.warehouse_id 
AND b.isbn LIKE '%69'

위 예제에서, 두 개의 닉네임과 XML 컬럼을 포함하고 있는 로컬 테이블을 결합(join)하고 있다.

아웃풋(prettyPrint)은 다음과 같다.

<book isbn="0201633469" year="1993" category="Computers">
  <title>TCP/IP Illustrated</title>
  <author><last>Stevens</last><first>W. Richard</first></author>
  <publisher>Addison-Wesley Professional</publisher>
  <price>65.00</price>
  </book>,
3,
'San Francisco'

다음 예제는 XMLTABLE 함수를 사용하여 로컬 XML 컬럼에서 결과 테이블을 리턴하고, 결과 테이블을 사용하여 데이터를 닉네임에 삽입한다. 목적은 BOOKSTORE 테이블에 있는 XML 문서에서 데이터를 추출하여 개별 테이블에 책 저자를 저장하는 것이다.

INSERT INTO author
  SELECT xb.*
  FROM bookstore b, XMLTABLE(
    '$doc/book' PASSING b.xmlinfo AS "doc" COLUMNS
      "ISBN" CHAR(10) PATH '@isbn',
      "LASTNAME" VARCHAR(30) PATH 'author/last',
      "FIRSTNAME" VARCHAR(30) PATH 'author/first'
    ) AS xb;

다음 예제는 추가 필터링 용도로 XMLEXISTS를 사용하여 전체 BOOKSTORE 문서를 리턴한다. 가격이 $65.50 이하인 책이 있는 행들과 카피를 보유하고 있는 창고가 리턴된다. passing by 문은 SQL과 XQuery 컨텍스트 간 바인딩을 만든다.

SELECT b.isbn, i.warehouse_id, i.quantity
FROM bookstore b, inventory i
WHERE i.isbn = b.isbn 
  AND i.quantity > 0
  AND XMLEXISTS('$doc/book[price < 65.50]' 
        PASSING BY REF b.xmlinfo AS "doc")

다음 예제는 WHERE 문의 XMLQUERY 함수를 보여주어 로컬 XML 컬럼에서 추출된 값이 닉네임의 컬럼과 결합(join)하는데 사용될 수 있도록 한다. 여기에서, 타이틀에 "TCP/IP" 키워드를 포함하고 있는 각 책의 경우, 저자가 출간한 총 책의 수를 찾고 있다.

SELECT DISTINCT count(*) as NUMBER_OF_BOOKS, a.firstname, a.lastname
FROM author a, bookstore b
WHERE XMLSERIALIZE(CONTENT XMLQUERY('$doc/book/author/first/text()'
    PASSING BY REF b.xmlinfo AS "doc"
    RETURNING SEQUENCE) AS CHAR(50)) = a.firstname
  AND XMLSERIALIZE(CONTENT XMLQUERY('$doc/book/author/last/text()'
    PASSING BY REF b.xmlinfo AS "doc"
    RETURNING SEQUENCE) AS CHAR(50)) = a.lastname
  AND XMLSERIALIZE(CONTENT XMLQUERY('$doc/book/title/text()'
    PASSING BY REF b.xmlinfo AS "doc"
    RETURNING SEQUENCE) AS CHAR(50)) like '%TCP/IP%'
GROUP BY a.firstname, a.lastname, b.isbn

XQuery로 로컬 XML 데이터와 닉네임 쿼리하기

DB2 9의 XQuery를 사용하여 관계형 데이터에 액세스 하여 검색할 수 있다. 관계형 데이터를 XML 포맷으로 변형하고 XQuery에 대한 인풋으로서 작용할 수 있는 XML 컬럼을 만들어 내는 SQL/XML 컨스트럭터 함수를 사용할 수 있다. 사용자들은 이 모든 기존 관계형 데이터를 활용하여 XQuery 프로세싱에 맞는 XML을 만들 수 있다. db2-fn:sqlquery 함수는 XQuery에 대한 인풋을 줄일 뿐만 아니라, 확장시키는데 사용될 수 있다.

다음 예제에서, XQuery는 책, 재고, 지정된 책의 정보를 포함하고 있는 결과 문서를 만든다. 책 정보는 XML 컬럼 XMLINFO에서 가져온 XML 문서이다. 재고 정보는 두 개의 관련 닉네임을 결합하여 나타난다. SQL/XML 문은 두 개의 닉네임 WAREHOUSEINVENTORY의 결합의 결과에서 취해진 값을 가진 다섯 개의 자식 엘리먼트로 XML 엘리먼트 warehouse를 만든다. warehouse ID, street, city, state, quantity 등이 그것이다. 결과는 책에 대한 재고 리포트이고 창고에 대한 정보도 들어있다.

XQUERY 
  let $b := db2-fn:sqlquery("
    SELECT xmlinfo
    FROM bookstore
    WHERE isbn='0201633469'")
  let $w := db2-fn:sqlquery("
    SELECT XMLELEMENT(NAME warehouse, XMLFOREST(
      w.warehouse_id, w.street, w.city, w.state, i.quantity))
    FROM warehouse w, inventory i
    WHERE w.warehouse_id = i.warehouse_id
    AND i.isbn = '0201633469'")  
  return 
    <report>   
     {$b}
     <stock>{$w}</stock>
    </report>

아웃풋 샘플(prettyPrint)은 다음과 같다.

<report>
  <book isbn="0201633469" year="1993" category="Computers">
    <title>TCP/IP Illustrated</title>
    <author><last>Stevens</last><first>W. Richard</first></author>
    <publisher>Addison-Wesley Professional</publisher>
    <price>65.00</price>
  </book>
  <stock>
    <WAREHOUSE>
      <WAREHOUSE_ID>1</WAREHOUSE_ID>
      <STREET>1234 Market Street</STREET>
      <CITY>San Francisco</CITY>
      <STATE>CA</STATE>
      <QUANTITY>3</QUANTITY>
    </WAREHOUSE>
    <WAREHOUSE>
      <WAREHOUSE_ID>2</WAREHOUSE_ID>
      <STREET>4012 1st Street</STREET>
      <CITY>San Jose</CITY>
      <STATE>CA</STATE>
      <QUANTITY>1</QUANTITY>
    </WAREHOUSE>
  </stock>
</report>

다음 예제는 하나의 닉네임과 결합하여 XQuery에 대한 인풋 문서들을 걸러낸다. 가격이 $65 이상인 책의 제목을 쿼리하고 ID가 1인 창고에 의해 리스팅 된다.

XQUERY 
  for $e in db2-fn:sqlquery("
    SELECT b.xmlinfo 
    FROM bookstore b, inventory i
    WHERE b.isbn = i.isbn 
     AND i.warehouse_id = 1")/book
  where $e/price > 65.00
  return $e/title

샘플 아웃풋(prettyPrint)은 다음과 같다.

<title>Advanced Programming in the UNIX environment</title>

이 예제들은 XQuery와 SQL을 통합했을 때의 결과를 보여준다. 특히 닉네임을 통해 액세스 된 관계형 데이터가 네이티브 XML 스토어와 함께 사용될 때 힘을 발휘한다.

원격 XML 스토어 데이터 통합하기

WebSphere Federation Server Version 9.1에서 닉네임은 XML-유형 컬럼을 포함하고 있는 원격 테이블 또는 뷰를 통해 생성될 수 없다. 다양한 관계형 데이터베이스에서 XML 데이터를 통합하려면 직렬화된 스트링 데이터를 원격 및 로컬 XML 데이터간 매핑 메커니즘으로 간주할 수 있다.

그림 3은 다음과 같은 세 단계를 묘사하고 있다.

  1. 뷰를 사용하여 원격 데이터베이스에 XML 데이터 직렬화 하기
  2. 원격 뷰를 통해 닉네임 만들기
  3. 로컬 닉네임에서 온 직렬화 된 XML 데이터를 연합 서버(federated server)의 로컬 뷰로 파싱하기

그림 3. 원격 XML 데이터 통합하기

다음과 같은 정의를 가진 원격 Oracle 테이블이 있다고 해보자.

CREATE TABLE bookstore(isbn CHAR(10), xmlinfo XMLType);

XML 데이터는 원격 서버에서 다음과 같이 직렬화 된다.

CREATE VIEW bookstore_blob (isbn, xmlinfo) AS
SELECT b.isbn, b.xmlinfo.getBlobVal(nls_charset_id('utf8'))
FROM bookstore b;

XML 데이터는 정해진 길이가 없다. 큰 문서의 경우, 외부 XML 데이터 유형은 LOB 데이터와 비슷한 방식으로 취급된다. 하지만, 작은 문서의 경우, 보다 적절한 VARCHAR 같은 결과 유형을 지정할 수 있고, Character Large Objects (CLOB) 보다 더 나은 성능을 보인다.

원격 XML 데이터가 직렬화 된 후에, 다음과 같이 연합 서버에 원격 뷰를 통해 닉네임을 만들 수 있다.

CREATE NICKNAME bookstore_blob FOR server_name.myuser.bookstore_blob;

연합 서버에서, 직렬화 된 스트링을 XML 유형으로 변환해야 한다. 직렬화된 스트링을 XML 값으로 변환하는 XMLPARSE 함수를 사용해 보자.

CREATE VIEW vbookstore (isbn, xmlinfo) AS
SELECT isbn, XMLPARSE(DOCUMENT xmlinfo PRESERVE WHITESPACE)
FROM bookstore_blob;

XQuery와 SQL/XML 함수를 사용하여 로컬 XML 데이터 유형으로서 원격 XML 데이터를 조작할 수 있다.

원격 XML 데이터용 데이터 밸리데이션

DB2 파서는 유효 XML 데이터만 인풋으로서 허용한다. 제공된 데이터가 파싱되지 않으면, 에러가 리턴된다. 예를 들어, XML 문서의 일부 또는 엘리먼트의 값을 추출하는 원격 뷰를 통해 닉네임을 만들 수 있다. 아래 Oracle 뷰는 XML 엘리먼트의 콘텐트를 리턴한다.

CREATE VIEW bookstore_blob (isbn, xmlinfo) AS
SELECT extract(xmlinfo, '//book').getBlobVal(nls_charset_id('utf8'))
FROM bookstore;

결과는 XML 유형의 인스턴스로서 리턴된 노드의 시퀀스이다. XMLPARSE가 원격 뷰를 통해 생성된 닉네임의 아웃풋에 적용되면, DB2 파서는 무효 XML 문서 구조(SQL16132N)를 포함하고 있는 XML 문서를 발견해 낸다. 이는 사용 에러로 간주된다.

이 에러를 해결하는 한 가지 방법은 뷰 정의의 일부로서 root 엘리먼트를 추가하는 것이다. 예를 들어, Oracle 데이터 소스에 다음과 같은 뷰를 정의할 수 있다.

CREATE VIEW bookstore_blob (isbn, xmlinfo) AS
SELECT '<root>' || 
       extract(xmlinfo,//book').getBlobVal(nls_charset_id('utf8'))|| 
       '</root>' 
FROM bookstore;

연합 서버에서, XMLPARSE와 함께 스키마 밸리데이션을 사용할 수 있다.

CREATE VIEW vbookstore (isbn, xmlinfo) AS
SELECT isbn, XMLVALIDATE(XMLPARSE(DOCUMENT xmlinfo WHITESPACE)
                          ACCORDING TO XMLSCHEMA ID bookschema)
FROM bookstore_blob;

bookschema는 로컬 DB2 등록 스키마 객체로서, 원격 데이터 소스 XML 스키마를 나타낸다. REGISTER XMLSCHEMA 명령을 사용하여 bookstore 스키마를 DB2에 등록할 수 있다.

REGISTER XMLSCHEMA schema_URI FROM content_URI AS bookschema COMPLETE;

기본적으로, XMLPARSE만 스키마 밸리데이션 없이 잘 구성된 데이터를 체크한다.

XMLVALIDATE 함수는 주어진 XML 스키마 또는, 인스턴스 문서에 있는 스키마 스팩에 포함된 XML 스키마에 대해서 주어진 XML 값의 유효성 검사를 수행한다.

다음 제약 사항들을 주지하기 바란다.

  • 스키마 스팩 없이 XMLVALIDATE 가 호출되면 내부 스키마 스팩이 사용되거나, 내부 스팩도 없다면 DTD 스팩이 사용된다. 스키마 위치 또는 외부 DTD에 액세스 할 수 없다면 파서는 에러 메시지를 실행한다.
  • XMLVALIDATE가 등록된 스키마 또는 지정된 URI로 호출되면 지정된 스키마에 대해 밸리데이션이 수행된다. 외부 스키마가 지정되면, 내부 스키마 스팩이 무시된다. 연합 문의 경우, DB2 서버에서 스키마 정보에 액세스 할 수 없다면 문서의 내부 스키마 스팩은 무시된다.

원격 XML 데이터에 대한 데이터 인코딩 고려 사항

XML 데이터를 직렬화 할 때, 대상 유형들은 인코딩 유형을 결정한다. XML 아웃풋에는 내부 인코딩 정보가 포함될 것이다. 하지만, 비 XML 아웃풋에는 XML 선언이 포함되지 않으며, 이 경우, 연합 서버 또는 DB2 XML 파서로 가서 인코딩 스키마을 담당한다.

일반적으로, XML 데이터가 XML 데이터 유형을 사용하여 송수신 되면, 코드페이지 변환 문제는 생기지 않는다. 하지만 SQL 문자 유형이 직렬화 된 XML 데이터를 저장하는데 사용될 때 그 문자 유형의 코드페이지는 코드 페이지 변환 문제를 일으킬 수 있다.

연합 문의 경우, 코드 페이지 관련 문제들이 직렬화 된 원격 XML 데이터를 조작하는 동안 발생할 수 있다.

원격 XML 데이터는 바이너리 데이터 유형으로 직렬화 된다.

원격 클라이언트에서 연합 래퍼(wrapper)로 전송 시 어떤 데이터 소실도 없다.

DB2 XML 파서 인코딩 규칙이 적용될 것이다. 또한, 내부 인코딩이 존재하고, 이것이 유효한 IBM 인코딩 스키마가 아니면, 파서는 SQL16168N 에러 메시지를 만들어 낸다. 이와 같은 경우, 원격의 직렬화 된 스트링에서 XML 선언을 배제할 것을 권한다. 예를 들어, Oracle에서 XML 선언을 배제한 다음과 같은 원격 뷰 정의를 사용할 수 있다. Oracle은 XML 문서에 XML 선언이 있다면 기본적으로 XML 선언을 추가한다.

CREATE VIEW bookstore_blob (isbn, xmlinfo) AS
SELECT isbn, 
extract(xmlinfo,'/').getBlobVal(nls_charset_id('utf8'))
FROM bookstore; 

원격 XML 데이터는 문자 데이터 유형으로 직렬화 된다.

  • XML 데이터의 코드 페이지는 연합 데이터베이스 코드 페이지(Unicode)가 될 것이다. 원격 클라이언트에서 연합 래퍼로 전송 시 데이터 소실 가능성이 존재한다. 변환을 통해 문자 치환(substitution)이 생기면, 데이터 소스 작동과 래퍼 실행에 따라 경고가 발생된다.
  • DB2 XML 파서 인코딩 규칙이 사용된다. 내부 인코딩이 존재하고 이것이 무효한 IBM 인코딩 스키마라면, 파서는 SQL16168N을 실행한다. 이 경우, 직렬화가 이를 허용한다면 XML 선언을 배제할 것을 권한다. 예를 들어, Oracle에서, 다음의 원격 뷰 정의를 사용하여 XML 선언을 배제한다.
CREATE VIEW clob_books (isbn, xmlinfo) AS
SELECT isbn, extract(xmlinfo, '/').getClobVal() 
FROM bookstore;

코드 페이지 변환 문제를 피하려면, 문자 유형 대신 FOR BIT DATA 또는 BLOB을 사용할 것을 권한다. 연합 시스템의 경우, 내부 XML 인코딩은 데이터 소스마다 다를 수 있다. 이 같은 경우, XML 선언을 배제할 것을 권한다.

분산 bookstore 시나리오

로컬 XML 스토어 데이터 섹션에서 설명한 시나리오에 기반하여, 온라인 bookstore 시나리오를 묘사한 그림 4의 엔터티 관계 다이어그램을 생각해 보자. BOOKSTORE 테이블은 연합 서버와 Oracle 10g Release 2 데이터베이스에 위치해 있다.


그림 4. 분산 BOOKSTORE 시나리오

Appendix A3에는 서버, 래퍼, 사용자 매핑 생성 과정이 나와있다. 전체적인 설정 모습은 그림 5에 나타나 있다.


그림 5. BOOKSTORE 시나리오의 구성

원격 뷰를 사용하여 원격 XML 데이터 직렬화 하기

Oracle 10gR2 Server에는 하나의 BOOKSTORE 테이블이 있다. XML 데이터는 다음과 같은 원격 뷰를 사용하여 BLOB 데이터 유형으로 직렬화 된다.

CREATE VIEW bookstore_blob (isbn, xmlinfo) AS
SELECT b.isbn, b.xmlinfo.getBlobVal(nls_charset_id('utf8'))
FROM bookstore2 b;

REVIEW 테이블은 SQL Server 2005에 있다. XML 데이터는 다음과 같은 원격 뷰를 사용하여 BLOB으로 직렬화 된다.

CREATE VIEW review_blob (review_id, xmlinfo) AS
SELECT review_id, CAST(xmlinfo AS VARBINARY(MAX))
FROM review;

CUSTOMER_INFO 테이블은 DB2 9 데이터베이스에 저장되고, XML 데이터는 다음과 같은 원격 뷰를 사용하여 BLOB 컬럼으로 직렬화 된다.

CREATE VIEW customer_info_blob (customer_id, xmlinfo) AS
SELECT customer_id, XMLSERIALIZE(xmlinfo AS BLOB INCLUDING XMLDECLARATION)
FROM customer_info;

닉네임과 로컬 XML 뷰 생성하기

다음은 닉네임을 정의하는 문장이다.

CREATE NICKNAME bookstore_blob FOR "oracle10g2".myuser.bookstore_blob;
CREATE NICKNAME review_blob FOR "mssql".myuser.review_vlob;
CREATE NICKNAME customer_info_blob 
  FOR "db2v91".myuser.customer_info_blob; 
CREATE NICKNAME inventory FOR "db2v91".myuser.inventory;
CREATE NICKNAME warehouse FOR "db2v91".myuser.warehouse;

orders.xml XML 문서에 있는 고객 주문에 아이템 리스트가 포함되기 때문에, 두 개의 닉네임을 사용하여 나타난다.

CREATE NICKNAME order (
  order_id CHAR(10) OPTIONS (XPATH '@id'),
  order_date DATE OPTIONS (XPATH '@date'),
  customer_id CHAR(10) OPTIONS (XPATH '@cid'))  
FOR SERVER "xml_server"
OPTIONS (
  FILE_PATH '/my/path/orders.xml', 
  XPATH '/orders/order');

CREATE NICKNAME order_item (
  order_id VARCHAR(10) OPTIONS (XPATH '../@id'),
  isbn CHAR(10) OPTIONS (XPATH '@isbn'))
FOR SERVER "xml_server"
OPTIONS (
  FILE_PATH '/my/path/orders.xml', 
  XPATH '/orders/order/item');

닉네임을 통해 로컬 XML 뷰를 만든다.

CREATE VIEW vbookstore2 (isbn, xmlinfo) AS
SELECT isbn, XMLPARSE(DOCUMENT xmlinfo PRESERVE WHITESPACE)
FROM bookstore_blob;

CREATE VIEW vreview (review_id, xmlinfo) AS
SELECT review_id, XMLPARSE(DOCUMENT xmlinfo PRESERVE WHITESPACE)
FROM review_blob;

CREATE VIEW vcustomer_info (customer_id, xmlinfo) AS
SELECT customer_id, XMLPARSE(DOCUMENT xmlinfo PRESERVE WHITESPACE)
FROM customer_info_blob;

분산 BOOKSTORE를 모델링 하려면, bookstore1 테이블과 vbookstore2 뷰에서 UNION ALL 뷰를 정의한다.

CREATE VIEW big_bookstore (isbn, xmlinfo) AS
  SELECT isbn, xmlinfo FROM bookstore1
  UNION ALL
    SELECT isbn, xmlinfo FROM vbookstore2; 

SQL/XML과 XQuery로 쿼리하기

사용자들은 우리가 위에서 만든 로컬 뷰에 대해 SQL/XML 또는 XQuery를 실행할 수 있다. XML 데이터가 어디에 있는지 몰라도 상관 없다.

우선, SQL/XML 퍼블리시 함수와 XMLTABLE 함수를 사용하여 각 책에 대한 리뷰를 찾는다.

SELECT XMLELEMENT(NAME "book",
         XMLFOREST(
           b."title" AS "title", 
           r."review" AS "review"))
FROM big_bookstore vb, vreview vr,
  XMLTABLE('$doc/book' PASSING vb.xmlinfo AS "doc"
    COLUMNS "isbn" CHAR(10) PATH '@isbn',
            "title" VARCHAR(50) PATH 'title') as b,
  XMLTABLE('$doc/reviews/review' PASSING vr.xmlinfo AS "doc"
    COLUMNS "isbn" CHAR(10) PATH '@isbn',
            "review" VARCHAR(70) PATH '.') as r
WHERE b."isbn" = r."isbn";

다음은 샘플 아웃풋이다. (prettyPrint)

<book>
  <title>Advanced Programming in the UNIX environment</title>
  <review>A clear and detailed discussion of UNIX programming.</review>
</book>
<book>
  <title>TCP/IP Illustrated</title>
  <review>One of the best books on TCP/IP.</review>
</book>

SQL/XML 퍼블리시 함수와 다른 XML 구조체를 사용하여 다양한 장소에서 팔린 도서 리스트를 제공한다. 다음은 아웃풋 포맷이다.

<list>
  <state name="CA">
    <city name="San Francisco">
      <book>TCP/IP Illustrated</book>
    </city>
    <city name="San Jose">
      <book>Advanced Programming in the UNIX environment</book>
      <book>TCP/IP Illustrated</book>
      <book>TCP/IP Illustrated</book>
    </city>
  </state>
  <state name="NY">
    <city name="New York">
      <book>TCP/IP Illustrated</book>
    </city>
  </state>
</list>

다음 문장에서는 위의 아웃풋을 (시퀀스로서) 만들어 낸다.

VALUES (XMLELEMENT(NAME "list", (
  SELECT XMLAGG (s.state)
  FROM ( SELECT XMLELEMENT(NAME "state", 
           XMLATTRIBUTES(c.state AS "name"),
           XMLAGG(c.city)) AS state
         FROM ( SELECT ci."state" AS state, 
                  XMLELEMENT(NAME "city", 
                  XMLATTRIBUTES(ci."city" AS "name"),
                  XMLAGG(XMLELEMENT(NAME "book", b."title"))) AS city
                FROM order o, order_item oi, 
                     big_bookstore vb, vcustomer_info vci,
	          XMLTABLE('$p/customer' PASSING vci.xmlinfo AS "p"
		    COLUMNS "id" VARCHAR(10) PATH '@id',
			    "city" VARCHAR(20) PATH 'address/city',
			    "state" VARCHAR(10) PATH 'address/state') AS ci,
	          XMLTABLE('$p/book' PASSING vb.xmlinfo AS "p"
	            COLUMNS "isbn" VARCHAR(10) PATH '@isbn',
	                    "year" VARCHAR(4) PATH '@year',
	                    "title" VARCHAR(100) PATH 'title') AS b
                     WHERE o.order_id = oi.order_id 
                       AND oi.isbn = b."isbn"
                       AND o.customer_id = ci."id"
                       AND o.order_date <= '10/25/2004'
                     GROUP BY ci."city", ci."state") AS c 
         GROUP BY c.state) AS s
  )));

사용자들은 XQuery를 사용하여 베스트 리뷰를 가지고 있고 평균 가격 보다 저렴한 컴퓨터 서적 리스트를 검색할 수 있다.

 
XQUERY 
  let $a := fn:avg(
    db2-fn:xmlcolumn("BIG_BOOKSTORE.XMLINFO")
    /book[@category = "Computers"]/price/text())
  for $book in db2-fn:xmlcolumn('BIG_BOOKSTORE.XMLINFO')/book
  for $review in db2-fn:xmlcolumn('VREVIEW.XMLINFO')/reviews/review 
where 
  $book/@isbn = $review/@isbn
  and $book/price/text() <= $a 
  and fn:contains($review/text(), "best")
return 
  <book>{$book/title/text()}</book>

다음은 샘플 아웃풋이다.

<book>TCP/IP Illustrated</book>

마지막 예제에서는 XQuery 내에서 SQL의 사용법과, XQuery 구조를 중첩시키는 방법을 설명한다. 이 쿼리의 목적은 각 창고 마다 도서의 재고량을 파악하고, 각 도서의 총 재고량을 파악하는 것이다.

XQUERY
  for $total_order in db2-fn:sqlquery('
    SELECT 
      XMLELEMENT(NAME "total_order",
        XMLFOREST(
          i.isbn AS "isbn",
          sum(i.quantity) AS "total"
        )
      )
    FROM warehouse w, inventory i
    WHERE w.warehouse_id = i.warehouse_id
    GROUP BY i.isbn
  ')
  let $warehouses := db2-fn:sqlquery('
    SELECT
        XMLAGG(
          XMLELEMENT(NAME "warehouse",        
            XMLFOREST(
              i.isbn AS "isbn",
              i.quantity AS "quantity",
              w.city AS "city",
              w.warehouse_id AS "id"
            ) 
          )
        )
    FROM warehouse w, inventory i      
    WHERE w.warehouse_id = i.warehouse_id
  ')[isbn=$total_order/isbn]
  return
    <book isbn="{$total_order/isbn}">
      <stock total="{$total_order/total}">
        {
          for $wh in $warehouses
          return 
            <warehouse id="{$wh/id}">
              <city>{$wh/city/text()}</city>
              <quantity>{$wh/quantity/text()}</quantity>
            </warehouse>
        }
      </stock>
    </book>   

우리 예제에서, 샘플 아웃풋은 다음과 같은 포맷으로 리턴된다.

<book isbn="0201563177">
  <stock total="7">
    <warehouse id="1">
      <city>San Francisco</city>
      <quantity>2</quantity>
    </warehouse>
    <warehouse id="2">
      <city>San Jose</city>
      <quantity>5</quantity>
    </warehouse>
  </stock>
</book>  
<book isbn="0201633469">
  <stock total="4">
    <warehouse id="1">
      <city>San Francisco</city>
      <quantity>3</quantity>
    </warehouse>
    <warehouse id="2">
      <city>San Jose</city>
      <quantity>1</quantity>
    </warehouse>
  </stock>
</book>

소셜 북마크

mar.gar.in mar.gar.in
digg Digg
del.icio.us del.icio.us
Slashdot Slashdot

요약

이 글에서 WebSphere Federation Server Version 9.1을 사용하여 로컬 XML 스토어 데이터와 원격 XML 스토어 데이터를 통합하는 방법을 설명했다. 아직은 원격 XML 스토어 데이터에 액세스 할 수 있는 닉네임을 정의할 수 없지만, 이와 같은 태스크를 수행할 수 있는 뷰를 사용하는 방법에 대해서 배웠다.

현재, 우리는 원격 XML 스토어 데이터로의 연합 액세스에 대해 작업 중이다. 이러한 작업을 통해 이 글에서 설명한 추가 구성이 없어지고, 뷰 대신 직접 액세스를 사용함으로써 성능을 높일 수 있다. 더욱이, 새로운 연합 액세스로 원격 XML 데이터를 업데이트 할 수 있다. pureXML 지원과 연합(federation)이 언제나 진화하는 기업에 있어서 강력한 대안이 될 것을 믿어 의심치 않는다.

부록: 설정 스크립트

A1. BOOKSTORE 예제 설정하기

로컬 XML 스토어 데이터 섹션에서 설명한 대로 테이블이 생성되었다면, 이제 데이터로 테이블을 채울 차례이다. 다음 라인은 BOOKSTORE 테이블의 콘텐트이다.

('0201633469', 
<book isbn="0201633469" year="1993" category="Computers">
  <title>TCP/IP Illustrated</title>
  <author>
    <last>Stevens</last>
    <first>W. Richard</first>
  </author>
  <publisher>Addison-Wesley Professional</publisher>
  <price>65.00</price>
</book>)
,
('0201563177', 
<book isbn="0201563177" year="1992" category="Computers">
  <title>Advanced Programming in the UNIX environment</title>
  <author>
    <last>Stevens</last>
    <first>W. Richard</first>
  </author>
  <publisher>Addison-Wesley Professional</publisher>
  <price>65.95</price>
</book>)

다음 데이터가 INVENTORY 테이블에 저장되어 있다고 해보자.

SELECT * FROM inventory;

INVENTORY_ID WAREHOUSE_ID ISBN       QUANTITY
------------ ------------ ---------- -----------
        1001            1 0201633469           3
        1002            1 0201563177           2
        1003            2 0201633469           1
        1004            2 0201563177           5

4 record(s) selected.

WAREHOUSE 테이블에는 다음과 같은 데이터가 포함된다.

SELECT * FROM warehouse;

WAREHOUSE_ID STREET             CITY          STATE
------------ ------------------ ------------- -----------------
           2 4012 1st Street    San Jose      CA
           1 1234 Market Street San Francisco CA

2 record(s) selected.

The AUTHOR table is assumed to be empty.

A2. 분산 bookstore 시나리오를 위한 테이블 만들기

BOOKSTORE 관계를 나타내는 XML 문서들은 두 개의 테이블에 저장된다. 첫 번째 테이블은 로컬 BOOKSTORE 테이블이고, DB2 데이터베이스 서버의 연합 데이터베이스 쪽에 있다.

CREATE TABLE bookstore1(isbn CHAR(10), xmlinfo XML);

다른 테이블은 Oracle 10g Release 2 데이터베이스에 위치해 있다. 정의는 다음과 같다.

CREATE TABLE bookstore2(isbn CHAR(10), xmlinfo XMLTYPE);

두 개의 데이터베이스에 있는 테이블들은 같은 원격 XML 스키마를 사용해야 한다.

REVIEW 테이블은 MS SQL Server 2005 데이터베이스에 있고, 책에 대한 리뷰가 들어있다. 테이블 정의는 다음과 같다.

CREATE TABLE review(review_id INT, xmlinfo XML);

CUSTOMER_INFO 테이블은 DB2 9 데이터베이스에 저장되고, 고객 정보가 들어있다. 테이블 정의는 다음과 같다.

CREATE TABLE customer_info(customer_id INT, xmlinfo XML);

INVENTORYWAREHOUSE 테이블은 DB2 9 데이터베이스에 위치한 비 XML 관계형 테이블이다.

CREATE TABLE warehouse(warehouse_id INT, street CHAR(50), city CHAR(30), state CHAR(30));
CREATE TABLE inventory(inventory_id INT, warehouse_id INT, isbn CHAR(10), quantity INT);

온라인 주문 정보는 orders.xml이라고 하는 로컬 파일 시스템 상의 XML 문서에 있다.

A3. 분산 bookstore 시나리오를 위한 래퍼, 서버, 사용자 매핑 만들기

네 개의 래퍼를 정의하여 네 개의 다른 유형의 데이터 소스에 액세스 해야 한다.

CREATE WRAPPER net8;
CREATE WRAPPER drda;
CREATE WRAPPER mssqlodbc3;
CREATE WRAPPER xml_wrapper LIBRARY 'libdb2lsxml.a';

주: 우리의 시나리오는 AIX 5.2에서 테스트 되었다.

래퍼 라이브러리가 연합 시스템에 등록된 후에, 각 데이터 소스는 서버로서 등록되어야 한다.

CREATE SERVER "oracle10g2" TYPE ORACLE VERSION 10.2
  WRAPPER net8 OPTIONS (NODE 'MYORA10');
 
CREATE SERVER "db2v91" TYPE db2/cs VERSION 9 
  WRAPPER drda AUTHORIZATION "myuser" PASSWORD "secret"
  OPTIONS (NODE 'MYDB2', DBNAME 'MYDB');

CREATE SERVER "mssql" TYPE MSSQLSERVER VERSION 2005 
  WRAPPER mssqlodbc3 OPTIONS (NODE 'MYMSSQL', DBNAME 'MYDB');

CREATE SERVER "xml_server" WRAPPER xml_wrapper;
			

사용자 매핑을 생성하여 원격 인증 정보를 데이터 소스에 등록할 수 있다.

CREATE USER MAPPING FOR USER SERVER "oracle10g2"
  OPTIONS (REMOTE_AUTHID 'myuser', REMOTE_PASSWORD 'secret'); 

CREATE USER MAPPING FOR USER SERVER "db2v91"
  OPTIONS (REMOTE_AUTHID 'myuser', REMOTE_PASSWORD 'secret');

CREATE USER MAPPING FOR USER SERVER "mssql"
  OPTIONS (REMOTE_AUTHID 'myuser', REMOTE_PASSWORD 'secret');

A4. 분산 bookstore 예제 설정하기

분산 bookstore 시나리오 섹션에서 설명한 대로 원격 테이블이 생성된 후에, 예제 데이터로 채울 수 있다.

연합 서버의 BOOKSTORE1 테이블에는 다음과 같은 데이터가 포함된다.

% DB2 Federated Server
INSERT INTO bookstore1 VALUES('0201633469', 
'<book isbn="0201633469" year="1993" category="Computers">
  <title>TCP/IP Illustrated</title>
  <author>
    <last>Stevens</last>
    <first>W. Richard</first>
  </author>
  <publisher>Addison-Wesley Professional</publisher>
  <price>65.00</price>
</book>');

Oracle 10g Release 2 서버에는 BOOKSTORE2 테이블이 다음과 같은 명령어를 사용하여 채워진다.

% Oracle 10g Release 2
INSERT INTO bookstore2 VALUES('0201563177', XMLTYPE(
'<book isbn="0201563177" year="1992" category="Computers">
  <title>Advanced Programming in the UNIX environment</title>
  <author>
    <last>Stevens</last>
    <first>W. Richard</first>
  </author>
  <publisher>Addison-Wesley Professional</publisher>
  <price>65.95</price>
</book>'));

MS SQL Server 2005에 있는 REVIEW 테이블은 다음과 같이 채워진다.

INSERT INTO review VALUES
  (1, 
  '<reviews>
    <review id="10001" isbn="155860622X">A very good discussion of 
semi-structured database systems and XML.</review>
    <review id="10002" isbn="0201563177">A clear and detailed discussion 
of UNIX programming.</review>
    <review id="10003" isbn="0201633469">One of the best books on 
TCP/IP.</review>
  </reviews>');

데이터는 DB2 9 데이터베이스에 저장된 CUSTOMER_INFO 테이블에 다음 문장을 사용하여 삽입된다.

INSERT INTO customer_info VALUES(1, XMLPARSE(DOCUMENT
'<customer id="1">
  <name><last>Smith</last><first>Joe</first></name>
  <address>
    <street>6127 Crown Bld</street>
    <city>San Jose</city>
    <state>CA</state>
  </address>
</customer>' PRESERVE WHITESPACE));

 INSERT INTO customer_info VALUES(2, XMLPARSE(DOCUMENT
'<customer id="2">
  <name><last>Miller</last><first>Bob</first></name>
  <address>
    <street>544 Capitol Expw</street>
    <city>San Jose</city><state>CA</state>
  </address>
</customer>' PRESERVE WHITESPACE));

INSERT INTO customer_info VALUES(3, XMLPARSE(DOCUMENT
'<customer id="3">
  <name><last>Meyer</last><first>Ann</first></name>
  <address>
    <street>8400 Main St</street>
    <city>San Francisco</city><state>CA</state>
  </address>
</customer>' PRESERVE WHITESPACE));

INSERT INTO customer_info VALUES(4, XMLPARSE(DOCUMENT
'<customer id="3">
  <name><last>Apple</last><first>Sue</first></name>
  <address>
    <street>2200 Diamond Blvd</street>
    <city>New York</city><state>NY</state>
  </address>
</customer>' PRESERVE WHITESPACE));

같은 데이터베이스에 있는 INVENTORYWAREHOUSE 테이블은 다음과 같은 데이터로 채워진다.

INSERT INTO warehouse VALUES (1, '1234 Market Street', 'San Francisco', 'CA');
INSERT INTO warehouse VALUES (2, '4012 1st Street', 'San Jose', 'CA');
INSERT INTO inventory VALUES (1001, 1, '0201633469', 3);
INSERT INTO inventory VALUES (1002, 1, '0201563177', 2);
INSERT INTO inventory VALUES (1003, 2, '0201633469', 1);
INSERT INTO inventory VALUES (1004, 2, '0201563177', 5);

로컬 파일 시스템의 orders.xml 문서에 있는 온라인 주문 정보에는 다음과 같은 데이터가 포함된다.

<?xml version="1.0" encoding="UTF-8"?>
<orders>
  <order id="101" cid="1" date="2004-10-24">
    <item isbn="0201633469"/>    
    <item isbn="0201633469"/>    
  </order>
  <order id="102" cid="3" date="2004-10-25">
    <item isbn="0201633469"/>    
  </order>
  <order id="103" cid="2" date="2004-10-26">
    <item isbn="0201633469"/>    
    <item isbn="0201563177"/>    
  </order>
  <order id="104" cid="1" date="2004-10-27">
    <item isbn="0201563177"/>    
  </order>
  <order id="105" cid="3" date="2004-10-28">
    <item isbn="0201563177"/>    
    <item isbn="0201563177"/>    
  </order>
</orders>

기사의 원문보기



참고자료

교육

제품 및 기술 얻기

토론


필자소개

Aakash Bordia photo

Aakash Bordia는 Silicon Valley Laboratory의 소프트웨어 엔지니어이다. 2000년 1월 University of Illinois를 졸업한 후에, IBM DB2 Warehouse Manager 개발 팀에 합류하여 SQL 기반 웨어하우스 변형에 기여했다. 2002년에, WebSphere Information Integrator Federation 팀으로 옮겨와서 컴파일러 개발자로서 활동했으며, 최근에는 QA Engineer로 활동하고 있다.


Author photo

Eileen Lin 박사는 Silicon Valley Laboratory의 Senior Technical Staff Member이다. DB2의 전신인 DataJoiner를 담당했었다. 현재, WebSphere Information Integrator의 데이터 연합 기술 관련 아키텍트로 활동하고 있다. 연합 기술, 쿼리 최적화, 병렬 쿼리 프로세싱 분야에서 많은 페이턴트를 소지하고 있다.


Author photo

Ioana Ursu는 Silicon Valley Laboratory의 Advisory Software Engineer이다. 1998년 IBM Almaden에서 Garlic 연구 프로젝트를 진행했다. 1999년 이후, 쿼리 시맨틱, 쿼리 재작성, pushdown 분석, 쿼리 최적화를 포함하여 연합 쿼리와 관련한 여러 분야에서 작업했다. 현재 WebSphere Information Integrator Federated Query Compiler 팀에서 일반적인 연합 쿼리 프로세싱을 연구하고 있다.


Sebastian Hahnel photo

Sebastian Hahnel은 IBM Silicon Valley Lab의 인턴이다. University of Applied Sciences of Leipzig (독일)에서 컴퓨터 공학과를 졸업한 후에 2006년 4월 WebSphere Information Integrator Federation 팀에 합류했다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



아니오잘 모르겠음
 


 


12345
 



위로


developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.

    IBM 소개개인정보 보호정책문의