본문 바로가기
Database/MSSQL

SQL로의 입력, XML로의 출력

by 반화넬 2007. 6. 4.
반응형
XML 기술
SQL로 들어가서 XML로 나온다

저자: Jonathan Gennick

새로운 SQL/XML 함수는 관계형 데이타와 XML을 표준에 기반하여 연결합니다.

수 십년 동안 기업들은 관계형 데이타베이스에 데이타를 쏟아 부어 왔습니다. 그러나 다른 기업과 데이타를 교환하는 기업들은 관계형 데이타베이스에서 데이타를 꺼내 이를 XML 포맷으로 변경한 후 비즈니스 파트너에게 전송해야 하는 경우가 갈수록 늘어나고 있습니다.

SQL/XML 표준

Oracle9i Database에는 관계형 데이타를 쿼리하고 XML 문서를 반환할 수 있는 여러 표준 기반 함수들이 들어 있습니다. 이 함수들을 통칭하여 SQL/XML이라 하며 때때로 SQLX라고 불리기도 합니다. SQL/XML은 현재 ANSI/ISO SQL 표준의 일부(정확히 말해 Part 14)로 등장하고 있으며 올해 후반 ISO/IEC 표준으로 발표될 예정입니다. SQL/XML 표준은 업계의 폭 넓은 지원을 받고 있으며, SQL/XML 표준 정의 작업과 관련된 주요 데이타베이스 업체들로는 IBM, Microsoft, Oracle, Sybase 등이 있습니다.

SQL/XML 국제 표준 최종안(The Final Draft International Standard for SQL/XML)에서는 다음과 같은 요소들을 정의하고 있습니다.


XML: XML 데이타를 담는 데이타 유형

XMLAgg: GROUP BY 질의에서 XML 데이타를 그룹으로 분류 또는 집계하는 함수

XMLAttributes: SQL 질의에 의해 반환된 XML 요소에 특성을 설정하는 데 사용되는 함수

XMLConcat: 둘 이상의 XML 값을 연결하는 함수

XMLElement: 관계형 값을 XML 요소로 변형시키는 함수(형식: <elementName>value</elementName>)

XMLForest: 관계형 값 목록으로부터 XML 요소의 목록(일명: '포리스트(forest)')을 생성하는 함수

XMLNamespaces: XML 요소에서 네임스페이스를 선언하는 함수

XMLSerialize: XML 값을 문자열로 직렬화하는 함수

이 목록으로부터 Oracle9i Database는 XML 데이타 유형(XMLType), XMLAgg, XMLConcat, XMLElement 및 XMLForest 등을 구현합니다. 향후 출시되는 버전에서는 추가로 다른 함수를 지원할 계획입니다.

함수와 데이타 유형 외에도 SQL/XML 표준에서는 열 이름을 XML 요소 이름으로 변환하고 SQL 데이타 유형을 XML 데이타 유형으로 변환하는 규칙을 정의합니다. 이 규칙들은 XMLElement 및 기타 SQL/XML 함수들에 의해 자동으로 적용됩니다.


XML 문서 생성

여러분이 관광 안내소에 근무하고 있으며, 관광객들의 관심을 끌만한 관광 명소에 대한 정보를 다음 테이블과 같이 관계형으로 저장하고 있다고 가정해 보십시오.


SQL> describe COUNTY


 Name                Null? Type
 --------------      ----- --------------
 COUNTY_NAME              VARCHAR2(10)
 STATE                    VARCHAR2(2)
SQL> describe ATTRACTION

 Name                Null? Type
 --------------      ----- --------------
 COUNTY_NAME              VARCHAR2(10)
 ATTRACTION_NAME            VARCHAR2(30)
 ATTRACTION_URL            VARCHAR2(40)

 GOVERNMENT_OWNED          CHAR(1)
 LOCATION                  VARCHAR2(20)

여러분은 방금 이 데이타를 다른 지역의 유사한 사무소로 보내 줄 것을 요청 받았습니다. 이 데이타를 보낼 때는 반드시 XML로 보내야 합니다. 우선 XMLElement를 활용하여 각 관광 명소에 대한 XML 요소를 다음과 같이 생성합니다.


SELECT XMLElement("Attraction",
                attraction_name)
FROM attraction;

XMLELEMENT("ATTRACTION",ATTRACTION_NAME)
------------------------------------------

