XML의 값을 수정하는 방법에는 무엇이 있을까? XML 편집기 등을 이용하여 사용자가 직접 수정 할 수도 있지만 XML노드와값을 정확하게 수정하려면 XQuery를 사용하여 수정 할 수 있다.
XQuery는 구조화 되었거나 반구조화된 XML 데이터를 쿼리할 수 있는 언어이다. XQuery는 기존의XPath 쿼리 언어를 기반으로 더 나은 반복 성능 및 정렬 결과를 위한 지원이 추가 되었다.
자세한 내용은 MSDN을 참고한다.
[노드삽입]
삽입 키워드는 다음과 같은 구조를 사용한다.
Insert Expression1 ({as first | as last}into | after | before Expression2)
삽입 키워드를 통하여 샘플 테이블을 생성 한다.
CREATETABLEHR_XML(IDINTIDENTITY,SALARIESXML)
GO
INSERTHR_XMLVALUES(
'<SALARIES>
<MARKETING>
<EMPLOYEE ID="1" TIER="4">
<SALARY>42000</SALARY>
</EMPLOYEE>
<EMPLOYEE ID="2" TIER="1">
<SALARY>52000</SALARY>
</EMPLOYEE>
<EMPLOYEE ID="3" TIER="4">
<SALARY>48000</SALARY>
</EMPLOYEE>
</MARKETING>
</SALARIES>
'
)
GO
SELECT*FROMHR_XML
GO
<Account / >라는 새로운 노드를 생성하려면 INSERT 구문을 이용하여 수행 할 수 있다.
UPDATEHR_XML
SETSalaries.modify('insert <Accounting /> into (/Salaries)[1]')
GO
SELECT*FROMHR_XML
GO
위의 쿼리에서 보면 Salaries [1] 노드에 대해 Singleton Designation 값이 지정된 것을 확인 할 수 있다.Singleton Designation 없이 쿼리를 실행하면 오류가 발생 한다.
UPDATEHR_XML
SETSalaries.modify('insert <Accounting /> into (/Salaries)')
GO
[원하는위치 노드 추가]
노드를 추가하면 기존의 노드 이후에 삽입되는 것을 확인 할 수 있다. (위그림 참조). 원하는 위치에 노드를 삽입하는 방법을 알아 보자. 실습에서는 <Salaries> 아래 첫번째 노드에 삽입을 하여 보자. Firstinto 명령어를 이용한다.
UPDATEHR_XML
SETSalaries.modify('insert <Accounting /> as first into (/Salaries)[1]')
GO
select*fromHR_XML
GO
첫번째 노드 <Account />에 Employee 노드(ID, tier)를 입력 해보자. 노드를 입력 할 때 속성을 포함해야 한다. SingletonDesignation [2] 지정으로 <Account>노드 바로 아래 <Employee>가 삽입 되는 것을 확인 할 수 있다.
UPDATEHR_XML
SETSalaries.modify('insert <Employee ID="4" tier="4" /> into (/Salaries/Accounting)[1]')
GO
select*fromHR_XML
GO
[특정노드를 식별하여 삽입]
특정 Employee의 노드에 새 노드를 삽입하여 보자. @ID 인수를 사용하여 Employee를 식별 할 수 있다. 실습에서는 Employee ID = 2인 노드를 찾아서 새로운 노드를삽입하였다.
UPDATEHR_XML
SETSalaries.modify('insert <Projects /> into (/Salaries/Marketing/Employee[@ID=("2")])[1]')
GO
select*fromHR_XML
GO
[노드삽입과 값 삽입]
노드 삽입과 컬력션 삽입을 할 수 있다. Employee id =2의노드에 새로운 노드(Project ID = 1)과 값을 삽입한다.
UPDATEHR_XML
SETSalaries.modify('insert <Project ID="1"><Description>Organize new
XQuery는 XML에 대한 쿼리 언어입니다. XML 데이터를 조회하기 위한 XQuery 표현식 기반 xml 데이터형의 메서드를 살펴보고 XQuery 구문에 대해서 살펴봅니다. XQuery 구문에는 XPath 2.0 표현식이 포함되어 있으며, XQuery를 사용하여 XML 데이터원본에 복잡한 쿼리를 실행할 수 있습니다. SQL Server 에 제공하는 xml 데이터형에서는 XQuery 표현식을 사용하여 xml 데이터를 조회하고 변경하기 위해서 사용할 수 있는 메서드를 제공합니다. SQL Server 2005의 XQuery 지원기능은 W3C XQuery 1.0 언어 스펙을 기초로 합니다. ( http://www.w3.org/XML/Query 참조)
XQuery 구문
XQuery는 크게 두가지 부분으로 구성됩니다. 네임스페이스를 선언하고, 스키마를 추가하기 위한 머리글 부분(생략가능)과 xml 데이터를 조회하기 위해서 사용하는 실제 XQuery 표현식이 포함된 본문 부분으로 나눌 수 있습니다. XQuery 표현식은 조회하고자 하는 XML 노드에 대한 간략한 경로 정보일 수도 있고, XML 결과를 생성하기 위한 복잡한 표현식일 수도 있습니다.
XQuery 경로는 XPath 언어를 기반으로 하며, XML 문서상에서 조회하고자 하는 노드의 위치를 나타냅니다. 경로는 절대경로(루트 엘리먼트로부터 XML 트리의 특정 노드의 위치를 표현)로 지정될 수도 있고, 상대경로(이미 알려진 노드로부터 조회하고자 하는 노드의 위치를 상대적으로 표현)로 지정될 수도 있습니다. 다음의 표는 간단한 XQuery 경로 예제를 나타냅니다.
FLOWR 문장
XQuery 언어 스펙에 포함되어 있는 for, let, order by, where, return 문장을 통상적으로 FLOWR “( flower”라고 읽음) 라고 부릅니다. SQL Server 2005에서는 for, where, return 문장을 지원하며, 각각의 사용용도는 다음과 같습니다.
다음의 예제는 각 엘리먼트별로 자식 엘리먼트에 포함된 하나 이상의 엘리먼트의 목록을 반환합니다.
for $i in /InvoiceList/Invoice where count($i/Items/Item) > 1 return $i
SQL Server 2005 XML 데이터형은 XML 데이터를 쿼리하고 수정하기 위해서 사용할 수 있는 네 가지 메서드를 제공합니다. 각 메서드는 대부분의 개발자에게 익숙한 구문인 데이터형.메서드_명칭으로 호출할 수 있습니다. 각 메서드의 기능에 대해서 이해하면, XML 데이터를 데이터베이스에서 처리하는 어플리케이션을 개발하는데 도움이 될 것입니다.
Query 메서드
Query 메서드는 XML 데이터형에 저장된 데이터에서 XML을 추출하기 위해서 사용합니다. Query 메서드의 매개변수로 전달되는 XQuery 표현식에 지정된 결과값이 조회됩니다.
SELECT xmlCol.query‘( declare default namespace =
“http://schemas.adventure-works.com/InvoiceList”;
<InvoiceNumbers>
{
for $i in /InvoiceList/Invoice
return <InvoiceNo>
{number($i/@InvoiceNo)}
</InvoiceNo>
}
</InvoiceNumbers>’
Value 메서드
Value 메서드는 XML 문서로부터 단일 값을 반환하기 위해서 사용합니다. value 메서드를 사용하기 위해서는 XQuery 표현식을 XML 데이터에 포함된 단일 노드를 식별할 수 있는 형태로 지정해야 하며, 반환되는 값이 T-SQL 데이터형이 되도록 지정해야 합니다.
SQL Server 2005에서는 XQuery 언어를 사용하여 xml 데이터형 컬럼을 조회하기 위한 메서드가 포함된 SELECT 문장에서, 관계형 데이터 컬럼을 참조할 수 있도록 지원합니다. XML 데이터형 컬럼으로부터 XML 데이터를 조회하기 위해, XML 데이터형 메서드가 포함된 SELECT 문장에서, sql:column 함수를 사용하여, XML 데이터안에 비-xml 데이터 컬럼값을 포함시킬 수 있습니다. 또한, sql:variable 확장을 사용하여, 저장 프로시저내에서 변수를 참조할 수 있습니다. XML 데이터내부에 비-xml 컬럼 값을 포함시키기 위해, sql:column 함수를 사용하는 예제는 다음과 같습니다.
SELECT StoreName, Invoices.query‘( declare default namespace=
“http://schemas.adventure-works.com/Invoices”;
<Invoices>
<Store>{sql:column“( StoreName”)}</Store>
{
for $i in /InvoiceList/Invoice
return $i
}
</Invoices>’) InvoicesWithStoreName
FROM Stores
Modify 메서드를 사용하여 XML 데이터 변경
XML 데이터형 컬럼에 저장된 XML 데이터를 변경하기 위해서 Modify 메서드를 사용합니다. Modify 메서드는 XQuery 언어 스펙에 대해 insert, replace, delete 확장기능을 지원합니다. 세 가지 확장기능은 XML DML로서 참조할 수 있습니다.
INSERT 문장을 사용하여 XML 데이터에 노드를 추가할 수 있습니다.
REPLACE 문장을 사용하여 XML 데이터를 변경할 수 있습니다.
DELETE 문장을 사용하여 XML 데이터에서 특정 노드를 삭제할 수 있습니다.
INSERT 문장
Modify 메서드와 함께 INSERT 문장을 사용하여, XML 데이터형 컬럼이나 변수에 저장된 XML 데이터에 노드를 추가할 수 있습니다. INSERT 문장에 대한 구문은 다음과 같습니다.
insert Expression1 ( {as first | as last} into | after | before Expression2 )
INSERT 키워드에 지정할 수 있는 매개변수는 다음과 같습니다.
다음 예제는 Modify 메서드와 함께 INSERT Xquery 문장을 사용하는 방법을 나타냅니다.
SET @xmlDoc.modify
‘( declare default namespace = “ http://schemas.adventureworks.
com/InvoiceList”;
insert element salesperson “{ Bill”}
as first into (/InvoiceList/Invoice)[1]’
replace 문장
XML 데이터를 변경하기 위해서 modify 메서드와 함께 REPLACE 문장을 사용합니다. REPLACE 문장에 대한 구문은 다음과 같습니다.
replace value of Expression1 with Expression2
REPLACE 문장에서 사용할 수 있는 매개변수는 다음과 같습니다.
다음의 예제는 Modify 메서드와 함께 REPLACE 문장을 사용하는 방법을 나타냅니다.
SET xmlCol.modify
‘( declare default namespace =”http://schemas.adventure-works.com/InvoiceList”;
replace value of (/InvoiceList/Invoice/SalesPerson/text( ))[1]
with“ Ted”’)
DELETE 문장
XML 데이터에서 지정된 노드를 삭제하기 위해서 Modify메서드와 함께 DELETE 문장을 사용합니다. DELETE 문장에 대한 구문은 다음과 같습니다.
delete Expression
Expression 매개변수는 삭제할 노드를 지정하기 위한 XQuery 표현식입니다. 다음 예제는 modify 메서드와 함께 DELETE 문장을 사용하는 방법을 나타냅니다.
SET xmlCol.modify
‘( declare default namespace =”http://schemas.adventure-works.com/InvoiceList”;
delete (/InvoiceList/Invoice/SalesPerson)[1]’)
Nodes 메서드를 사용하여 XML 데이터 부분추출
Xml 데이터형에서는 nodes 메서드를 통해, XML 데이터를 관계형 테이블 형식으로 생성할 수 있는 기능을 제공합니다. Nodes 메서드는 XQuery 표현식으로 지정된 각 노드를 행집합 형식으로 반환합니다.
nodes 메서드의 구문은 다음과 같습니다.
xmlvalue.nodes (XQuery) [AS] Table(Column)
Nodes 메서드에서 사용할 수 있는 매개변수는 다음과 같습니다.
Xml 데이터형 변수나 컬럼에서 nodes 메서드를 사용하여 관계형 테이블 형식의 데이터를 조회할 수 있습니다.
XML 데이터형 변수에서 관계형 테이블 형식의 데이터를 추출하기 위해서, nodes 메서드에서 반환하는 결과행집합에 대해서, query, value, exist와 같은 메서드를 사용합니다.
Xml 데이터형 컬럼에서 관계형 테이블 형식의 데이터를 반환하기 위해서, nodes 메서드와 함께 APPLY 연산자를 사용합니다.
XML 변수에 대해 nodes 메서드 사용법
Xml 데이터형 변수에서 관계형 테이블 형식의 데이터를 추출하기 위해서, nodes 메서드에서 반환하는 행집합에 query, value, exist 메서드를 사용할 수 있습니다. 다음 예제는 xml 변수에서 관계형 테이블 형식의 주문 데이터를 추출하는 방법을 나타냅니다.
DECLARE @xmlOrder xml
SET @xmlOrder =‘ <?xml version=”1.0”?>
<Order OrderID=”1000”OrderDate=”2005-06-04”>
<LineItem ProductID=”1”Price=”2.99”Quantity=”3”/>
<LineItem ProductID=”2”Price=”3.99”Quantity=”1”/>
</Order>’
SELECT nCol.value‘( @ProductID’,‘ integer’) ProductID,
nCol.value‘( @Quantity’,‘ integer’) Quantity
FROM @xmlOrder.nodes‘( /Order/LineItem’) AS nTable(nCol)
위의 코드를 실행하면 다음과 같은 결과가 반환됩니다.
XML 컬럼에 대해 nodes 메서드 사용하는 방법
Xml 컬럼에서 관계형 테이블 형식의 데이터를 반환하게 하기 위해서, nodes 메서드와 함께 APPLY 연산자를 사용합니다. 다음 예제는 nodes 메서드를 사용하여 XML 컬럼으로부터 주문 데이터를 추출하는 방법을 나타냅니다.
SQL Server 2012 에서 XML 문서를 테이블에 Bulk Insert 하는 방법과 XQuery 를 사용하여 XML 데이터를 검색하는 몇 가지 예제를 아래와 같이 정리하였습니다.
1. XML 원본 문서를 테이블에 Bulk Insert 하는 방법
CREATE DATABASE XMLDB GO
USE XMLDB GO
CREATE TABLE TBL_XML ( ID INT IDENTITY PRIMARY KEY, XMLDATA XML ) GO
INSERT INTO TBL_XML(XMLDATA) SELECT * FROM OPENROWSET ( BULK 'D:\SQL\BOOKS.XML', SINGLE_BLOB) AS x;
2. XQuery 를 사용하여 XML 데이터 검색 예제
CREATE TABLE TBL_XQUERY ( ID INT IDENTITY PRIMARY KEY, XMLDATA XML ) GO
INSERT INTO TBL_XQUERY VALUES (' <CATALOG> <book id="bk101"> <author>Gambardella, Matthew</author> <title>XML Developer''s Guide</title> <genre>Computer</genre> <price>44.95</price> <publish_date>2000-10-01</publish_date> <description>An in-depth look at creating applications with XML.</description> </book> </CATALOG> ')
INSERT INTO TBL_XQUERY VALUES (' <CATALOG> <book id="bk102"> <author>Ralls, Kim</author> <title>Midnight Rain</title> <genre>Fantasy</genre> <price>5.95</price> <publish_date>2000-12-16</publish_date> <description>A former architect battles corporate zombies, n evil sorceress, and her own childhood to become queen of the world.</description> </book> </CATALOG> ')
INSERT INTO TBL_XQUERY VALUES (' <CATALOG> <book id="bk103"> <author>Corets, Eva</author> <title>Maeve Ascendant</title> <genre>Fantasy</genre> <price>5.95</price> <publish_date>2000-11-17</publish_date> <description>After the collapse of a nanotechnology society in England, the young survivors lay the foundation for a new society.</description> </book> </CATALOG> ')
SELECT XMLDATA.query('/CATALOG/book') FROM TBL_XQUERY WHERE ID = 2 /* <book id="bk102"> <author>Ralls, Kim</author> <title>Midnight Rain</title> <genre>Fantasy</genre> <price>5.95</price> <publish_date>2000-12-16</publish_date> <description>A former architect battles corporate zombies, n evil sorceress, and her own childhood to become queen of the world.</description> </book> */
SELECT XMLDATA.value ( '(/CATALOG/book/@id)[1]', 'char(5)' ) AS 'Book id' FROM TBL_XQUERY /* bk101 bk102 bk103 */
SELECT XMLDATA FROM TBL_XQUERY WHERE XMLDATA.exist('/CATALOG/book[@id="bk103"]') = 1 /* <CATALOG> <book id="bk103"> <author>Corets, Eva</author> <title>Maeve Ascendant</title> <genre>Fantasy</genre> <price>5.95</price> <publish_date>2000-11-17</publish_date> <description>After the collapse of a nanotechnology society in England, the young survivors lay the foundation for a new society.</description> </book> </CATALOG> */
SELECT nCol.value('@id', 'char(5)') AS 'Book id', nCol.value('(author)[1]', 'varchar(10)') AS author, nCol.value('(title)[1]', 'varchar(50)') AS title, nCol.value('(genre)[1]', 'varchar(10)') AS genre FROM TBL_XQUERY CROSS APPLY XMLDATA.nodes('/CATALOG/book') AS nTbl(nCol) ORDER BY ID /* bk101 Gambardell XML Developer's Guide Computer bk102 Ralls, Kim Midnight Rain Fantasy bk103 Corets, Ev Maeve Ascendant Fantasy */