【问题标题】:Sql Server table to XML with multiple child nodes具有多个子节点的 Sql Server 表到 XML
【发布时间】:2011-05-29 13:06:19
【问题描述】:

我有下表

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>'
)

【问题讨论】:

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


    【解决方案1】:

    这个怎么样..

    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>'
    )
    

    【讨论】:

    • 我知道这是一个简单的语法!我认为我更喜欢 xquery 版本,因为我认为发生的事情更加明显。再次感谢
    【解决方案2】:

    您实际上是在尝试获取未透视数据的 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')
    

    【讨论】:

    • 感谢您的回答。如果我没有得到 xquery 解决方法,我正在考虑第二个版本,因为事实证明我只需要删除大括号! unpivot 看起来很有趣,可能适用于我需要的另一个查询!
    猜你喜欢
    • 2016-12-09
    • 2018-03-12
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多