Sql Server表到具有多个子节点的XML

时间:2010-12-22 17:17:51

标签: sql-server xml tsql sql-server-2008

我有下表

name  | age | misc
------------------
david | 20  | foo
john  | 30  | bar

我想将其转换为以下XML:

<doc>
  <field name="name" val="david" />
  <field name="age" val="20" />
  <field name="misc" val="foo" />
</doc>
<doc>
  <field name="name" val="john" />
  <field name="age" val="30" />
  <field name="misc" val="bar" />
</doc>

我有以下工作用于单个列,但是如果我尝试为另一个field节点添加第二列,我会收到错误:

Msg 9303, Level 16, State 1, Line 25
XQuery [query()]: Syntax error near 'name', expected '}'.

这是我尝试做的一个示例,并准备在SQL Server Management Studio中运行。我找不到很多关于语法的文档,而且很遗憾。

感谢任何帮助!

declare @MyData table (name varchar(200), age varchar(200), misc varchar(200))

insert into @MyData values('david', '20', 'foo')
insert into @MyData values('john', '30', 'bar')

/*This one works fine*/
SELECT (select * from @MyData as MyData for xml auto, type).query
(
' for $d in /MyData
   return 
   <doc>{
     <field name="name" val="{data($d/@name)}"  />
  }</doc>'
)

/*This one is what I want*/
SELECT (select * from @MyData as MyData for xml auto, type).query
(
' for $d in /MyData
   return 
   <doc>{
     <field name="name" val="{data($d/@name)}"  />
     <field name="age" val="{data($d/@age)}"  />
     <field name="misc" val="{data($d/@misc)}"  />
  }</doc>'
)

2 个答案:

答案 0 :(得分:4)

这个怎么样..

select 
    (select 'name' as 'field/@name', a.name as 'field/@val' for xml path(''), type),
    (select 'age' as 'field/@name', a.age as 'field/@val' for xml path(''), type),
    (select 'misc' as 'field/@name', a.misc as 'field/@val' for xml path(''), type)
from 
    MyData a for xml path('doc')

对于你的XQuery版本试试这个:(我刚刚删除了花括号)那可以吗?

SELECT (select * from @MyData as MyData for xml auto, type).query
(
' for $d in /MyData
   return 
   <doc>
     <field name="name" val="{data($d/@name)}"  />
     <field name="age"  val="{data($d/@age)}"  />
     <field name="misc" val="{data($d/@misc)}"  />
  </doc>'
)

答案 1 :(得分:1)

您实际上是在尝试为不透明的数据获取XML。因此,首先获取一个不是字段的唯一行标识符(我将使用CTE和row_number)。从那里,您可以使用UNPIVOTFOR XML EXPLICIT

;with data as (
    select name, age, misc,
        row_number() over(order by name) as 'row'
    from @MyData
)
select 1 as tag,
       null as parent,
       row as [doc!1!row!hide],
       null as [field!2!name],
       null as [field!2!val]
from data
UNION
select 2 as tag,
       1 as parent,
       row as [doc!1!row!hide],
       fieldName as [field!2!name],
       val as [field!2!val]
from data d
  UNPIVOT(val for fieldName in (name, age, misc)) up
order by row, tag
FOR XML EXPLICIT, ROOT('root')

ROOT('root')是添加一个简单的根元素,并且是所请求的xml格式的补充,但我认为它可能有用。

<强>更新
在仔细查看查询执行计划之后,最好只创建格式化文本然后转换为xml:

select cast('<field name="name" val="'+name+'" />'+
            '<field name="age" val="'+age+'" />'+
            '<field name="misc" val="'+misc+'" />'
            as xml)
from @MyData
for xml path('doc')