SQL Server для проблем с авто XML - PullRequest
1 голос
/ 17 февраля 2012

Привет. Я пытаюсь заставить свою БД выводить XML, и у меня это получается.

Когда я делаю стандартный выбор с различными объединениями и т. Д., И все работает нормально, я добавляю следующую строку:

for xml auto, root('MyRoot')

Это сгенерировало необходимый XML

Однако, когда я использую приведение или преобразование в select, один из моих тегов объединяется с его родителем, и я не понимаю, почему или как это исправить. Все остальное идеально.

Ниже приведен код, который выводит XML так, как я хочу

select  Tbl1.id, 
        'xyz   ' as [randCol], 
        Tbl2.id,
        Tbl2.name, 
        aDate as [date] --(aDate is the date field, date here is not data type, but a colum name for output) 
from dbo.table1 as Tbl1 
inner join dbo.table3 as Tbl3 
on Tbl1.id = Tbl3.table1id 
inner join table2 as Tbl2 
on Tbl3.table2id = Tbl2.id 
where Tbl1.id = 1 

for xml auto, root('MyRoot')

Итак, итоговый XML выглядит так:

<MyRoot>
  <Tbl1 id="1" randCol="xyz   ">
    <Tbl2 id="10001" name="John">
      <Tbl3 date="2011-10-19T22:59:00" />
    </Tbl2>
    <Tbl2 id="10002" name="Brian">
      <Tbl3 date="2011-10-19T22:59:00" />
    </Tbl2>
    <Tbl2 id="10003" name="Jimmy">
      <Tbl3 date="2011-05-19T23:00:00" />
    </Tbl2>
  </Tbl1>
</MyRoot>

Проблема в том, что когда я заменяю строку «aDate as date» следующей строкой для форматирования даты, в которой мой XML испорчен.

CONVERT(date,aDate) as [date]

Это приводит к следующему выводу:

<MyRoot>
  <Tbl1 id="1" randCol="xyz   ">
    <Tbl2 id="10001" name="dave" date="2010-11-17" />
    <Tbl2 id="10002" name="harry" date="2010-11-16" />
    <Tbl2 id="10003" name="lenny" date="2010-06-15" />
  </Tbl1>
</MyRoot>

Что вызвало это изменение и что я должен сделать, чтобы отформатировать дату так, как я хочу, и сохранить ее на отдельной строке, как в первом примере.

EDIT2: ниже приведена ERD для db (я удалил объяснение erd и просто поместил erd. Также с некоторыми примерами данных: Ниже приведен набор данных, который я хочу в моем xml.

id    randCol   id        name      date
1     xyz       10001     John      2011-10-19
1     xyz       10002     Brian     2011-10-19
1     xyz       10003     Jimmy     2011-05-19

полный набор данных с select * покажет следующее: (для объяснения объединений).

id  table1id   table2id   aDate                 id      name
1   1          10001      2011-10-19 22:59:00   10001   John
1   1          10002      2011-10-19 22:59:00   10002   Brian
1   1          10003      2011-05-19 23:00:00   10003   Jimmy

enter image description here

Я пытаюсь получить вывод XML в следующем формате.

<MyRoot>
  <Tbl1 id="1" randCol="xyz   ">
    <Tbl2 id="10001" name="John">
      <Tbl3 date="2011-10-19" />
    </Tbl2>
    <Tbl2 id="10002" name="Brian">
      <Tbl3 date="2011-10-19" />
    </Tbl2>
    <Tbl2 id="10003" name="Jimmy">
      <Tbl3 date="2011-05-19" />
    </Tbl2>
  </Tbl1>
</MyRoot>

Однако мне нужно добиться этого без использования Explisit, поэтому нужно знать, следует ли мне использовать Raw, Auto или Path и с какой комбинацией параметров.

Ответы [ 2 ]

1 голос
/ 17 февраля 2012

Я думаю, что проблема в том, что при преобразовании (как и в случае любой достаточно сложной функции) результирующий столбец больше не «принадлежит» Tbl3 (представьте себе функцию, принимающую столбцы из нескольких таблиц - к какой таблице она «принадлежит» "к?). Как Использование режима AUTO говорит:

Это не дает большого контроля над формой XML, сгенерированного из результата запроса. ... Использование режима EXPLICIT и режима PATH обеспечивает больше контроля

и

Когда столбец в предложении SELECT не может быть связан ни с одной из таблиц, указанных в предложении FROM, как в случае агрегированного столбца или вычисляемого столбца, этот столбец добавляется в документ XML в самый глубокий уровень вложенности, когда он встречается в списке. Если такой столбец отображается как первый столбец в предложении SELECT, столбец добавляется в верхний элемент.

Так что я бы предложил перейти на использование PATH . Упрощая ваш запрос, я думаю, вы слишком упростили свои объединения, поскольку все они теперь имеют одно и то же значение id, но следующее генерирует правильную форму запроса:

declare @table1 table (
    id int not null
)
declare @table2 table (
    id int not null,
    name varchar(10) not null
)
declare @table3 table (
    table1id int not null,
    table2id int not null,
    aDate datetime not null
)

insert into @table1 (id) select 1
insert into @table2 (id,name) select 10001,'John' union all select 10002,'Brian' union all select 10003,'Jimmy'
insert into @table3 (table1id,table2id,aDate)
select 1,10001,'2011-10-19T22:59:00' union all
select 1,10002,'2011-10-19T22:59:00' union all
select 1,10003,'2011-05-19T23:00:00'
select  Tbl1.id as [@id],
        'xyz   ' as [@randCol],
        (select 
          Tbl2.id as [@id],
          Tbl2.name as [@name],
          CONVERT(date,aDate) as [Tbl3/@date] --(aDate is the date field, date here is not data type, but a colum name for output)
        from
          @table3 as Tbl3 
             inner join
          @table2 as Tbl2 
             on
                Tbl3.table2id = Tbl2.id 
        where
          Tbl1.id = Tbl3.table1id 
        for xml path('Tbl2'), type)
from @table1 as Tbl1 
where Tbl1.id = 1 

for xml path('Tbl1'), root('MyRoot')

Результат:

<MyRoot>
  <Tbl1 id="1" randCol="xyz   ">
    <Tbl2 id="10001" name="John">
      <Tbl3 date="2011-10-19" />
    </Tbl2>
    <Tbl2 id="10002" name="Brian">
      <Tbl3 date="2011-10-19" />
    </Tbl2>
    <Tbl2 id="10003" name="Jimmy">
      <Tbl3 date="2011-05-19" />
    </Tbl2>
  </Tbl1>
</MyRoot>
0 голосов
/ 17 февраля 2012

Я думаю, что вы должны использовать XML Path в этом случае.Попробуйте что-то вроде этого:

select  Tbl1.id,
        'xyz   ' as [randCol],
        (SELECT Tbl2.id,
                Tbl2.name,
                (convert(date,aDate,102)) as [date]
                FROM (dbo.table1 as Tbl1 inner join table3 as Tbl3 on Tbl1.id = Tbl3.id inner join table2 as Tbl2 on Tbl3.id = Tbl2.id where Tbl1.id = 1)
                FOR XML PATH('Table2'), TYPE
        ) 
from table1
FOR XML path('Table1'), root('myroot'), ELEMENTS;

Если это не сработает, вы можете опубликовать структуры ваших таблиц, чтобы их было проще тестировать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...