<Attraction>Pictured Rocks</Attraction>
<Attraction>Da Yoopers ... </Attraction>
<Attraction>Valley Camp ...</Attraction>
...

XMLElement는 확실히 이해해야 할 가장 중요한 SQL/XML 기능 중의 하나인 것은 XML 요소 생성이야말로 SQL/XML이 존재하는 근본적인 이유이기 때문입니다. XMLElement의 첫 번째 인수는 문자열 인수가 아니라 식별자로서 테이블 이름 또는 열 이름이 식별자인 것과 같은 의미입니다. 그래서 위의 XMLElement 질의에서 이중 따옴표를 사용했습니다. 테이블에서 소문자 열 이름을 사용하려면 테이블을 생성할 때 그 열 이름에 이중 따옴표를 사용하십시오. 마찬가지로 요소 이름을 소문자로 하는 경우에도 이중 따옴표로 묶습니다. XMLElement에 대한 두 번째 인수는 현재 생성하고 있는 요소에 값을 제공하는 열 이름입니다.

이번 데이타 전달에는 관광 명소 이름 뿐만 아니라 다른 정보도 전달하려 합니다. 목록 1과 같이 XMLElement에 호출을 중첩하여 각각의 관광 명소에 하위 요소를 생성할 수 있습니다. XMLElement에 대한 외부 호출은 <Attraction> 요소를 생성합니다. XMLElement에 대한 내부 호출은 중첩된 <Name>, <Location>, <URL> 요소를 생성합니다. XMLAttributes를 외부 XMLElement 함수 호출의 둘째 인수로 사용하는 것에 유의하십시오. XMLAttributes의 호출은 XMLElements에 선택적으로 쓸 수 있는 둘째 인수이며 이 경우에는 각 <Attraction> 태그에서 볼 수 있는 GOV 특성이 만들어집니다.

XMLElement 함수가 문자열 값이 아니라 XMLType 값을 반환한다는 점을 이해하는 것이 중요합니다. 목록에 문자가 표시되는 것은 SQL*Plus(Oracle9i Release 2)가 여러분이 선택한 모든 XMLType 값에 대해 XML 텍스트를 암묵적으로 추출하여 표시하기 때문입니다. SQL*Plus를 사용하여 이 문서에서 그 예제를 재현해 보려면, 여기에서 테이블 생성 스크립트를 다운로드하십시오. SQL*Plus에서는 XML 출력이 절단되지 않도록 SET LONG 2000 명령을 내리고, 선택적으로 SET PAGESIZE 80 명령을 내려 XML 출력에 성가신 페이지 구분이 생기지 않도록 합니다.


Null 요소의 처리

관계형 데이타를 다룰 때는 null 값이 나타날 가능성을 반드시 고려해야 합니다. 예를 들어 LOCATION 열이 일부 관광 명소에 대해 null인 경우에는 어떨까요? XMLElement을 사용하는 경우 null 열 값은 목록 2의 첫번째 질의와 결과에 나타난 바와 같이 빈 요소로 나타납니다. XML에 이러한 빈 요소를 두고 싶지 않다면 최소한 두 가지 해결책이 있습니다.

빈 XML 요소 생성을 방지하는 데 사용할 수 있는 방법 중 하나는 SQL CASE 표현식을 사용하여 열의 null 값을 테스트하고 null 또는 XMLElement의 결과를 반환하는 것입니다. 목록 2의 둘째 질의가 이 방법을 구현한 것입니다. 문제의 열이 null인 경우 각 CASE 표현식 결과는 항상 null이며, 내부 XMLElement 함수에 null이 아닌 값을 전달합니다. 외부 XMLElement은 null이 아닌 모든 값을 끌어모으며 빈 XML 요소가 될 모든 null은 무시됩니다.

빈 XML 요소 생성을 방지하는 또 다른 방법은 XMLForest 함수를 사용하는 것입니다. XML에서는 <Attraction> 아래 중첩된 요소들을 "포리스트(forest)"라 부릅니다. XMLForest를 이용하면 단 하나의 함수 호출을 가진 요소의 포리스트(forest)를 생성할 수 있습니다. 이러한 요소를 생성할 때 XMLForest는 null 값을 가진 요소들은 생략합니다. 이러한 결과를 다음 질의의 출력에서 볼 수 있습니다. 여기서 XMLForest는 질의 결과에서 null <location> 요소를 산출하지 않습니다.



