SQL Server 2008 - 需要列名作为属性

时间:2011-04-06 15:50:23

标签: sql xml sql-server-2008

我需要在SQL Server 2008中创建一个T-SQL查询,它以XML格式输出数据。但这是一个通用的过程,它使用不同的列查询数据,这些列可能在列名中有空格。因此,我希望XML将列名列为属性(元素名称中不允许使用空格)。

给定一个链接到子记录详细信息表的主表,我希望输出看起来像这样:

<master id="123">
   <detail colname="customer">John Smith</detail>
   <detail colname="amount">888.45</detail>
   <detail colname="date">01/01/01</detail>
</master>
<master id="456">
   <detail colname="customer">Suzie Jones</detail>
   <detail colname="amount">1000.25</detail>
   <detail colname="date">05/05/01</detail>
</master>

详细记录中的列可能会有所不同,因此我无法对其进行硬编码。

我相信这可能是使用PIVOT命令实现的,但是当你不知道数据结构时会变得非常难看。我觉得必须有一种方法可以让列名显示为属性值!

感谢任何建议。

5 个答案:

答案 0 :(得分:2)

使用XQuery可以将一组简单的xml行转换为所需的格式

DECLARE @X xml = '<row id="123" customer="John Smith" amount="888.45" date="01/01/01" />'
                +'<row id="456" customer="Suzie Jones" amount="1000.25" date="05/05/01" />'

SELECT  @X.query
        (
            '
            for     $id in //row/attribute::id
            return  <master id="{ string($id) }">
                        {
                            for $attr in //row[@id=$id]/attribute::*
                            where local-name($attr) != "id"
                            return <detail columnname="{ local-name($attr) }">{ string($attr) }</detail>
                        }
                    </master>
            '
        )

答案 1 :(得分:1)

另一个选项,它产生这样的输出(注意列名中的空格):

<root>
  <master id="123">
    <detail
      customer_x0020_name="John Smith"
      amount="888.4500"
      date="2001-01-01"
    />
  </master>
  <master id="456">
    <detail
      customer_x0020_name="Suzie Jones"
      amount="1000.2500"
      date="2001-05-05"
    />
  </master>
</root>

使用此脚本:

SELECT
    master.id,
(
    SELECT
        detail.[customer name],
        detail.amount,
        detail.[date]
    FROM dbo.detail AS detail
    WHERE
        detail.master_id = master.id
    FOR XML AUTO, TYPE
)
FROM dbo.master_table AS [master]
FOR XML AUTO, TYPE, ROOT('root')

...使用此样本数据:

CREATE TABLE dbo.master_table
(
    id INTEGER PRIMARY KEY
)

CREATE TABLE dbo.detail 
(
    master_id       INTEGER NULL REFERENCES dbo.master_table,
    [customer name] VARCHAR(30) NULL, 
    amount          MONEY NULL,
    [date]          DATE NULL
)

INSERT dbo.master_table
    (id)
VALUES 
    (123), 
    (456)

INSERT dbo.detail
    (master_id, [customer name], amount, [date]) 
VALUES 
    (123, 'John Smith', $888.45, '2001-01-01'),
    (456, 'Suzie Jones', $1000.25, '2001-05-05')

答案 2 :(得分:0)

使用T-SQL中的FOR XML子句

更多示例here

<强>更新

对于OP:使用FOR XML EXPLICIT从列显式设置属性值。

其他 EXPLICIT 示例:

http://blogs.technet.com/b/wardpond/archive/2006/09/08/454938.aspx

答案 3 :(得分:0)

有什么方法可以在查询中使用“FOR XML”吗?这对你来说很重要。

此页面详细介绍了一些与我认为您非常相似的内容:http://msdn.microsoft.com/en-us/library/ms345137(v=sql.90).aspx

答案 4 :(得分:0)

您可以按如下方式创建存储过程:

if exists (select * from dbo.sysobjects where id = object_id(N'[QueryXML]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure QueryXML
GO
create procedure QueryXML
  @Columns VarChar(1000),
  @Table VarChar(100)
as
begin
  declare @query varchar(1100)

  set @query = 'select (select ' + @Columns + ' from ' + @Table + ' for XML PATH(''columns'')) for XML PATH(''''), ROOT (''SampleXML'')'   

  exec (@query)

end

我试过这些表

create table dummy1(
  ID int not null identity(1,1),
  dummy1 int,
  dummy2 int,
  dummy3 int
)
GO

insert into dummy1 (dummy1,dummy2,dummy3) values(1,2,3)
insert into dummy1 (dummy1,dummy2,dummy3) values(4,5,6)
insert into dummy1 (dummy1,dummy2,dummy3) values(7,8,9)
insert into dummy1 (dummy1,dummy2,dummy3) values(10,11,12)
insert into dummy1 (dummy1,dummy2,dummy3) values(13,14,15)
insert into dummy1 (dummy1,dummy2,dummy3) values(16,17,18)

示例:

exec QueryXML @Columns = 'ID, dummy1', @Table = 'dummy1'
exec QueryXML @Columns = 'ID, dummy2,dummy3', @Table = 'dummy1'
exec QueryXML @Columns = 'ID, dummy1,dummy2,dummy3', @Table = 'dummy1'

您还可以查看:sql-server-simple-example-of-creating-xml-file-using-t-sql