3

我有两个不同的 XML 片段要放在一起。

例如,第一部分的 SQL 如下所示:

SELECT
  *
FROM
  (
    SELECT 1 AS OrdNum, 'Abc'       AS Name
  ) a
FOR XML
  AUTO,
  TYPE

一旦执行,你会得到这个:

<a OrdNum="1" Name="Abc" />

第二个在这里:

SELECT
  *
FROM
  (
     SELECT 4  AS Age, 'M'  AS Sex,   'John'      AS FirstName
  ) b
FOR XML
  AUTO,
  TYPE

你会得到这个:

<b Age="4" Sex="M" FirstName="John" />

现在我将这两部分放在一起:

SELECT
  *
FROM
  (

    SELECT
      (
        SELECT
          *
        FROM
          (
            SELECT 1 AS OrdNum, 'Abc'       AS Name
          ) a
        FOR XML
          AUTO,
          TYPE
      ) AS aa

      ,

      (
        SELECT
          *
        FROM
          (
             SELECT 4  AS Age, 'M'  AS Sex,   'John'      AS FirstName
          ) b
        FOR XML
          AUTO,
          TYPE
      ) AS bb

  ) Data
FOR XML
  AUTO,
  ELEMENTS

结果如下:

<Data>
  <aa>
    <a OrdNum="1" Name="Abc" />
  </aa>
  <bb>
    <b Age="4" Sex="M" FirstName="John" />
  </bb>
</Data>

但我不想在那里有元素“aa”和“bb”。我很想得到这个:

<Data>
  <a OrdNum="1" Name="Abc" />
  <b Age="4" Sex="M" FirstName="John" />
</Data>

但我不知道如何实现这一目标。

有什么提示吗?

4

2 回答 2

4

没有“简单”的方法可以做到这一点。FOR XML PATH|EXPLICIT|AUTO都将要求每个顶级输出元素具有相同的名称。而且您不能将多个FOR XML查询联合在一起(Sql Server 2012)。

你走的方向是最可靠和灵活的。本质上,您必须为要包含的每种不同元素类型添加一个单独的列。你可以简化你的最终尝试来得到你想要的:

SELECT
    (
        SELECT 1 AS [@OrdNum], 'Abc' AS [@Name]
            WHERE 1=1
            FOR XML PATH ('a'), TYPE
    )
    , 
    (
        SELECT 4 AS [@Age], 'M' AS [@Sex], 'John' AS [@FirstName]
            WHERE 1=1
            FOR XML PATH ('b'), TYPE
    )
    FOR XML PATH ('Data'), TYPE;

上述查询输出:

<Data>
  <a OrdNum="1" Name="Abc" />
  <b Age="4" Sex="M" FirstName="John" />
</Data>

使用FOR XML PATH时,列别名是 XPath。因此,要使其成为属性名称,您必须以 '@' 为前缀---然后要求您转义别名(因此是[])。on 参数PATH指示每行的 Xml 元素的名称。该TYPE选项表示将输出保留为 Xml 类型而不是 nvarchar(max),这意味着外部查询可以更好地合并它。外部查询只有 2 列可以填充到它所代表的单个元素中。最后,我喜欢WHERE 1=1,但它在语法上不是必需的。

切线:我知道您的示例已简化,因此您可能希望知道 Xml 数据类型可以应用“方法”。例如,假设您想要上述内容,但外部查询只需要“b”元素。您可以使用该query()方法仅选择部分 Xml 以合并到某些外部查询中。

SELECT 
    (
        SELECT
            (
                SELECT 1 AS [@OrdNum], 'Abc' AS [@Name]
                    WHERE 1=1
                    FOR XML PATH('a'), TYPE
            )
            , 
            (
                SELECT 4 AS [@Age], 'M' AS [@Sex], 'John' AS [@FirstName]
                    WHERE 1=1
                    FOR XML PATH('b'), TYPE
            )
            FOR XML PATH('Data'), TYPE
    ).query('Data/b');

产生这个:

<b Age="4" Sex="M" FirstName="John" />
于 2016-01-09T17:14:07.397 回答
1

您需要查看 SQL Server 2005 引入的 FOR XML PATH 选项 - 有关详细信息,请参阅 Microsoft SQL Server 2005 文档中 FOR XML 的新增功能。

基本上,使用 FOR XML PATH,您可以非常轻松地定义 XML 的形状。您可以定义某些结构,可以定义某些列作为属性输出,而将其他列定义为元素 - 完全在您的控制之下。

您可以在此处获取有关如何格式化的更多信息:

在此处输入链接描述

于 2014-05-21T16:50:56.563 回答