选择没有列别名换行的XML列

时间:2016-03-01 15:33:04

标签: sql sql-server

我有以下查询返回以下XML结果集。 请注意查询1结果中的嵌套<Configuration>元素。

问题:

如果我添加一个case语句,它会从xml输出中删除列名。这给了我预期的结果。如果没有case语句或嵌套select,我怎么能这样做呢? 请参阅查询2&amp;查询2结果示例。

查询1:

   SELECT
        (SELECT
             q.NotificationQueueId
            ,nc.Configuration -- Provides unexpected result -- Nested <Configuration><Configuration /></Configuration>
            ,q.UserAdded
            ,q.DateAdded
            ,q.UserEdited
            ,q.DateEdited
            ,q.IsActive
        FROM Queue q
            INNER JOIN NotificationConfigurations nc ON nc.NotificationConfigurationId = q.NotificationConfigurationId
        FOR XML RAW ('NotificationItem'),TYPE)
    FOR XML RAW ('NotificationItems'),TYPE

查询1结果:

<NotificationItems>
  <NotificationItem NotificationQueueId="1" UserAdded="someone" DateAdded="2016-02-29T13:26:11.110" IsActive="1">
    <Configuration>
      <Configuration>
        <Email AddressList="blah@blah.com" Subject="blah blah blah">       
        </Email>
      </Configuration>
    </Configuration>
  </NotificationItem>
</NotificationItems>

查询2:

   SELECT
        (SELECT
             q.NotificationQueueId
            ,CASE WHEN 1 = 1 THEN nc.Configuration END -- Provides expected result
            ,(SELECT nc.Configuration) -- Provides expected result
            ,q.UserAdded
            ,q.DateAdded
            ,q.UserEdited
            ,q.DateEdited
            ,q.IsActive
        FROM Queue q
            INNER JOIN NotificationConfigurations nc ON nc.NotificationConfigurationId = q.NotificationConfigurationId
        FOR XML RAW ('NotificationItem'),TYPE)
    FOR XML RAW ('NotificationItems'),TYPE

查询2结果

<NotificationItems>
  <NotificationItem NotificationQueueId="1" UserAdded="someone" DateAdded="2016-02-29T13:26:11.110" IsActive="1">
    <Configuration>
      <Email AddressList="blah@blah.com" Subject="blah blah blah">       
      </Email>
    </Configuration>
  </NotificationItem>
</NotificationItems>

表格定义:

CREATE TABLE [dbo].[NotificationConfigurations](
    [NotificationConfigurationId] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
    [Configuration] [xml] NOT NULL,
 )

CREATE TABLE [dbo].[Queue](
    [NotificationQueueId] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
    [NotificationConfigurationId] [uniqueidentifier] NOT NULL,
    [UserAdded] [nvarchar](128) NOT NULL,
    [DateAdded] [datetime] NOT NULL,
    [UserEdited] [nvarchar](128) NULL,
    [DateEdited] [datetime] NULL,
    [IsActive] [bit] NOT NULL,
)

示例配置Xml:

<Configuration>
    <Email AddressList="blah@blah.com"
           Subject="blah blah blah">
    </Email>
</Configuration>

1 个答案:

答案 0 :(得分:1)

请参阅示例:

WITH t1 AS (
SELECT 1 AS ID UNION SELECT 2
), t2 AS (
SELECT 1 AS ID, CONVERT(XML, '
    <Configuration>
        <Email AddressList="blah@blah.com" Subject="blah blah blah">       
        </Email>
    </Configuration>
    ') As Configuration
)
SELECT (
    SELECT t1.ID,
        t2.Configuration,
        CASE WHEN 1 = 1 THEN t2.Configuration END,
        (SELECT nc.Configuration)
    FROM t1
    INNER JOIN t2 On t1.ID = t2.ID
    FOR XML RAW ('NotificationItem'),TYPE
) FOR XML RAW ('NotificationItems'),TYPE

您的Configuration字段已经是带有<Configuration />根标记的XML。选中后,它将被包含在字段名称后面的额外<Configuration />标记中。

您已经通过(SELECT nc.Configuration)获得了解决方案,这导致“匿名”字段“按原样”包含在结果XML中,没有字段名称换行标记。而这个“嵌套查询”实际上并没有花费任何成本。

更新:原因Configuration XML可以在JOIN之前明确“解包”,但效率会低得多:

WITH t1 AS (
SELECT 1 AS ID UNION SELECT 2
), t2 AS (
SELECT 1 AS ID, CONVERT(XML, '
    <Configuration>
        <Email AddressList="blah@blah.com" Subject="blah blah blah">       
        </Email>
    </Configuration>
    ') As Configuration
)
SELECT (
    SELECT t1.ID,
        t2sub.Configuration
    FROM t1
    INNER JOIN (
        SELECT ID, sub.ConfigurationContents.query('.') AS Configuration
        FROM t2
        CROSS APPLY Configuration.nodes('/Configuration/child::node()') AS sub(ConfigurationContents) 
    ) t2sub ON t2sub.id = t1.id
    FOR XML RAW ('NotificationItem'),TYPE
) FOR XML RAW ('NotificationItems'),TYPE