将多个XML连接到单个

时间:2015-04-09 14:54:35

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

我在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强制转换+ UDF非常懒散,看起来很难看。

有没有更好的方法呢?

2 个答案:

答案 0 :(得分: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')

答案 1 :(得分:0)

这不能解决性能问题,这似乎与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')

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

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