如何查询SQL Server并使用列名和值作为属性生成XML

时间:2012-03-03 06:12:36

标签: sql-server-2008 sqlxml

我正在试图弄清楚如何查询生成如下所示的xml的表: (这是AdventureWorks数据库中的一个示例。

我可以很容易地将列名称作为元素,但是可以将列名和值都作为属性吗?我试图弄清楚如何以通用方式执行此操作,因此我不想使用FOR EXPLICIT对列名进行硬编码

    <TABLE name="StateProvince">
        <ROW>
            <COL name="StateProvinceID" value="1" />
            <COL name="StateProvinceCode" value="AB" />
            <COL name="CountryRegionCode" value="CA" />
            <COL name="IsOnlyStateProvinceFlag" value="0" />
            <COL name="Name" value="Alberta" />
            <COL name="TerritoryID" value="6" />
            <COL name="rowguid" value="298C2880-AB1C-4982-A5AD-A36EB4BA0D34" />
            <COL name="ModifiedDate" value="2004-03-11T10:17:21.587" />
        </ROW>
    </TABLE>

2 个答案:

答案 0 :(得分:4)

在不指定列名的情况下执行此操作有点棘手,但可行 要使用此功能,您需要将@T替换为您的表名,并将表名常量'StateProvince'更改为您的表名。

declare @T table
(
  StateProvinceID int,
  StateProvinceCode char(2),
  CountryRegionCode char(2),
  IsOnlyStateProvinceFlag int,
  Name varchar(50),
  TerritoryID int,
  rowguid uniqueidentifier,
  ModifiedDate datetime
)

insert into @T values
(1, 'AB', 'CA', 0, 'Alberta', 6, '298C2880-AB1C-4982-A5AD-A36EB4BA0D34', '2004-03-11T10:17:21.587'),
(2, 'AB', 'CA', 0, 'Alberta', 6, '298C2880-AB1C-4982-A5AD-A36EB4BA0D34', '2004-03-11T10:17:21.587')

select 'StateProvince' as [@name],
  (
    select 
      (
        select T3.N.value('local-name(.)', 'sysname') as [@name],
               T3.N.value('.', 'nvarchar(max)') as [@value]
        from (
               select T1.*
               for xml path(''), type
             ) T2(N)
          cross apply T2.N.nodes('*') as T3(N)       
        for xml path('COL'), root('ROW'), type
      )         
    from @T as T1
    for xml path(''), type
  )
for xml path('TABLE')  

结果:

<TABLE name="StateProvince">
  <ROW>
    <COL name="StateProvinceID" value="1" />
    <COL name="StateProvinceCode" value="AB" />
    <COL name="CountryRegionCode" value="CA" />
    <COL name="IsOnlyStateProvinceFlag" value="0" />
    <COL name="Name" value="Alberta" />
    <COL name="TerritoryID" value="6" />
    <COL name="rowguid" value="298C2880-AB1C-4982-A5AD-A36EB4BA0D34" />
    <COL name="ModifiedDate" value="2004-03-11T10:17:21.587" />
  </ROW>
  <ROW>
    <COL name="StateProvinceID" value="2" />
    <COL name="StateProvinceCode" value="AB" />
    <COL name="CountryRegionCode" value="CA" />
    <COL name="IsOnlyStateProvinceFlag" value="0" />
    <COL name="Name" value="Alberta" />
    <COL name="TerritoryID" value="6" />
    <COL name="rowguid" value="298C2880-AB1C-4982-A5AD-A36EB4BA0D34" />
    <COL name="ModifiedDate" value="2004-03-11T10:17:21.587" />
  </ROW>
</TABLE>

注意:表中的列名必须是有效的XML元素名称。例如,您可以在列名称中没有任何空格。

答案 1 :(得分:1)

我不认为只使用SQL Server的功能就可以实现100%的目标 - 你可以接近,但不是100%。

我的查询使用SQL Server 2005及更新版本中提供的FOR XML PATH结构:

SELECT 
    [StateProvinceID] AS 'COL/@StateProvinceID',
    '',
    [StateProvinceCode] AS 'COL/@StateProvinceCode',
    '',
    [CountryRegionCode] AS 'COL/@CountryRegionCode',
    '',
    [IsOnlyStateProvinceFlag] AS 'COL/@IsOnlyStateProvinceFlag',
    '',
    [Name] AS 'COL/@Name',
    '',
    [TerritoryID] AS 'COL/@TerritoryID',
    '',
    [rowguid] AS 'COL/@rowguid',
    '',
    [ModifiedDate] AS 'COL/@ModifiedDate'
  FROM [Person].[StateProvince]
  FOR XML PATH('ROW'), ROOT('TABLE')

导致XML如下:

<TABLE>
  <ROW>
    <COL StateProvinceID="1" />
    <COL StateProvinceCode="AB " />
    <COL CountryRegionCode="CA" />
    <COL IsOnlyStateProvinceFlag="0" />
    <COL Name="Alberta" />
    <COL TerritoryID="6" />
    <COL rowguid="298C2880-AB1C-4982-A5AD-A36EB4BA0D34" />
    <COL ModifiedDate="2008-03-11T10:17:21.587" />
  </ROW>
  <ROW>
    <COL StateProvinceID="2" />
    <COL StateProvinceCode="AK " />
    <COL CountryRegionCode="US" />
    <COL IsOnlyStateProvinceFlag="0" />
    <COL Name="Alaska" />
    <COL TerritoryID="1" />
    <COL rowguid="5B7B8462-A888-4E0B-A3E1-7278F8AF107E" />
    <COL ModifiedDate="2008-03-11T10:17:21.587" />
  </ROW>
  ..........
</TABLE>

您需要在每个属性之间选择“空”列,以避免所有列值都插入到单个<COL .... />元素中,如下所示:

    <COL StateProvinceID="2"  
         StateProvinceCode="AK "  
         CountryRegionCode="US"    
         IsOnlyStateProvinceFlag="0"  
         Name="Alaska"  
         TerritoryID="1" 
         rowguid="5B7B8462-A888-4E0B-A3E1-7278F8AF107E"  
         ModifiedDate="2008-03-11T10:17:21.587" />