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

发布于 2024-08-24 19:36:58 字数 1407 浏览 3 评论 0原文

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

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))

INSERTS:

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

I have a table like this (simplified):

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))

INSERTS:

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

And I'd like to generate a xml file from it which is structured according to the parent IDs

like this (simplified)

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

I believe its done maybe with some kinda recursion or something like that, but I don't know how. Any help is greatly appreciated!

edit: Its a SQL Server Express 2008

I don't really care if it's valid XML or not, because I only use it to populate a treeview control.

edit2: I would probably use "FOR XML EXPLICIT" but I don't really understand the syntax when there is no fixed maximum depth of the tree.

edit3: for easier understanding of the task, I added the DDL for the table

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谜兔 2024-08-31 19:36:58

根据 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>

Based on Recep's answer (see comments) I created the following solution for this problem:

1. Create a recursive function

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. Build a SELECT statement, that calls the function

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')

This creates a hierarchical XML, no matter how deep the tree actually is:

<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>
背叛残局 2024-08-31 19:36:58

您还可以在不创建单独的函数的情况下执行此操作,只需将子查询包含为返回 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')

You can also do this without creating a separate function, by including the sub-query as an additional column that returns XML. For example, the following will return a hierarchical XML document containing users and their associated list of roles:

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')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文