xml
문서를 만들거나 이미 만들어진 xml
문서를 읽어 올 경우 쿼리로 작업이 가능합니다
이 경우 Select내용을 xml
로 만들거나 만들어진 xml
을 테이블 결과로 불러오는 방법이 있는데 for xml explicit과 for xml auto를 이용하여 xml문서로 select결과를 만들수 있으며 다음과 같습니다
-- Make xml message
declare @msg nvarchar(max) = '';
set @msg = @msg + '<mgp title="player_info">';
set @msg = @msg + convert(nvarchar(max),
(
select 1 as tag
, null as parent
, player_id as [player!1!player_id]
, player_name as [player!1!player_name]
, nickname as [player!1!nickname]
, back_no as [player!1!back_no]
from dbo.player with(nolock)
where player_id in (2000001, 2000002, 2000003)
for xml explicit
));
set @msg = @msg + convert(nvarchar(max),
(
select 2 as tag
, null as parent
, player_id as [coach!2!player_id]
, player_name as [coach!2!player_name]
, nickname as [coach!2!nickname]
, back_no as [coach!2!back_no]
from dbo.player with(nolock)
where player_id in (2000031, 2000032, 2000033)
for xml explicit
));
set @msg = @msg + '</mgp>';
위의 경우는 데이터 테이블의 결과를 xml로 만드는 과정입니다. select문에 from xml explicit
를 추가함으로써 테이블 형식의 쿼리결과를 xml형태의 문서로 변환할 수 있습니다
xml로 변환시 tag
와 parent
부분을 꼭 써줘야 하는데 해당영역은 Select요소에 대한 고유 Tag번호 이며, Parent를 이용하여 xml계층구조를 만들 수 있게되는 값입니다
xml로 변환시에 Select
절에 다음과 같은 형식으로 써야합니다
xml속성값 명칭 as [태그명!Tag번호!Table에서 선택할 칼럼명]
쿼리의 결과를 <mgp>~</mgp>
로 묶은 이유는 xml문서에서 depth를 만들기 위함이며 다음과 같은 결과로 받아올 수 있습니다
<mgp title="player_info">
<player player_id="2000001" player_name="김태호" nickname="" back_no="0" />
<player player_id="2000002" player_name="정상수" nickname="" back_no="0" />
<player player_id="2000003" player_name="유동우" nickname="" back_no="40" />
<coach player_id="2000031" player_name="차경복" nickname="" back_no="0" />
<coach player_id="2000032" player_name="정학범" nickname="" back_no="0" />
<coach player_id="2000033" player_name="안익수" nickname="" back_no="0" />
</mgp>
위의 내용은 @msg
변수를 Select했을시 값입니다. mgp로 xml depth를 나눴는데 쿼리의 결과를 단위별로 묶으면 불러올 때 어떤내용인지 관리하기 편리합니다
아래의 내용은 위에서 만든 @msg
변수를 다시 Select절로 불러오려고 할 때의 방법입니다
sp_xml_preparedocument
라는 DBMS내장 도움말 함수를 이용하여 xml을 불러올수 있으며 @h_xml
값은 @msg(xml형식)를 고유의 핸들링 할수있는 정수값으로 변환합니다
즉, @h_xml의 정수값은 @msg와 같은 것이라고 볼 수 있습니다
-- Open xml message
declare @h_xml int = 0
exec sp_xml_preparedocument @h_xml output, @msg
select title
from openxml(@h_xml, '/mgp', 1)
with
(
title varchar(20)
)
select player_id
, player_name
, nickname
, back_no
from openxml(@h_xml, '/mgp/player', 1)
with
(
player_id char(7)
, player_name varchar(20)
, nickname varchar(30)
, back_no tinyint
)
select player_id
, player_name
, nickname
, back_no
from openxml(@h_xml, '/mgp/coach', 1)
with
(
player_id char(7)
, player_name varchar(20)
, nickname varchar(30)
, back_no tinyint
)
xml문서를 열 때 어느영역까지 열 것 인지 경로로 판단하여 값을 가져옵니다
'/mgp'
까지의 경로에는 title항목 밖에 없기 때문에 title값만 가져올 수 있습니다
'/mgp/player'
로 경로를 설정시에는 mgp하위의 player태그의 값들만 가져와서 select 할수 있으며 '/mgp/coach'
로 경로를 설정시에는 mgp하위의 coach태그의 값들만 가져올 수 있습니다
for xml explicit
를 이용하여 xml계층구조를 이용할 경우에는 아래의 스크립트를 참고하시면 됩니다
Execute Script
SELECT
1 AS Tag,
NULL AS Parent,
'2.17' AS [Root!1!Version],
'XX-DD 389' AS [Root!1!KFZ],
NULL AS [Head!2!name!Element],
NULL AS [Key!3!name],
NULL AS [Key!3!value],
NULL AS [Key!3!!CDATA],
NULL AS [Section!4!name],
NULL AS [Key!5!name],
NULL AS [Key!5!value],
NULL AS [Key!6!name],
NULL AS [Key!6!!CDATA]
UNION ALL
SELECT
2 as Tag,
1 as Parent,
NULL,
NULL,
'ExecuteAnswer',
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
UNION ALL
SELECT
3 as Tag,
2 as Parent,
NULL,
NULL,
NULL,
'AnswerStatus',
'-OK',
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
UNION ALL
SELECT
3 as Tag,
2 as Parent,
NULL,
NULL,
NULL,
'MsgId',
NULL,
'KFHB0907896aAUH223',
NULL,
NULL,
NULL,
NULL,
NULL
UNION ALL
SELECT
4 as Tag,
2 as Parent,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
'Command',
NULL,
NULL,
NULL,
NULL
UNION ALL
SELECT
5 as Tag,
4 as Parent,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
'Name',
'SetNewCommand',
NULL,
NULL
UNION ALL
SELECT
6 as Tag,
4 as Parent,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
'Param0',
'XX-DD 389'
FOR XML EXPLICIT
Result Xml
<Root Version="2.17" KFZ="XX-DD 389">
<Head>
<name>ExecuteAnswer</name>
<Key name="AnswerStatus" value="-OK" />
<Key name="MsgId"><![CDATA[KFHB0907896aAUH223]]></Key>
<Section name="Command">
<Key name="Name" value="SetNewCommand" />
<Key name="Param0"><![CDATA[XX-DD 389]]></Key>
</Section>
</Head>
</Root>
위의 방법은 xml계층구조를 설정하고, Select절에 xml을 만들기 위한 세부사항을 입력 하여야 만들 수 있었는데 for xml auto
를 사용하면 더 간단하게 xml문서로 변환할 수 있게됩니다
-- Make xml message
declare @msg2 nvarchar(max) = '';
set @msg2 = @msg2 + '<mgp>';
set @msg2 = @msg2 + convert(nvarchar(max),
(
select player_id
, player_name
, nickname
, back_no
from dbo.player with(nolock)
where player_id in (2000001, 2000002, 2000003)
for xml auto, type
)
)
set @msg2 = @msg2 + '</mgp>';
쿼리의 where절 하단에 for xml auto
를 넣음으로써 쿼리의 결과를 xml로 바로 만들 수 있습니다. type을 사용하면 타입이 xml로 변환되지만 type을 사용하지 않으면 nvarchar(max)로 변환됩니다
위의 쿼리 결과인 xml을 표현하자면 다음과 같이 결과가 나옵니다
<mgp>
<dbo.player player_id="2000001" player_name="김태호" nickname="" back_no="0"/>
<dbo.player player_id="2000002" player_name="정상수" nickname="" back_no="0"/>
<dbo.player player_id="2000003" player_name="유동우" nickname="" back_no="40"/>
</mgp>
for xml auto, type
되어있는 부분을 for xml auto, elements
로 하게 되면 요소중심으로 xml결과값이 나와서 더 깊은 계층구조를 만들어 내며, 다음과 같은 결과값이 나오게 됩니다
<mgp>
<dbo.player>
<player_id>2000001</player_id>
<player_name>김태호</player_name>
<nickname></nickname>
<back_no>0</back_no>
</dbo.player>
<dbo.player>
<player_id>2000002</player_id>
<player_name>정상수</player_name>
<nickname></nickname>
<back_no>0</back_no>
</dbo.player><dbo.player>
<player_id>2000003</player_id>
<player_name>유동우</player_name>
<nickname></nickname>
<back_no>40</back_no>
</dbo.player>
</mgp>
xml변환시 다음과 같은 방법으로 xml결과를 테이블 형식으로 변환할 수 있습니다
declare @h_xml2 int = 0;
exec sp_xml_preparedocument @h_xml2 output, @msg2
select @msg2
select player_id
, player_name
, nickname
, back_no
from openxml(@h_xml2, '/mgp/dbo.player', 1)
with
(
player_id char(7)
, player_name varchar(20)
, nickname varchar(30)
, back_no tinyint
)
for xml explicit
을 사용할 때와 for xml auto
를 사용할 때의 분명한 차이는 있으나 계층구조를 단순하게 만들경우에는 사용방식에 큰 차이가 없게됩니다. xml을 이용한 작업을 할 때 필요에 따라 방법을 가져다 쓰면 유용합니다
for xml explicit
: https://docs.microsoft.com/ko-kr/sql/relational-databases/xml/use-explicit-mode-with-for-xml?view=sql-server-ver15
for xml auto
: https://docs.microsoft.com/ko-kr/sql/relational-databases/xml/use-auto-mode-with-for-xml?view=sql-server-ver15
for xml auto, type
: https://docs.microsoft.com/ko-kr/sql/relational-databases/xml/type-directive-in-for-xml-queries?view=sql-server-ver15