Sql server 如何使用FOR XML AUTO子句将特定列作为元素返回

Sql server 如何使用FOR XML AUTO子句将特定列作为元素返回,sql-server,xml,for-xml,Sql Server,Xml,For Xml,我需要在sql server中使用FOR xml AUTO子句返回的xml中返回一个特定列作为元素。自动返回将所有字段转换为相应元素的属性。好吧,但不管是哪个领域,我需要它成为一个元素 我有两张桌子: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Table1]( [Id] [int] NULL, [Nome] [varchar](50) NULL ) ON [PRIMARY] GO /*

我需要在sql server中使用FOR xml AUTO子句返回的xml中返回一个特定列作为元素。自动返回将所有字段转换为相应元素的属性。好吧,但不管是哪个领域,我需要它成为一个元素

我有两张桌子:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Table1](
    [Id] [int] NULL,
    [Nome] [varchar](50) NULL
) ON [PRIMARY]
GO
/****** Object:  Table [dbo].[Table2]    Script Date: 02/03/2018 16:24:11 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Table2](
    [Id] [int] NULL,
    [DataVencimento] [date] NULL,
    [Table1_Id] [int] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[Table1] ([Id], [Nome]) VALUES (1, N'AAA')
GO
INSERT [dbo].[Table1] ([Id], [Nome]) VALUES (2, N'BBB')
GO
INSERT [dbo].[Table1] ([Id], [Nome]) VALUES (3, N'CCC')
GO
INSERT [dbo].[Table2] ([Id], [DataVencimento], [Table1_Id]) VALUES (1, CAST(N'2018-01-01' AS Date), 1)
GO
INSERT [dbo].[Table2] ([Id], [DataVencimento], [Table1_Id]) VALUES (2, CAST(N'2018-01-02' AS Date), 2)
GO
INSERT [dbo].[Table2] ([Id], [DataVencimento], [Table1_Id]) VALUES (3, CAST(N'2018-01-03' AS Date), 2)
GO
我与他们之间有以下关系:

select 
    Table1.Id,
    Table1.Nome,
    Table2.Id,
    Table2.DataVencimento
from Table1 
    inner join Table2 on Table2.Table1_Id = Table1.Id
    order by Table1.Id, Table2.Id
for xml auto, root('ArrayOfTable1')
返回:

<ArrayOfTable1>
  <Table1 Id="1" Nome="AAA">
    <Table2 Id="1" DataVencimento="2018-01-01" />
  </Table1>
  <Table1 Id="2" Nome="BBB">
    <Table2 Id="2" DataVencimento="2018-01-02" />
    <Table2 Id="3" DataVencimento="2018-01-03" />
  </Table1>
</ArrayOfTable1>

但我需要DataVencimento作为一个元素,如下所示:

<ArrayOfTable1>
    <Table1 Id="1" Nome="AAA">
        <Table2 Id="1">
            <DataVencimento>2018-01-01</DataVencimento>
        </Table2>
    </Table1>
    <Table1 Id="2" Nome="BBB">
        <Table2 Id="2">
            <DataVencimento>2018-01-02</DataVencimento>
        </Table2>
        <Table2 Id="3">
            <DataVencimento>2018-01-03</DataVencimento>
        </Table2>
    </Table1>
</ArrayOfTable1>

2018-01-01
2018-01-02
2018-01-03

如何做到这一点?

我现在不知道是否有更清洁的解决方案,但类似的方法应该有效:

select 
    Table1.Id as [@Id],
    Table1.Nome as [@Nome],
    [inner].[xml] as [*]
from Table1 
outer apply 
( select (select
     Table2.Id as [@Id],
    Table2.DataVencimento
  from Table2 
  where Table2.Table1_Id = Table1.Id
  for xml path('Table2'), type) as [xml]

) as [inner]
    inner join Table2 on Table2.Table1_Id = Table1.Id
    order by Table1.Id, Table2.Id
for xml path('Table1'), root('ArrayOfTable1')
输出:

<ArrayOfTable1>
  <Table1 ID="1" Nome="AAA">
    <Table2 Id="1">
      <DataVencimento>2018-01-01</DataVencimento>
    </Table2>
  </Table1>
<Table1 ID="2" Nome="BBB">
  <Table2 Id="2">
    <DataVencimento>2018-01-02</DataVencimento>
  </Table2>
  <Table2 Id="3">
    <DataVencimento>2018-01-03</DataVencimento>
  </Table2>
</Table1>
</ArrayOfTable1>

在大多数情况下,
FOR XML PATH()
是首选方法。使用
PATH
可以完全控制输出。没有什么是自动的

试一试:

SELECT t1.Id AS [@id]
      ,t1.Nome AS [@Nome]
      ,(
        SELECT t2.Id AS [@Id]
              ,t2.DataVencimento
        FROM dbo.Table2 AS t2
        WHERE t1.Id=t2.Table1_Id
        ORDER BY t2.Id
        FOR XML PATH('Table2'),TYPE
       )
FROM dbo.Table1 AS t1
WHERE EXISTS(SELECT 1 FROM dbo.Table2 WHERE Table2.Table1_Id=t1.Id)
ORDER BY t1.Id
FOR XML PATH('Table1'), ROOT('ArrayOfTable1');

它的解决方案是好的,仍然打开了一系列的可能性!谢谢Adam,这个解决方案将使我的查询变得非常大,因为我有更复杂的关系和多个列作为一个元素。谢谢你的帮助!这种方法确实有效,在我需要在子查询中使用下一个值之前,我就是这样做的。但子查询中不允许使用此函数。这就是我选择使用自动模式的原因,也是我规避这种情况的方法。非常感谢。
SELECT t1.Id AS [@id]
      ,t1.Nome AS [@Nome]
      ,(
        SELECT t2.Id AS [@Id]
              ,t2.DataVencimento
        FROM dbo.Table2 AS t2
        WHERE t1.Id=t2.Table1_Id
        ORDER BY t2.Id
        FOR XML PATH('Table2'),TYPE
       )
FROM dbo.Table1 AS t1
WHERE EXISTS(SELECT 1 FROM dbo.Table2 WHERE Table2.Table1_Id=t1.Id)
ORDER BY t1.Id
FOR XML PATH('Table1'), ROOT('ArrayOfTable1');