简体   繁体   English

用于XML自动问题的SQL Server

[英]SQL Server For XML auto problems

Hi I am trying to get my db to output XML and I am succeeding somewhat. 嗨,我正在尝试让我的数据库输出XML,并且我取得了一些成功。

When I do a standard select with various joins ect and all works fine, I add the following line: 当我对各种联接进行标准选择并且一切正常时,我添加以下行:

for xml auto, root('MyRoot')

This generated the required XML 这生成了所需的XML

However, when I use a cast or convert in the select one of my tags get combined into its parent and I dont have any understanding why or how to fix it. 但是,当我在选择中使用强制转换或转换时,我的一个标签被合并到其父标签中,而我却不了解为什么或如何修复它。 Everything else is perfect. 其他一切都很完美。

Below is the code which outputs the XML as I want it 以下是根据需要输出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')

So the resulting XML is like this: 因此,生成的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>

The problem is that when I replace the "aDate as date" line with the following line to format the date my XML gets messed up. 问题是,当我用以下行替换“ aDate as date”行以格式化XML弄乱日期时。

CONVERT(date,aDate) as [date]

This causes the following output: 这将导致以下输出:

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

What has caused this change and what do I do to get the date formatted the way I want it and keep it on a separate line like in the first example. 造成此更改的原因以及如何使日期格式化为所需的格式并将其保留在第一个示例中的单独行中。

EDIT2: Below is an ERD of the db (I removed the explanation of the erd and just put an erd. also with some sample data: Following is the dataset I want in my xml. EDIT2:以下是数据库的ERD(我删除了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

a full dataset run with select * will show the following: (for the purposes of explaining the joins). 使用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

在此处输入图片说明

What I am trying to acheive is XML output in the following format. 我要实现的是以下格式的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>

However I need to acheive this without using Explisit, so need to know if I should be using Raw, Auto or Path, and with what combination of prameters. 但是,我需要在不使用Explisit的情况下实现这一点,因此需要知道我是否应该使用Raw,Auto或Path,以及使用什么参数。

I think the problem is that, with the conversion (as with any reasonably complex function), the resulting column no longer "belongs" to Tbl3 (imagine a function taking columns from multiple tables - which table would it "belong" to?). 我认为问题在于,通过转换(与任何相当复杂的函数一样),结果列将不再“属于” Tbl3 (想象一个函数从多个表中获取列-它会“属于”哪个表?)。 As Using AUTO Mode says: 使用自动模式所说:

This does not provide much control over the shape of the XML generated from a query result. 这不能很好地控制从查询结果生成的XML的形状。 ... Using EXPLICIT Mode and Using PATH Mode provide more control ...使用EXPLICIT模式和PATH模式可提供更多控制

and, 和,

When a column in the SELECT clause cannot be associated with any of the tables identified in the FROM clause, as in the case of an aggregate column or computed column, the column is added in the XML document in the deepest nesting level in place when it is encountered in the list. SELECT子句中的列无法与FROM子句中标识的任何表相关联时(例如,聚合列或计算列),该列将在XML文档中以最深的嵌套级别添加在列表中遇到。 If such a column appears as the first column in the SELECT clause, the column is added to the top element. 如果此类列显示为SELECT子句中的第一列,则该列将添加到顶部元素。

So I'd suggest switching to using PATH . 所以我建议切换到使用PATH In simplifying your query, I think you've oversimplified your joins, since they're all now on the same id value, but the following generates the right shape of query: 在简化查询时,我认为您已简化了联接,因为它们现在都具有相同的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')

Result: 结果:

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

I think you have to use XML Path in this case. 我认为您必须在这种情况下使用XML Path。 Try something like this: 尝试这样的事情:

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;

If it doesnt work, can you post your tables' structures so its easier to test? 如果它不起作用,您可以发布表的结构以便于测试吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM