[SQL] 產出巢狀式 XML

摘要:[SQL] 產出巢狀式 XML

  又是一個工作需要 , 順便學習使用新方法來達到需求

        1. 先來建立一張資料表

  


USE [TestDB]
GO

/****** Object:  Table [dbo].[Employees]    Script Date: 08/11/2011 17:11:41 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Employees](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[Name] [nvarchar](50) NULL,
	[FullName] [nvarchar](120) NULL,
	[EmployeeNo] [nvarchar](1000) NULL,
	[EmployeeIdUp] [int] NULL,
	[Layer] [int] NULL,
 CONSTRAINT [PK_Organization] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

         2. 再新增幾筆資料


insert into Employees values(N'總經理室',N'總經理室','M0001',null,0)

insert into Employees values(N'特助室',N'總經理室/特助室','C0001',1,1)

insert into Employees values(N'經理室',N'總經理室/經理室','M0101',1,1)

insert into Employees values(N'會計室',N'總經理室/會計室','M0102',1,1)

insert into Employees values(N'大特助',N'總經理室/特助室','C00011',2,2)

insert into Employees values(N'小特助',N'總經理室/特助室','C00012',2,2)

insert into Employees values(N'專案經理A',N'總經理室/經理室','M01011',3,2)

insert into Employees values(N'專案經理B',N'總經理室/經理室','M00012',3,2)

insert into Employees values(N'專案經理C',N'總經理室/經理室','M00013',3,2)

     

        3.  利用 SQL  FOR XML 來產生巢狀式 XML             


select Id as '@EmployeeId',ISNULL(FullName,'') as '@FullName',Name as '@Name',EmployeeIdUp as '@EmployeeIdUp',
( select Id as '@EmployeeId',ISNULL(FullName,'') as '@FullName',Name as '@Name',EmployeeIdUp as '@EmployeeIdUp',
( select Id as '@EmployeeId',ISNULL(FullName,'') as '@FullName',Name as '@Name',EmployeeIdUp as '@EmployeeIdUp' from Employees as Level2 
	where Layer=2 and Level1.Id=Level2.EmployeeIdUp order by Level2.Id for xml Path('Organization'), type) from Employees as Level1 
			where Layer=1 and Level0.Id=Level1.EmployeeIdUp order by Level1.Id for xml Path('Organization'), type) from Employees as Level0 where Level0.Id=1
	 for xml Path('Organization'), type

       4. 產生出來的結果如下圖

 5. 程式的部分,再用 ExecuteXMLReader 來接收即可

====================== 以上是在網路很常見的範例 ===============================

  相信很多人會把第 3 點的語法改 CTE 來執行,拔特,在 CTE 裡是不能執行 FOR XML,雖然可以在最後把 CTE 抛出來的資料表使用 FOR XML ,

跑來的 XML 是有巢狀式啦,不過會跟你想像中的不太一樣,在下為了這一點也傷腦筋很久(其實是腦筋不太靈活),最後想出來一個可能不妥當的方式

,利用動態組成查詢字串的方式(嘿嘿嘿.........偷偷參考 Hunterpo前輩及johnny前輩)組合出語法,如下所示:


declare @depth int
 declare @childe varchar(10)
 declare @parent varchar(10)
 declare @outputStatement nvarchar(4000)
 set @depth=10 --層數
 while(@depth>0)
 begin
	set @childe='Level'+CAST(@depth as varchar(2))
	set @parent='Level'+CAST(@depth-1 as varchar(2))
	if(@outputStatement is null)
	begin
	
		set @outputStatement='select Id as ''@EmployeeId'',ISNULL(FullName,'''') as ''@FullName'',Name as ''@Name'',EmployeeIdUp as ''@EmployeeIdUp'' from Employees as '+@childe+' 
			where Layer='+CAST(@depth as varchar(2))+' and '+@parent+'.Id='+@childe+'.EmployeeIdUp order by '+@childe+'.Id for xml Path(''Employees''), type'
	end
	else
	begin
		set @outputStatement='select Id as ''@EmployeeId'',ISNULL(FullName,'''') as ''@FullName'',Name as ''@Name'',EmployeeIdUp as ''@EmployeeIdUp'',( '
			+@outputStatement+') from Employees as '+@childe+' 
			where Layer='+CAST(@depth as varchar(2))+' and '+@parent+'.Id='+@childe+'.EmployeeIdUp order by '+@childe+'.Id for xml Path(''Employees''), type'
	end
   set @depth=@depth-1
 end
 
 set @outputStatement='select Id as ''@EmployeeId'',ISNULL(FullName,'''') as ''@FullName'',Name as ''@Name'',EmployeeIdUp as ''@EmployeeIdUp'',( '
	+@outputStatement+') from Employees as '+@parent+' 
	where '+@parent+'.Layer=0 for xml Path(''Employees''), type'

print @outputStatement
EXEC sp_executesql @outputStatement

使用的方法可能不是很好,畢竟用了迴圈來跑,如果有更好的方式或能改進的地方,希望各位前輩多多請教

 

===================

大家好  , 我叫芋宅宅

我很菜 , 請各位前輩指教