XQuery를 사용한 XML 데이터 업데이트

 

-      Version :  SQL Server 2005,2008, 2008R2, 2012

 

XML의 값을 수정하는 방법에는 무엇이 있을까? XML 편집기 등을 이용하여 사용자가 직접 수정 할 수도 있지만 XML노드와값을 정확하게 수정하려면 XQuery를 사용하여 수정 할 수 있다.

XQuery는 구조화 되었거나 반구조화된 XML 데이터를 쿼리할 수 있는 언어이다. XQuery는 기존의XPath 쿼리 언어를 기반으로 더 나은 반복 성능 및 정렬 결과를 위한 지원이 추가 되었다.

자세한 내용은 MSDN을 참고한다.

 

[노드삽입]

삽입 키워드는 다음과 같은 구조를 사용한다.

Insert Expression1 ({as first | as last}into | after | before Expression2)

삽입 키워드를 통하여 샘플 테이블을 생성 한다.

CREATE TABLE HR_XML (ID INT IDENTITY, SALARIES XML)

GO

INSERT HR_XML VALUES(

    '<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 * FROM HR_XML

GO

 

     

 

 

<Account / >라는 새로운 노드를 생성하려면 INSERT 구문을 이용하여 수행 할 수 있다.

UPDATE HR_XML

SET Salaries.modify('insert <Accounting /> into (/Salaries)[1]')

GO

 

SELECT * FROM HR_XML

GO

 

 

 

위의 쿼리에서 보면 Salaries [1] 노드에 대해 Singleton Designation 값이 지정된 것을 확인 할 수 있다.Singleton Designation 없이 쿼리를 실행하면 오류가 발생 한다.

UPDATE HR_XML

SET Salaries.modify('insert <Accounting /> into (/Salaries)')

GO

 

 

 

[원하는위치 노드 추가]

노드를 추가하면 기존의 노드 이후에 삽입되는 것을 확인 할 수 있다. (위그림 참조). 원하는 위치에 노드를 삽입하는 방법을 알아 보자실습에서는 <Salaries> 아래 첫번째 노드에 삽입을 하여 보자. Firstinto 명령어를 이용한다.

UPDATE HR_XML

SET Salaries.modify('insert <Accounting /> as first into (/Salaries)[1]')

GO

 

select * from HR_XML

GO

 

 

 

첫번째 노드 <Account /> Employee 노드(ID, tier)를 입력 해보자노드를 입력 할 때 속성을 포함해야 한다. SingletonDesignation [2] 지정으로 <Account>노드 바로 아래 <Employee>가 삽입 되는 것을 확인 할 수 있다.

UPDATE HR_XML

SET Salaries.modify('insert <Employee ID="4" tier="4" /> into (/Salaries/Accounting)[1]')

GO

 

select * from HR_XML

GO

 

 

 

[특정노드를 식별하여 삽입]

특정 Employee의 노드에 새 노드를 삽입하여 보자. @ID 인수를 사용하여 Employee를 식별 할 수 있다실습에서는 Employee ID = 2인 노드를 찾아서 새로운 노드를삽입하였다.

UPDATE HR_XML

SET Salaries.modify('insert <Projects /> into (/Salaries/Marketing/Employee[@ID=("2")])[1]')

GO

 

select * from HR_XML

GO

 

 

 

[노드삽입과 값 삽입]

노드 삽입과 컬력션 삽입을 할 수 있다. Employee id =2의노드에 새로운 노드(Project ID = 1)과 값을 삽입한다.

UPDATE HR_XML

SET Salaries.modify('insert <Project ID="1"><Description>Organize new

    strategies</Description></Project> into

    (/Salaries/Marketing/Employee[@ID=("2")]/Projects)[1]')

GO

 

select * from HR_XML

GO

 

 

 

[다른노드 값을 참조하여 노드 삽입]

Employee id = 1의 값을 참조하여 Employee ID = 4 <Salary>노드를 추가하여보자중괄호를 사용하여 명시적으로 노드를 지정한 것을 확인 할 수 있다.

UPDATE HR_XML

SET Salaries.modify('insert

<Salary>{(/Salaries/Marketing/Employee[@ID=("1")]/Salary/text())}</Salary>

into (/Salaries/Accounting/Employee[@ID=("4")])[1]')

GO

 

select * from HR_XML

GO

 

 

 

[노드삭제]

노드 삭제는 노드 삽입보다 간단하다표현식은

Delete Expression 이다노드 마지막의 <Account />노드를 삭제 하여 보자.

UPDATE HR_XML

SET Salaries.modify('delete (/Salaries/Accounting)[2]')

GO

 

select * from HR_XML

GO

 

 

 

[값삭제]

값 삭제는 텍스트() 함수를 사용하여 삭제 할 수 있다.

UPDATE HR_XML

SET Salaries.modify('delete

(/Salaries/Marketing/Employee[@ID=("2")]/Projects/Project[@ID="1"]/Description/text())[1]')

GO

 

select * from HR_XML

GO

 

 

 

[값수정]

Exployee ID = 2<Salary> 값을 수정하여 보자.

UPDATE HR_XML

SET Salaries.modify('replace value of

(/Salaries/Marketing/Employee[@ID=("2")]/Salary/text())[1] with ("60000")')

GO

 

select * from HR_XML

GO

 

 

 

[XQuery의산술값을 이용한 수정]

모든 Exployee에 대해서<Salary>의 값이 10% 증가한 값을 수정할 수 있도록 반복문을 사용 할수 있다.

DECLARE @i INT = 1

WHILE @i <= 3

   BEGIN

 UPDATE HR_XML

 SET Salaries.modify('replace value of

 (/Salaries/Marketing/Employee[@ID=(sql:variable("@i"))]/Salary/text())[1]

 with (/Salaries/Marketing/Employee[@ID=(sql:variable("@i"))]/Salary)[1] * 1.01')

 SET @i+=1

   END

GO

 

select * from HR_XML

GO

 

 

 

[수정제한]

XQuery에서 Modify() 메소드는수정하려는 값을 SELECT와 함께 사용 할 수 없다.

SELECT Salaries.modify('replace value of

(/Salaries/Marketing/Employee[@ID=("2")]/Salary/text())[1]

with ("60000")')

FROM HR_XML

GO

 

 

 

 

기존의 값을 조회하여 수정하려면 다음과 같이 변수를 이용하여 사용하여야 한다.

DECLARE @x XML

SELECT @x = Salaries FROM HR_XML

SET @x.modify('replace value of (/Salaries/Marketing/Employee[@ID=("2")]/Salary/text())[1] with ("60000")')

SELECT @x

GO

 

 

 

쿼리문에서 UPDATE 구문을 동시에 2개 사용할 수 없다별도의 업데이트문을 사용하여야 한다.

UPDATE HR_XML

SET Salaries.modify('replace value of

(/Salaries/Marketing/Employee[@ID=("2")]/Salary/text())[1] with ("60000")'),

Salaries.modify('replace value of

(/Salaries/Marketing/Employee[@ID=("1")]/Salary/text())[1] with ("60000")')

GO

 

 

 

Employee ID = 2의 값을 참조하여 Employee ID = 1의 값을 업데이트 할 수 있다.

UPDATE HR_XML

SET Salaries.modify('replace value of

(/Salaries/Marketing/Employee[@ID=("1")]/Salary/text())[1]

with (/Salaries/Marketing/Employee[@ID=("2")]/Salary)')

GO

 

select * from HR_XML

GO

 

 

 

[계층값 변경]

@ID 값을 사용하여Employee ID = 1 tier = 4 값을tier =1로 변경 할 수 있다.

UPDATE HR_XML

SET Salaries.modify('replace value of

(/Salaries/Marketing/Employee[@ID=("1")]/@tier)[1] with "1"')

GO

 

select * from HR_XML

GO

 

 

 

 

XQuery를 사용하여 XMLDML 실습을 하였다많은 XML 편지기가있지만 SSMS를 이용하여 속성값을 사용하여 정확하게 수정할 때에 매우 유용하게 사용 할 수 있을 듯하다.

 

 

 Centos 에서 Objective-c 와 gcc 설치 법...

 

 

 

* WINVER
Using the Windows Headers
http://msdn.microsoft.com/en-us/library/aa383745(VS.85).aspx
_WIN32_WINNT ,WINVER
Windows 8    = 0x0602 (_WIN32_WINNT_WIN8 )
Windows 7    = 0x0601 (_WIN32_WINNT_WIN7 )
Windows Server 2008 = 0x0600
Windows Vista        = 0x0600
Windows Server 2003 with SP1, Windows XP with SP2    = 0x0502
Windows Server 2003, Windows XP    = 0x0501
Windows 2000    = 0x0500



* _MSC_VER
Visual Studio Version ( msc_ver )
https://en.wikipedia.org/wiki/Microsoft_Visual_Studio#Version_history
VC 4.0 (1995) = 1000
VC 5.0 (1997) = 1100
VC 6.0 (1998) = 1200  <----
VC 7.0 (2002) = 1300
VC 7.1 (2003) = 1310
VC 8.0 (2005) = 1400
VC 9.0 (2008) = 1500
VC 10.0 (2010) = 1600  - msvcr100.dll
VC 11.0 (2012) = 1700

출처 : http://polyphagia.egloos.com/10231978


아래 내용을 쿼리분석기에서 실행하면 찾으려는 단어가 포함된 프로시저 명을 알려준다.

단위는 데이터베이스 단위로 검색이 이루어져 특정 문자가 들어간 프로시저를 찾을때 용이하다.

 

-- 프로시저 검색
SELECT O.name
FROM   sysobjects O JOIN syscomments C
ON     O.id = C.id
WHERE  O.type = 'P' AND C.text LIKE '%찾으려는 단어%'


Windows에서 개발을 한 경험이 있는 분들이라면, AQTime(예전 이름은 Memproof)이라는 상용 Tool을 잘 아실 것입니다.

AQTime은 Runtime 검사를 통해서 Application의 Performance를 진단하고 Memory Leak(Heap Memory를 할당했을 경우 사용 후에 System에 반환하지 않아서 발생하는 누수현상)을 검사할 수 있는 유명한 Profiling Tool입니다.

이러한 Profiling Tool을 사용하면 개발자가 미처 파악하지 못한 Application의 문제를 해결하고 Performance를 향상시킬 수 있기 때문에 Project의 안정화 시에 주로 사용됩니다.

이번 Post에서는 이와 비슷한 기능을 Linux에서 수행하는 Command-line Tool인 Valgrind를 통해서 Memory Leak을 검사하는 방법을 알아보도록 하겠습니다.

Table of Contents [Show]

1. Valgrind?

Valgrind는 앞서 말한 대로 Linux Program의 Profiling을 위한 Application입니다. (지원하는 Platform과 Architecture를 확인하려면 여기를 방문하면 됩니다.) 그리고 License가 GPL이기 때문에 AQTime과 달리 사용하는데 전혀 비용이 들지 않습니다.

또한 수많은 Open-source Project가 Valgrind를 통해서 Debugging과 Profiling을 수행하고 있다는 것은 이 Program의 정확성과 안정성을 증명합니다.

Valgrind는 엄밀하게 말하면 Profiling Suite로 여러가지 Profiling을 위한 도구를 포함하고 있으며 각각의 도구는 valgrind 명령을 통해 통합되어 수행됩니다. 그 중 일부를 소개하면 다음과 같습니다.

  • Memcheck: Memory 관리의 문제를 진단하는 Tool입니다. 할당받지 않은 Heap Memory에 접근하는 것이나 Memory Leak과 같은 문제를 이 Tool을 통하여 발견할 수 있습니다.
  • Callgrind: Runtime 시에 각 함수의 호출 history와 실행 Function간의 Call Graph를 만들기 위한 정보를 기록하는데 사용하는 도구입니다. 저장된 내용은 Command-line Tool이나 KCachegrind를 통해서 분석할 수 있습니다. KCachegrind에 대해서는 이후에 간단한 사용법을 설명하겠습니다.
  • Massif: Heap Memory에 대한 사용 정보를 확인할 수 있습니다. 간단한 예제와 설명은 여기를 참고하기 바랍니다.
  • Helgrind: POSIX Thread(간단히 PThread)를 Program에서 사용할 때 각 Thread간의 동기화와 관련된 문제를 진단하기 위한 Tool입니다.

Valgrind는 좋은 Tool이지만 사용할 때 유의할 점이 있습니다. Valgrind는 Code 상의 오류를 검사할 수 있지만, 문맥적인 오류는 잡아내지 못합니다. 다시 말하면, 기술적으로 해당 Program이 문제가 없다는 것을 증명할 수는 있지만, 실제 그 Program이 사용자가 원하는 대로 제대로 동작한다는 것을 증명할 수 없다는 것입니다. 생각 외로 이런 Profiling Tool을 과신하는 경우가 종종 있는데 그런 점은 조심해야 합니다.

좀 더 자세한 Valgrind의 정보를 얻기 원한다면 다음 Link를 방문하기 바랍니다.

2. 설치

Valgrind를 설치하는 것은 간단합니다. Terminal을 새로 열어서 다음과 같이 입력하여 설치합니다.

1
sudo apt-get install valgrind

다음 Section에서는 Test Program을 Build하면서 설명을 진행합니다. System에 Build를 위한 Package가 설치되어있지 않다면 다음과 같이 입력하여 설치합니다.

1
sudo apt-get install build-essential

3. Memory Leak 검사하기

Valgrind가 무엇인지에 대해서 알아봤고 설치도 마쳤으니, 이제 Test Program을 만들어서 Valgrind의 Memcheck 도구를 사용하여 Memory Leak을 검사하는 방법을 알아봅시다.

Gedit나 Vim과 같은 편집기를 사용해서 다음과 같은 내용을 입력한 후 test.c라고 저장합시다.

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdlib.h>

void test(void)
{
    char *= malloc(sizeof(char) * 10);
}

int main(void)
{
    test();
    return 0;
}

위의 C Code를 보면 test()에서 malloc()을 통해서 Heap Memory를 할당받았지만 사용 후에 free()를 사용하여 System에 반환하지 않았기 때문에 Memory Leak이 발생하는 것을 알 수 있습니다.

이제 이 Source를 Compile해 봅시다. Terminal에서 다음과 같이 입력하여 Debugging이 가능하도록 Option을 적용하여 Compile합니다.

1
gcc -g -o test test.c

test.c를 Compile하여 생성된 test라는 실행 File에 대해서 이제 Valgrind를 사용하여 Memory Leak을 검사해 봅시다. Terminal에서 다음과 같이 입력하여 Valgrind를 실행합니다.

1
valgrind --leak-check=yes ./test

만약 Memory Leak을 검사할 Program이 Argument(명령행 인자)를 가지고 있다면, 위의 명령에서 검사할 Program 뒤에 그대로 이어서 적으면 됩니다.

위의 명령을 실행하면 먼저 test Program이 실행되고 종료된 후에 Valgrind가 검사한 정보가 Terminal에 출력됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
==8067== Memcheck, a memory error detector
==8067== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==8067== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==8067== Command: ./test
==8067== 
==8067== 
==8067== HEAP SUMMARY:
==8067==     in use at exit: 10 bytes in 1 blocks
==8067==   total heap usage: 1 allocs, 0 frees, 10 bytes allocated
==8067== 
==8067== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==8067==    at 0x4C28FAC: malloc (vg_replace_malloc.c:236)
==8067==    by 0x400505: test (test.c:5)
==8067==    by 0x400514: main (test.c:10)
==8067== 
==8067== LEAK SUMMARY:
==8067==    definitely lost: 10 bytes in 1 blocks
==8067==    indirectly lost: 0 bytes in 0 blocks
==8067==      possibly lost: 0 bytes in 0 blocks
==8067==    still reachable: 0 bytes in 0 blocks
==8067==         suppressed: 0 bytes in 0 blocks
==8067== 
==8067== For counts of detected and suppressed errors, rerun with: -v
==8067== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)

위의 내용은 Valgrind를 실행하여 얻은 출력화면입니다. 중요한 부분은 11~14번째 Line에 있는 Memory Leak정보로, 이것은 test.c의 5번째 줄에 위치한 test()의 Code에서 Memory Leak이 발생했다는 것을 나타냅니다.

이와 같이 Memory Leak 정보에 표시된 Call Stack을 통해서 Source Code의 어느 함수의 몇번째 Line에서 Memory Leak이 발생했는지를 확인할 수 있습니다.

유의해야할 점은, Valgrind는 검사할 Program을 실행한 상태(Runtime)에서 검사하기 때문에 실행 시에 수행되지 않은 Code에 대해서는 검사할 수 없다는 것입니다. 그래서 Test Case를 잘 수행하지 않으면 Memory Leak을 검사하지 못할 수 있기 때문에 실행하기 전에 Test Case를 미리 준비하는 것이 좋습니다.

4. 마치면서…

지금까지 Valgrind를 사용하여 Memory Leak을 검사하는 방법을 간단하게 알아봤습니다. 다음 Post에서는 Valgrind의 Front-end를 사용하여 좀 더 쉽게 Memory Leak을 검사하는 방법과 Eclipse CDT로 Program을 개발했을 때 Eclipse 상에서 Valgrind를 사용하는 방법에 대해서 알아보도록 하겠습니다.


출처 : http://ioriy2k.pe.kr/archives/3754

+ Recent posts