【问题标题】:Need multiple tags in FOR XML resultFOR XML 结果中需要多个标签
【发布时间】:2018-04-03 06:45:44
【问题描述】:

我尝试输出 XML 文本,其中输出行具有多个根标记,并且选择结果也具有多个根标记。我知道这有点含糊,所以让我试着说明这个问题。 实际环境比较复杂,所以我尽量简化结构。

在此简化示例中,涉及 2 个表。一个名为 xml_orderlines,一个名为 xml_clients。 表结构如下:

对于 1 个客户,有 1 个或多个订单行。我知道我们应该在这个结构中还有一个表 Orders,但对于这个例子它不适用)

创建 xml_orderlines:

CREATE TABLE [dbo].[xml_OrderLines](
[orderid] [int] NULL,
[cl_id] [int] NULL,
[DtOrder] [date] NULL,
[PlcOfOrder] [varchar](50) NULL,
[Accman] [varchar](50) NULL,
[Art_id] [int] NULL
) ON [PRIMARY]

GO

INSERT INTO xml_OrderLines (orderid,cl_id,DtOrder,PlcOfOrder,Accman,art_id) VALUES (12,101,'2017-05-31','Rotterdam',201,301)
INSERT INTO xml_OrderLines (orderid,cl_id,DtOrder,PlcOfOrder,Accman,art_id) VALUES (13,102,'2017-06-15','Amsterdam',202,302)
INSERT INTO xml_OrderLines (orderid,cl_id,DtOrder,PlcOfOrder,Accman,art_id) VALUES (14,103,'2017-07-15','London',203,303)
INSERT INTO xml_OrderLines (orderid,cl_id,DtOrder,PlcOfOrder,Accman,art_id) VALUES (15,104,'2017-08-15','Dublin',204,304)
INSERT INTO xml_OrderLines (orderid,cl_id,DtOrder,PlcOfOrder,Accman,art_id) VALUES (16,101,'2017-05-31','Rotterdam',205,305)
INSERT INTO xml_OrderLines (orderid,cl_id,DtOrder,PlcOfOrder,Accman,art_id) VALUES (17,102,'2017-06-15','Amsterdam',206,306)
INSERT INTO xml_OrderLines (orderid,cl_id,DtOrder,PlcOfOrder,Accman,art_id) VALUES (18,103,'2017-07-15','London',207,307)
INSERT INTO xml_OrderLines (orderid,cl_id,DtOrder,PlcOfOrder,Accman,art_id) VALUES (19,104,'2017-08-15','Dublin',208,308)
INSERT INTO xml_OrderLines (orderid,cl_id,DtOrder,PlcOfOrder,Accman,art_id) VALUES (18,103,'2017-07-15','London',207,307)

创建 xml_cients:

CREATE TABLE [dbo].[xml_clients](
[cl_id] [int] NULL,
[name] [varchar](50) NULL,
[surname] [varchar](50) NULL,
[DtOfBirth] [date] NULL
) ON [PRIMARY]

GO

INSERT INTO xml_Clients  (cl_id,name,surname,DtOfBirth) VALUES (101,'Jan','Winter','2000-05-31')
INSERT INTO xml_Clients  (cl_id,name,surname,DtOfBirth) VALUES (102,'John','Summer','2000-06-15')
INSERT INTO xml_Clients  (cl_id,name,surname,DtOfBirth) VALUES (103,'Jean','Autum','2000-05-12')
INSERT INTO xml_Clients  (cl_id,name,surname,DtOfBirth) VALUES (104,'Janis','Spring','2000-06-16')

这是我运行的查询:

SELECT 
ol.Art_id   AS 'ArtikelOrder'
,
    (
    SELECT
        c.cl_id AS 'Buyer/Client'
    ,   c.name  AS 'Buyer/FirstName'
    ,   c.surname   AS 'Buyer/SurName'
    ,   c.DtOfBirth AS 'Buyer/DateOfBirth'
    from 
        xml_clients AS c
    join
        xml_orderlines AS x ON c.cl_id=x.cl_id

    WHERE x.art_id = ol.art_id
    FOR XML PATH(''), TYPE, ROOT('Clients')
    )
,   ol.DtOrder  AS 'OrderDate'
,   ol.plcOfOrder AS 'OrderPlace'
,   ol.orderid AS 'OrderId'
FROM
xml_orderlines AS ol 
FOR XML PATH('Tx'),TYPE, ROOT('Document')

这个查询在 XML 中给出了以下结果:

<Document>
 <Tx>
  <ArtikelOrder>307</ArtikelOrder>
  <Clients>
    <Buyer>
      <Client>103</Client>
      <FirstName>Jean</FirstName>
      <SurName>Autum</SurName>
      <DateOfBirth>2000-05-12</DateOfBirth>
    </Buyer>
    <Buyer>
      <Client>103</Client>
      <FirstName>Jean</FirstName>
      <SurName>Autum</SurName>
      <DateOfBirth>2000-05-12</DateOfBirth>
    </Buyer>
  </Clients>
  <OrderDate>2017-07-15</OrderDate>
  <OrderPlace>London</OrderPlace>
  <OrderId>18</OrderId>
 </Tx>
 <Tx>
   <ArtikelOrder>302</ArtikelOrder>
    <Clients>
    <Buyer>
      <Client>102</Client>
      <FirstName>John</FirstName>
      <SurName>Summer</SurName>
      <DateOfBirth>2000-06-15</DateOfBirth>
    </Buyer>
   </Clients>
 <OrderDate>2017-06-15</OrderDate>
 <OrderPlace>Amsterdam</OrderPlace>
 <OrderId>13</OrderId>
