SQL Server таблицы в XML с несколькими дочерними узлами - PullRequest
3 голосов
/ 22 декабря 2010

У меня есть следующая таблица

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 ]

4 голосов
/ 22 декабря 2010

Как насчет этого ..

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 голос
/ 22 декабря 2010

По сути, вы пытаетесь получить XML для непивотированных данных. Итак, начнем с получения уникального идентификатора строки, который не является полем (я буду использовать CTE и row_number). Оттуда вы можете использовать UNPIVOT и FOR 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, но я подумал, что это может быть полезно.

UPDATE
Посмотрев немного ближе к планам выполнения запросов, вам может быть лучше просто создать форматированный текст, а затем привести к 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')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...