SELECT XMLElement("Attraction",
  XMLAttributes(government_owned AS GOV),
    XMLForest(attraction_name AS "Name",
              Location AS "Location",
              attraction_url AS "URL"))
FROM attraction
WHERE attraction_name='Mackinac Bridge';

XMLELEMENT("ATTRACTION",XMLATTRIBUTES(GOV
-------------------------------------------------
<Attraction GOV="Y">
  <Name>Mackinac Bridge</Name>
<URL>http://www.mackinacbridge.org/</URL>

</Attraction>

이 질의는 XMLForest에 한 번 호출하므로 목록 2에서와 같이 XMLElement에 세 번 호출하는 경우보다 입력하기 쉽고 입력 오류의 여지도 적습니다. 두 경우 모두, 질의 결과에서 null 요소가 제거됩니다. XMLForest 사용의 단점은 요소 특성을 지정할 수 없다는 점입니다. 요소에 특성을 지정해야 한다면 반드시 XMLElement를 XMLAttributes와 함께 사용해야 합니다.

XML 요소의 집계

앞의 질의는 각 관광 명소마다 별도의 XML 문서를 생성했습니다. 이는 그다지 현실적인 시나리오는 아닙니다. 관광 명소에 대한 데이타를 비즈니스 파트너에게 제공하는 경우에는 어떤 식으로든 데이타를 집계하고자 할 것입니다. 예를 들어 한 나라의 모든 관광 명소를 한 데 모아 한 문서로 전송하고자 할 수도 있습니다. 이 경우에는 XMLAgg 함수를 GROUP BY 질의와 함께 사용하면 그렇게 할 수 있습니다.

XMLAgg는 MIN, MAX, AVG 등과 같은 집계 함수입니다. 이 함수 사용의 핵심은 어떤 같은 값에 따라 데이타를 그룹으로 묶는 것입니다. 목록 3에서 질의는 데이타를 나라 이름으로 묶습니다. 그러면 XMLAgg 함수는 해당 나라의 모든 개별 <Attraction> 요소들을 가져와 한 데 연결하여 단일한 XMLType 값으로 반환하고, 그 값은 <County> 요소를 생성하는 새로운 포함 XMLElement 함수 호출로 입력됩니다. 그 결과는 목록 3< county. per document XML one returns> 에서 확인 하실 수 있습니다. 목록 3에서 XMLAttributes이 여러 특성 값을 생성하는 데 사용되는 것을 보게 됩니다.

XMLAttributes에 대한 가장 바깥 쪽의 호출은 세 개의 특성 즉, 나라 이름에 대한 것 하나, 그리고 해당 문서가 따르는 XML 스키마를 가리키는 것 둘을 생성합니다. 여기서 질의는 GROUP BY이므로 가장 바깥 쪽의 XMLElement 함수 호출과 그와 연관된 XMLAttributes 호출은 요약된 열만을 참조할 수 있습니다. c.county_name 대신 a.county_name을 사용하면 오류가 나타나는데 이는 a.county_name이 GROUP BY 표현식이 아니기 때문입니다.


XML 뷰의 폴더링

Oracle9i Release 2의 XML 관련 기능 가운데 특히 뛰어난 것은 필자가 이 문서에서 XMLType 뷰를 만드는 토대로서 개발한 것과 같은 SQL/XML 질의를 사용할 수 있다는 점입니다. 이렇게 해서 여러분은 그 뷰를 '폴더링'하여 그 내용이 XML DB Repository의 디렉토리에 있는 XML 파일로 나타나게 할 수 있는 것입니다.
다음 단계
SQL/XML 표준 학습
sqlx.org

Oracle SQL/XML에 대한 상세 정보
otn.oracle.com/tech/xml/
xmldb/htdocs/sql_xml.html

이 문서의 테이블 생성 코드 다운로드
otn.oracle.com/oramag/oracle/03-may/o33xml_tablecreate.zip

XML DB 데모
otn.oracle.com/tech/xml/xmldb

관련 자료 읽기
/kr/magazine/webcolumns/2003/o13xml.html

XML DB에 대하여
/technology/global/kr/tech/xml/
 

Internet Explorer 또는 Microsoft Excel과 같은 애플리케이션을 이용하여 이러한 XML 파일들 중 하나를 열면 그 파일의 내용이 그 특정 XMLType 뷰를 생성하는 질의를 실행하여 그 자리에서 바로 생성됩니다. Microsoft Office XP 버전의 Microsoft Excel은 XML 파일 형식을 지원하므로 Excel이 예상하는 XML 스키마를 이용해서 XMLType 뷰를 생성하면 현재 데이타를 담은 스프레드시트를 데이타베이스에서 바로 열 수 있습니다.

목록 4는 이 문서에서 개발된 질의로부터 만들어진 XMLType 뷰를 보여주고 있습니다. (이러한 특정 CREATE VIEW 구문과 폴더링 기능은 Oracle9i Database Release 9.2.0.2 이상에서만 작동합니다.) CREATE VIEW 구문의 OBJECT ID 절은 뷰의 각 행에 고유한 객체 식별자를 생성합니다. 이 뷰는 각 나라마다 하나의 XML 문서(한 행)을 반환하며 이 문서에는 해당 나라의 관광 명소가 모두 나열됩니다. extractValue 함수에서 여러분이 볼 수 있는 sys_nc_rowinfo$에 대한 참조는 해당 뷰의 '현재' 행에 대한 참조입니다. XPath 질의 구문 '/County/@Name'은 extractValue가 각 <County> 요소의 Name 특성 값을 반환하게 만들며 이 값은 뷰에 의해 반환된 각 행에 고유한 식별자를 생성하는 토대로 사용됩니다.

뷰 단독으로는 해당 XML 문서를 저장소에 나타나게 하는 데 충분하지 않습니다. 또한 문서로서 나타나는 저장소 리소스를 만들어 각 리소스를 하나의 개체 식별자로 연결하는 것도 필요합니다. 목록 5의 PL/SQL 블록은 attraction_xml 뷰에 대해 이 작업을 수행합니다. 뷰를 쿼리하는 데에는 이것이 필수가 아니라는 점을 유의하십시오. 목록 5의 코드는 커서를 열어 뷰가 토대로 하고 있는 관광 명소 테이블로부터 모든 나라 이름을 검색합니다. MAKE_REF 함수에 대한 호출은 뷰의 결과 집합에서 모든 나라의 행에 대한 REF를 생성합니다. 마지막으로 이 REF는 DBMS_XDB.createResource에 대한 호출에 사용됩니다. createResource 함수는 XML DB Repository에서 리소스를 만들며 뷰의 결과 집합에 있는 해당 나라에 대한 데이타로 그 리소스를 연결합니다. 저장소에서 리소스는 .xml 파일로 나타납니다.

목록 5의 코드를 실행하기 전에 저장소에서 /ATTRACTIONS라는 이름의 폴더를 만들어야 함에 유의하십시오. 이 폴더에서 PL/SQL 코드는 해당 뷰를 참조하는 XML 문서를 만듭니다.


계속 정진하십시오!

Oracle9i Database의 SQL/XML에 대한 Oracle의 지원은 기존 관계형 데이타로부터 XML 데이타를 생성하는 작업을 매우 쉽게 해줍니다. SQL/XML 함수를 이용하면 XML 요소, 중첩 XML 요소, XML 요소의 집계, 등을 쉽게 만들 수 있습니다. 자체 내장된 XMLType 데이타 유형을 이용하면 데이타베이스에서 XML을 자연스럽게 다룰 수 있습니다. SQL/XML 방식 뷰, XML DB Repository, 폴더링 기능 등으로 구성되는 강력한 조합을 이용하여 여러분은 XML을 통해 데이타를 Microsoft Excel과 같은 애플리케이션에서 바로 이용할 수 있게 만들 수 있습니다. 앞으로 관계형 데이타로부터 XML을 생성할 계획이거나 그렇게 될지 모른다고 생각한다면 XMLType 및 다양한 SQL/XML 함수들을 익혀 보도록 하십시오.

Jonathan Gennick (Jonathan@Gennick.com)은 많은 경험을 갖춘 Oracle DBA이자 Oracle Certified Professional입니다. 그는 새로운 Oracle 기술을 탐구하는 것을 좋아하며 최근에는 Oracle SQL*Plus Pocket Reference, Second Edition(O'Reilly & Associates, 2002)을 탈고했습니다.

본 기사의 원문은 /technology/oramag/oracle/03-may/o33xml.html에서 확인하실 수 있습니다.
반응형