将多个xml行连接成一个

时间:2013-06-25 13:50:50

标签: xml sql-server-2008 tsql concatenation

问题:

我想从sql server获取更改以打印到(可能很大的)xml文件中。 Sql-Server启用了ChangeTracking以识别具有更改的实体。 因此,我编写了三个Scalar-valued Functions,可以为单个实体生成适当的XML。

  • GenerateAccountXml(int AccountId)
  • GenerateDeviceXml(int DeviceId)
  • GenerateServiceXml(int ServiceId)
  • 此外,我还有三个Table-valued Function,它返回特定的实体ID ChangeTracking Number。

  • GetAccountChangeSets(bigint changeTrackingId)
  • GetDeviceChangeSets(bigint changeTrackingId)
  • GetServiceChangeSets(bigint changeTrackingId)
  • 最后我打个电话:

    select
    
    (
        select
        (
            select [dbo].GenerateServiceXml( CT.ServiceId )
            from [dbo].GetServiceChangeSets( 22000 ) CT
        ) FOR XML PATH( 'Services' ), TYPE
    ),
    
    (
        select
        (
            select [dbo].GenerateDeviceXml( CT.DeviceId )
            from [dbo].GetDeviceChangeSets( 22000 ) CT
        ) FOR XML PATH( 'Devices' ), TYPE
    ),
    
    (
        select
        (
            select [dbo].GenerateAccountXml( CT.AccountId ) )
            from [dbo].GetAccountChangeSets( 22000 ) CT
        ) FOR XML PATH( 'Accounts' ), TYPE
    )
    
    FOR XML PATH( 'Changes' ), TYPE
    

    只要GetXXXChangeSets函数为每个实体仅返回一个EntityId,这就有效,但目前我为每个实体获得多个XML-Rows。现在问题是以下错误消息:

    Subquery returned more than 1 value. This is not permitted when the subquery 
    follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
    

    我尝试了STUFF命令,但它只接受varchar。当我在varchar(max)中转换输出时,<>符号被替换。

    此问题还有其他解决方案吗?

    1 个答案:

    答案 0 :(得分:1)

    我认为如果稍微更改查询,引擎应该处理此问题并为您提供多个XML节点。如果你想为元素集合创建一个根节点,你可能需要将XML PATH('Service')更改为'XML PATH(''),ROOT('Services')`将所有行组合成一个节点

    基本上我认为问题是你有一个太多的嵌套子选择。内置的FOR XML可以处理嵌套的SELECT表达式中的多行。

    select
    
    (   select [dbo].GenerateServiceXml( CT.ServiceId )
        from [dbo].GetServiceChangeSets( 22000 ) CT
        FOR XML PATH( 'Services' ), TYPE
    ),
    
    (
        select [dbo].GenerateDeviceXml( CT.DeviceId )
        from [dbo].GetDeviceChangeSets( 22000 ) CT
        FOR XML PATH( 'Devices' ), TYPE
    ),
    
    (
        select [dbo].GenerateAccountXml( CT.AccountId ) )
        from [dbo].GetAccountChangeSets( 22000 ) CT
        FOR XML PATH( 'Accounts' ), TYPE
    )
    
    FOR XML PATH( 'Changes' ), TYPE