генерировать структурированный (xml) документ из данных иерархической таблицы (T-SQL) - PullRequest
7 голосов
/ 09 марта 2010

У меня есть такая таблица (упрощенно):

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-файл, структурированный в соответствии с родительскими идентификаторами

вот так (упрощенно)

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

Я полагаю, что это возможно с помощью некоторой рекурсии или чего-то в этом роде, но я не знаю как. Любая помощь с благодарностью!

edit: это SQL Server Express 2008

Меня не волнует, является ли это действительный XML или нет, потому что я использую его только для заполнения элемента управления в виде дерева.

edit2: Я бы, вероятно, использовал «FOR XML EXPLICIT», но я не совсем понимаю синтаксис, когда не имеет фиксированной максимальной глубины дерева.

edit3: для облегчения понимания задачи я добавил DDL для таблицы

Ответы [ 2 ]

12 голосов
/ 11 марта 2010

На основании ответа Реджепа (см. Комментарии) я создал следующее решение этой проблемы:

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>
2 голосов
/ 10 сентября 2012

Вы также можете сделать это без создания отдельной функции, включив подзапрос в качестве дополнительного столбца, который возвращает 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')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...