【问题标题】:Concatenate several XMLs to single将多个 XML 连接到单个
【发布时间】:2015-04-09 14:54:35
【问题描述】:

我的 SQL Server 2008 R2 数据库中生成了以下 XML

<XMLData>
...
<Type>1</Type>
...
</XMLData>

我需要的最终输出是单一组合如下:

<AllMyData>
    <XMLData>
        ...
        <Type>1</Type>
        ...
    </XMLData>
    <XMLData>
        ...
        <Type>2</Type>
        ...
    </XMLData>
    ...
    ...
    <XMLData>
        ...
        <Type>n</Type>
        ...
    </XMLData>
<AllMyData>

n 在查询运行之前是未知的。

现在我正在使用这种方法:

ALTER FUNCTION [dbo].[fn_GetErrorXML]
(   
    @DateFrom datetime,     
    @DateTo datetime,      
    @ResourceTypeID bigint,    
    @ServerID int           
)
RETURNS NVARCHAR(MAX) 
AS
BEGIN 

    DECLARE @ErrorDescription VARCHAR(MAX)
    SET @ErrorDescription = '<root>';
    WITH CTE AS
    (   

        SELECT 
            d.GeneratedOnUtc,
            ErrorDescription = cast(d.Data as nvarchar(max))
        FROM dbo.AgentData d
          INNER JOIN dbo.Agent a ON a.CheckID = d.CheckID
          INNER JOIN dbo.Server s ON a.ServerID = s.ID
        WHERE d.EventType = 'Result' AND
              a.ResourceTypeID & @ResourceTypeID > 0 AND
              s.ID = @ServerID AND
              d.GeneratedOnUtc between @DateFrom AND @DateTo AND
              d.Result = 0                            
    )
    SELECT @ErrorDescription = @ErrorDescription + cte.ErrorDescription
    FROM CTE    
    ORDER BY cte.GeneratedOnUtc ASC

    RETURN(@ErrorDescription + '</root>')
END

其中d.Data 数据类型为xml not null

但是 XML casts + UDF 太慢而且看起来很丑。

有更好的方法吗?

【问题讨论】:

  • d.Data 是什么类型,结果你想要什么类型?
  • @GiorgiNakeuri XMLstring,不管是哪一个
  • D.Data 的类型是 XMl 还是字符串???如果没有,那你为什么要转换为 nvarchar?
  • @GiorgiNakeuri XML。因为我不知道如何连接 XML。这就是我问这个问题的原因。

标签: sql sql-server xml sql-server-2008-r2 concatenation


【解决方案1】:

你能试试这个吗?

with cte AS
(SELECT d.GeneratedOnUtc as gtime,
d.Data as xmlDat FROM dbo.AgentData d
INNER JOIN dbo.Agent a ON a.CheckID = d.CheckID
INNER JOIN dbo.Server s ON a.ServerID = s.ID
WHERE d.EventType = 'Result' AND
a.ResourceTypeID & @ResourceTypeID > 0 AND
s.ID = @ServerID AND
d.GeneratedOnUtc between @DateFrom AND @DateTo AND
d.Result = 0 
)
select CAST(cte.xmlDat AS XML) from cte order by cte.gtime for xml   path(''), root('root')

【讨论】:

  • 我尝试了 Giorgi Nakeuri 发布的查询,并将我的查询的执行时间与 CAST(col AS XML)、他的 xquery 和没有 xquery 在一个有 1.025.484 行的表上进行了比较。 CAST(col AS XML) 和他的最后一个查询用了 11 秒,而 xquery 用了 37 秒。所以我没有看到性能差异。
  • 因为你的陈述等于我的第二个陈述。当然会有同样的计划。但是如果附加标签是不可接受的,那么我认为使用 xquery 的语句是唯一的方法。
  • 附加标签被 CAST(col AS XML) 消除。否则我为什么要将 XML 列转换为 XML? :)
  • 太好了,不知道。 +1
  • 谢谢。我从来没有想过用这种 xquery 技术来摆脱这个不需要的标签。 CAST 是一种蛮力方法。
【解决方案2】:

这并没有回答性能问题,这似乎与sql语句本身有关,或者与在其他语句中使用函数有关。试试这个。这会在 15 秒内返回 1.000.000 条记录的结果,我认为这非常好。

DECLARE @t TABLE ( x XML )

INSERT  INTO @t
        SELECT  '<XMLData><Type>1</Type></XMLData>'
        UNION
        SELECT  '<XMLData><Type>2</Type></XMLData>'

SELECT  x.query('/XMLData/*')
FROM    @t
FOR     XML PATH('XMLData') ,
            ROOT('AllMyData')

输出:

<AllMyData>
  <XMLData>
    <Type>1</Type>
  </XMLData>
  <XMLData>
    <Type>2</Type>
  </XMLData>
</AllMyData>

如果可以接受附加标签,那么您可以这样做:

SELECT  x
FROM    @t
FOR     XML PATH(''), ROOT('AllMyData')

对于 1.000.000 行,此查询在 3 秒内完成,输出如下:

<AllMyData>
  <x>
    <XMLData>
      <Type>1000000</Type>
    </XMLData>
  </x>
  <x>
    <XMLData>
      <Type>999999</Type>
    </XMLData>
  </x>
</AllMyData>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    • 2015-10-29
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多