Programming/Microsoft SQL Server
XQuery는 XML을 조회한다는 개념에서 한발 더 나아가 직접 XML Data에 접근할 수 있도록 해줍니다. 이때 어떠한 방식으로 접근하느냐에 따라 3가지 형식으로 나뉩니다.

우선 XQuery를 사용하기 전에 먼저 Sample XML Data를 만든 후 이 XML Data를 대상으로 XQuery를 적용시켜 보도록 하겠습니다.

Declare @MyXml Xml;
Set @MyXml = '
<TopEle>
<Department ID="1">
  <Names Nm="Engineering">
    <Group>
      <Name>Research and Development</Name>
    </Group>
  </Names>
</Department>
<Department ID="2">
  <Names Nm="Tool Design">
    <Group>
      <Name>Research and Development</Name>
    </Group>
  </Names>
</Department>
<Department ID="3">
  <Names Nm="Sales">
    <Group>
      <Name>Sales and Marketing</Name>
    </Group>
  </Names>
</Department>
</TopEle>';

1. query

XML Data의 요소를 얻어오는데 사용되는 method입니다.

Select @MyXml.query('/TopEle[1]/Department[2]');

Data형식이 XML이면 그것이 변수든 Column이든 상관없이 XQuery를 적용시킬 수 있습니다. 위에서는 @MyXml 변수에 XQuery의 query를 적용시켜 원하는 요소를 가져오도록 하였습니다.

먼저 /TopEle[1]을 통해 첫번째 TopEle요소의 하위 Department요소중 두번째 요소(/Department[2])내용을 가져오도록 합니다. 보시는 바와 같이 각 요소는 '/'문자로 구분하며 요소의 순서는 []안에 지정합니다.


이번에는 변수를 사용하여 XML문서내에 있는 각 Name의 요소값을 가져와 보겠습니다.

Select @MyXml.query('for $s in /TopEle/Department/Names/Group/Name return data($s)');

query내에 있는 for는 반복을 의미합니다. 즉, XML의  /Top /TopEle/Department/Names/Group/Name요소를 반복적으로 모두 확인하여 변수 $s에 넣고(data($s)) 그 결과를 출력하도록 하는 것입니다.

주의 :
XQuery사용시 대/소문자를 명확히 구분합니다. 예를 들어 for를 For라고 하면 오류가 발생합니다.


이번에는 요소의 값이 아니라 속성의 값을 가져와 보도록 하겠습니다.

Select @MyXml.query('for $s in /TopEle/Department/@ID return data($s)');
Select @MyXml.query('for $s in /TopEle/Department/Names/@Nm return data($s)');

첫번째 XQuery에서는 /TopEle/Department의 ID속성값을 가져오도록 하였고 두번째 XQuery에서는 /TopEle/Department/Names요소의 Nm속성값을 가져오도록 하였습니다.

여기서 '/'는 요소를, '@'는 속성을 의미합니다.


또한 XQuery는 XML Data에서 다음처럼 조건에 맞는 내용만 가져올 수도 있습니다.

Select @MyXml.query('for $s in /TopEle/Department[@ID eq "2"] return $s');

/TopEle/Department요소의 ID속성을 찾아서 값이 2인것만([@ID eq "2"]) 가져오도록 합니다. (XQuery조건문으로 일치하는 값을 지정할 수 있도록 합니다.)

참고 :
Data($s)를 통해서 값을 가져오는 경우는 해당 변수에 특정 값이 존재할때만 가능합니다. 위에서 제시된 예제는 특정 값이 아니라 XML Data자체이므로 data()를 쓰지 않습니다.


다음은 다른 XML구문을 추가하여 조회하는 예제입니다.

Select @MyXml.query('for $s in /TopEle/Department return <myXml><NewValue>{data($s/@ID)}</NewValue><NewString>{data($s/Names/@Nm)}</NewString></myXml>');

XQuery결과에 상위 <myXml>요소를 추가하고 각 값마다 <NewValue>요소와 <NewString>요소를 추가하여 XML형태로 결과값을 반환하도록 하고 있으며 동시에 두가지 값을 가져오는 방법도 제시하고 있습니다.

이때 주목해야할 부분이 있는데 두번째 data($s/Names/@Nm)부분을 보시면 for에서 in다음에 /TopEle/Department요소를 지정하여 궁극적으로는 Nmes요소의 Nm속성값을 가져올 수 없을지도 모르지만 이렇게 값을 반환하는 부분에서 하위 요소와 속성을 지정하면(/Names/@Nm) 해당 요소와 속성의 값을 가져올 수 있게 됩니다.


2. value

query는 XML data내에서 각 요소자체를 주출하는 역활을 하지만  value는 요소가 아닌 값만을 가져올 수 있도록 합니다.

Select @MyXml.value('(/TopEle/Department[3])[1]', 'Char(50)');

TopEle전체요소중에서 Department세번째 요소에 있는 첫번째 값을 Char(50) Data형으로 가져옵니다.


value를 사용하면 단순히 값을 가져오는것 이외에 실제 값이 있는가 없는가를 판단할 수도 있습니다.

Select @MyXml.value('some $s in /TopEle/Department/Names satisfies $s/@Nm="Sales"', 'Char(50)');

some을 통해 /TopEle/Department/Names요소의 Nm속성값에 "Sales"가 있으면 true 없으면 false를 반환합니다. (비교자는 satisfies를 사용합니다.)


값을 비교하여 있는지 없는지 판단하는 것은 some이외에 every도 있습니다. some은 값 비교시에 해당 값이 있는 요소가 하나라도 일치하면 true가 되지만 every는 전 요소가 모두 주어진 조건에 일치해야만 true가 됩니다.

Select @MyXml.value('every $s in /TopEle/Department/Names satisfies $s/@Nm="Sales"', 'Char(50)');

Nm속성이 "Sales"라고 되어 있는건 Department/Names의 세번째 요소에서만 일치하므로 결과는 false입니다.


3. exist

values로는 값이 있는지 없는지를 확인할 수 있지만 exist는 요소자체가 있는지 없는지를 판단할 수 있습니다.

Select @MyXml.exist('/TopEle/Department');

/TopEle요소 하위에 Department요소가 있는지 판단한 후 있으면 1 없으면 0을 반환합니다.


4. modify

XML에 접근하여 실제 XML Data를 추가/변경/삭제 할 수 있는 mothod입니다.

(1) 추가

Set @MyXml.modify('insert <newstart>spadework</newstart> as first into /');
Set @MyXml.modify('insert <newend>spadework</newend> as last into /');

<newstart>spadework</newstart>요소와 값을 해당 XML Data의 가장 처음(as first into)에 추가하고 <newend>spadework</newend>를 해당 XML Data의 가장 마지막(as last into)에 추가합니다.


Set @MyXml.modify('insert <TopEle mytag="new"/> as first into /TopEle[1]');

<TopEle mytag="new"/>요소와 속성을 TopEle요소의 처음부분에 추가합니다.


Set @MyXml.modify('insert <TopEle mytag="new"/> as last into /TopEle[1]/Department[3]');

<TopEle mytag="new"/>요소와 속성을 TopEle/Department 3번째 요소의 마지막에 추가합니다.


(2) 변경

Set @MyXml.modify('replace value of /TopEle[1]/Department[3]/Names[1]/@Nm with "abc"');

replace value of 를 통해 TopEle/Department 세번째요소의 Names요소에서 Nm속성값을 abc로 변경합니다.


(3) 삭제

Set @MyXml.modify('delete /TopEle[1]/Department[2]');

delete를 통해 /TopEle/Department 2번째 요소 전체를 삭제하도록 합니다.

0 0