2010-03-09 5 views
7

У меня есть таблица, как это (упрощенный):генерировать структурированный (XML) документ из иерархических данных таблицы (T-SQL)

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> 

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

редактировать: Сво SQL Server Express 2008

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

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

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

+0

Вы хотите, чтобы это выглядело как ваш пример вывода или как настоящий xml? также, какая версия базы данных? –

+1

Я отредактировал оригинал сообщения, спасибо. –

+2

ужасно похож на этот вопрос, который был задан совсем недавно: http://stackoverflow.com/questions/2408459/t-sql-question-query-to-xml –

ответ

12

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

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

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

Дэйв: Это действительно вернет всю глубину дерева? –

+0

@Dave Это лучший, гибкий, но очень короткий! – Jeb50

+0

@ AndreasJansson Он делает. Просто попробовал себя, используя реальные данные, работает! Чтобы проверить это быстро, вы можете добавить верхнюю часть 5 в верхний SELECT. – Jeb50

Смежные вопросы