从分层表数据(T-SQL)生成结构化(xml)文档

时间:2010-03-09 13:16:44

标签: xml tsql recursion

我有一张这样的表(简化):

ID   |   Name  |   Parent
---------------------------------
1    |  IND    |   NULL
2    |  INS    |   5
3    |  CON    |   NULL
4    |  AUT    |   1
5    |  FIN    |   NULL
6    |  PHA    |   1
7    |  CFIN   |   5
8    |  CMRKT  |   7

DDL:

CREATE TABLE [dbo].[tblIndustryCodes](
        [IdIndustry] [int] IDENTITY(1,1) NOT NULL,
        [IndustryCode] [nvarchar](5) NULL,
        [IndustryName] [nvarchar](50) NULL,
        [ParentId] [int] NULL,
 CONSTRAINT [PK_tblIndustryCodes] PRIMARY KEY CLUSTERED (       [IdIndustry] ASC))

插入:

INSERT INTO [tblIndustryCodes]
           ([IndustryCode]
           ,[IndustryName]
           ,[ParentId])
     VALUES
           ('IND','Industry',NULL),
           ('PHARM','Pharmacy',1),
           ('FIN','Finance',NULL),
           ('CFIN','Corporate Finance',3),
           ('CMRKT','Capital Markets',4)

我想从中生成一个xml文件,该文件是根据父ID

构建的 像这样(简化)

<IND>
   <AUT>
   <PHA>
<CON>
<FIN>
   <CFIN>
      <CMRKT>

我相信它的完成可能会有某种类似的递归或类似的东西,但我不知道如何。非常感谢任何帮助!

编辑:它是SQL Server Express 2008

我真的不在乎它是否是有效的XML,因为我只使用它来填充树视图控件。

edit2:我可能会使用“FOR XML EXPLICIT”,但是当没有固定的树最大深度时,我真的不懂语法。

edit3:为了更容易理解任务,我为表添加了DDL

2 个答案:

答案 0 :(得分:12)

基于Recep的回答(见评论)我为这个问题创建了以下解决方案:

<强> 1。创建递归函数

CREATE function SelectChild(@key as int)
returns xml
begin
    return (
        select 
            IdIndustry as "@key", 
            ParentId as "@parentkey",
            IndustryCode as "@Code",
            IndustryName as "@Name",
            dbo.SelectChild(IdIndustry)
        from tblIndustryCodes
        where ParentId = @key
        for xml path('record'), type
    )
end

<强> 2。构建一个SELECT语句,调用函数

SELECT 
    IdIndustry AS "@key", 
    '' AS "@parentkey",
    IndustryCode as "@Code",
    IndustryName as "@Name",
    dbo.SelectChild(IdIndustry)     
FROM dbo.tblIndustryCodes
WHERE ParentId is null
FOR XML PATH ('record')

这创建了一个分层XML,无论树实际有多深:

<record key="1" parentkey="" Code="IND" Name="Industry">
  <record key="2" parentkey="1" Code="AUTO" Name="Automotive" />
  <record key="3" parentkey="1" Code="PHARM" Name="Pharmaceuticals" />
</record>
<record key="4" parentkey="" Code="FIN" Name="Finance">
  <record key="5" parentkey="4" Code="CFIN" Name="Corporate Finance">
    <record key="6" parentkey="5" Code="CMRKT" Name="Capital Markets" />
  </record>
</record>
<record key="7" parentkey="" Code="CON" Name="Cosulting">
  <record key="8" parentkey="7" Code="IMPL" Name="Implementation" />
  <record key="9" parentkey="7" Code="STRAT" Name="Strategy" />
</record>

答案 1 :(得分:2)

您也可以在不创建单独函数的情况下执行此操作,方法是将子查询包含为返回XML的附加列。例如,以下内容将返回包含用户及其相关角色列表的分层XML文档:

SELECT 
    FirstName, LastName,
    CONVERT(XML, 
      (SELECT r.UserID, r.RoleID
       FROM global.[UserRole] r
       WHERE r.USerID = [user].UserID
       FOR XML RAW ('Role'), ELEMENTS, root('Roles')
      ))
FROM global.[user]
FOR XML RAW ('User'), ELEMENTS, root('Users')