</Tx>
</Document>

我尝试实现以下输出:

<FirstQRoot>
 <Document>
  <FirstRowRoot>
   <Tx>
    <ArtikelOrder>307</ArtikelOrder>
    <Clients>
     <Buyer>
      <Client>103</Client>
      <FirstName>Jean</FirstName>
      <SurName>Autum</SurName>
      <DateOfBirth>2000-05-12</DateOfBirth>
     </Buyer>
     <Buyer>
      <Client>103</Client>
      <FirstName>Jean</FirstName>
      <SurName>Autum</SurName>
      <DateOfBirth>2000-05-12</DateOfBirth>
     </Buyer>
    </Clients>
    <OrderDate>2017-07-15</OrderDate>
    <OrderPlace>London</OrderPlace>
    <OrderId>18</OrderId>
   </Tx>
  </FirstRowRoot>
  <FirstRowRoot>
   <Tx>
   <ArtikelOrder>302</ArtikelOrder>
    <Clients>
     <Buyer>
      <Client>102</Client>
      <FirstName>John</FirstName>
      <SurName>Summer</SurName>
      <DateOfBirth>2000-06-15</DateOfBirth>
     </Buyer>
    </Clients>
    <OrderDate>2017-06-15</OrderDate>
    <OrderPlace>Amsterdam</OrderPlace>
    <OrderId>13</OrderId>
   </Tx>
  </FirstRowRoot>
 </Document>
</FirstQRoot>

我希望可以添加“FirstQRoot”和“FirstRowRoot” 标签。 我尝试了几种子查询和双标签的组合(在标签名称中使用 /),但都没有解决问题。

【问题讨论】:

  • 请用实际的RDBMS(产品和版本)标记,请阅读How to ask a good SQL questionHow to create a MCVE提供示例代码,实际输出和预期输出很好,但尽量减少这一点并尝试使用测试数据创建一个独立示例...
  • 这是针对 SQL Server 的,对吧?如果是这样,您可以为此添加标签吗?
  • 我对你的结构感到困惑,xml_clients 是什么?是桌子吗?这是你真正的表源吗?如果是,这看起来是一个错误的设计。我希望有一个表clients、一个表articles 和一个映射表来告诉哪个客户购买了哪篇文章以及此次购买的详细信息。也许您会创建一个带有指向客户端的链接的购买表,并将购买表与文章映射......这看起来很奇怪......
  • @Shugo 我已经添加了表格数据,以便您可以更轻松地重现案例。

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


【解决方案1】:

添加一个内部的两个嵌套的行根有点棘手......试试这样:

SELECT 
(
    SELECT
    (
        SELECT ol.Art_id AS ArtikelOrder
              ,(
                SELECT
                    c.cl_id AS 'Client'
                ,   c.name  AS 'FirstName'
                ,   c.surname   AS 'SurName'
                ,   c.DtOfBirth AS 'DateOfBirth'
                from xml_clients AS c
                join xml_orderlines AS x ON c.cl_id=x.cl_id
                WHERE x.art_id = ol.art_id
                FOR XML PATH('Buyer'), ROOT('Clients'),TYPE
               )
              ,ol.DtOrder AS OrderDate
              ,ol.PlcOfOrder AS OrderPlace
              ,ol.orderid AS OrderId
        FOR XML PATH('Tx'),ROOT('FirstRowRoot'),TYPE
    )
    FROM xml_OrderLines AS ol
    FOR XML PATH(''),ROOT('Document'),TYPE
)
FOR XML PATH('FirstQRoot');

【讨论】:

    【解决方案2】:

    演示 初始查询:

    select x,y
    from (
        --demo data
         select 1 as x, 10 as y
         union all
         select 2, 20
    ) t 
    for xml path('Tx'), type, root ('Document');
    

    返回

    <Document>
      <Tx>
        <x>1</x>
        <y>10</y>
      </Tx>
      <Tx>
        <x>2</x>
        <y>20</y>
      </Tx>
    </Document>
    

    重构查询:

    select Document
    from (
        select x as [Tx/x],y as [Tx/y] 
          from (
             --demo data
             select 1 as x, 10 as y
             union all
             select 2, 20) t 
        for xml path('FirstRowRoot'), type
    ) t2(Document)
    for xml path(''), type, root('FirstQRoot');
    

    使用更新后的问题数据:

    SELECT Document
    FROM(
        SELECT 
        ol.Art_id   AS [Tx/ArtikelOrder]
        ,(
            SELECT
                c.cl_id AS 'Buyer/Client'
            ,   c.name  AS 'Buyer/FirstName'
            ,   c.surname   AS 'Buyer/SurName'
            ,   c.DtOfBirth AS 'Buyer/DateOfBirth'
            from 
                xml_clients AS c
            join
                xml_orderlines AS x ON c.cl_id=x.cl_id
    
            WHERE x.art_id = ol.art_id
            FOR XML PATH(''), TYPE
         ) AS [Tx/Clients]
        ,   ol.DtOrder  AS [Tx/OrderDate]
        ,   ol.plcOfOrder AS [Tx/OrderPlace]
        ,   ol.orderid AS [Tx/OrderId]
        FROM
        xml_orderlines AS ol 
        FOR XML PATH('FirstRowRoot'),TYPE
    ) t(Document)
    FOR XML PATH(''), TYPE, ROOT('FirstQRoot');
    

    【讨论】:

    • 您能否使用我现在随问题提供的测试表和数据设置您的重构 qeury?
    • 查看更新的答案,抱歉耽搁了,我无法到达是有原因的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-02
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多