请高手解释这段代码的原理

rainbowsoftware 2009-12-18 12:28:22
USE [Northwind]
GO
/****** 对象: StoredProcedure [dbo].[USP_TREEVIEW] 脚本日期: 12/18/2009 07:59:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[USP_TREEVIEW]
@TABLE NVARCHAR(50) --表名
,@PIDCOL NVARCHAR(50) --父结点标识字段名
,@IDCOL NVARCHAR(50) --子结点标识字段名
,@DESCCOL NVARCHAR(50) --显示节点标签字段
AS
BEGIN
DECLARE @SQL VARCHAR(8000)

SELECT @SQL='
DECLARE @TMP TABLE(
[PID_NUM] [INT] NULL,
[ID_NUM] [int] IDENTITY (1, 1) NOT NULL ,
['+@PIDCOL+'] [nvarchar] (20) NULL ,
['+@IDCOL+'] [nvarchar] (20) NOT NULL ,
['+@DESCCOL+'] [ntext] NULL,
PATH NVARCHAR(1000) NULL,
NEXT_PARENTID INT NULL,
PRE_PARENTID INT NULL,
PATHCHAR NVARCHAR(1000) DEFAULT('''') NULL,
ISFIRST BIT DEFAULT(1) NULL
)
INSERT @TMP (['+@PIDCOL+'],['+@IDCOL+'],['+@DESCCOL+'])
SELECT ['+@PIDCOL+'],['+@IDCOL+'],['+@DESCCOL+'] FROM '+@TABLE+' order by '+@PIDCOL+','+@IDCOL+'

UPDATE A SET PID_NUM=B.ID_NUM,PATH=CAST(A.ID_NUM AS NVARCHAR),NEXT_PARENTID=B.ID_NUM
FROM @TMP A LEFT JOIN @TMP B ON A.'+@PIDCOL+'=B.'+@IDCOL+'

WHILE @@ROWCOUNT!=0
UPDATE A SET
A.PATH=ISNULL(CAST(A.NEXT_PARENTID AS NVARCHAR)+''.'','''')+A.PATH
,A.PATHCHAR=CASE WHEN A.ISFIRST=1 THEN
CASE WHEN not exists (select * from @TMP where PID_NUM=A.NEXT_PARENTID and ID_NUM>A.ID_NUM ) THEN
''└'' + replicate(''─'', 2) + A.PATHCHAR
ELSE
''├'' +replicate(''─'', 2) + A.PATHCHAR
END
ELSE
CASE WHEN exists (select * from @TMP where PID_NUM=A.NEXT_PARENTID and ID_NUM>( select ID_NUM from @TMP where ID_NUM=A.PRE_PARENTID) ) THEN
''│'' + replicate('' '', 2) +A.PATHCHAR
ELSE
replicate('' '', 3) +A.PATHCHAR
END
END
,A.PRE_PARENTID=A.NEXT_PARENTID
,A.NEXT_PARENTID=B.PID_NUM
,A.ISFIRST=0
FROM @TMP A LEFT JOIN @TMP B ON A.NEXT_PARENTID=B.ID_NUM
WHERE A.NEXT_PARENTID IS NOT NULL
--SELECT * FROM @TMP ORDER BY PATH
SELECT PATHCHAR+CAST(['+@DESCCOL+'] AS NVARCHAR) AS '+'[Label_'+@DESCCOL+'],['+@IDCOL+'],['+@PIDCOL+']
FROM @TMP
ORDER BY PATH
'
--print (@SQL)
exec( @SQL)
END
EXEC USP_TREEVIEW 'Northwind..Employees','ReportsTo','EmployeeID','LastName'
...全文
213 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
rainbowsoftware 2009-12-21
  • 打赏
  • 举报
回复
UPDATE A SET
A.PATH=ISNULL(CAST(A.NEXT_PARENTID AS NVARCHAR)+'.','')+A.PATH --这里只记录层级没关系其实没用到。ID.ID 的形式
,A.PATHCHAR=CASE WHEN A.ISFIRST=1 THEN --这个A.ISFIRST=1其实就是记录一下是不是第一级,以后就没啥用了因为第一级的├──和└──而不是第一级就要├──前面加一个“|”和TAB,有点不一样
CASE WHEN not exists (select * from @TMP where PID_NUM=A.NEXT_PARENTID and ID_NUM>A.ID_NUM ) THEN
'└' + replicate('─', 2) + A.PATHCHAR
ELSE
'├' +replicate('─', 2) + A.PATHCHAR
END
ELSE
CASE WHEN exists (select * from @TMP where PID_NUM=A.NEXT_PARENTID and ID_NUM>( select ID_NUM from @TMP where ID_NUM=A.PRE_PARENTID) ) THEN
'│' + replicate(' ', 2) +A.PATHCHAR
ELSE
replicate(' ', 3) +A.PATHCHAR
END
END
,A.PRE_PARENTID=A.NEXT_PARENTID
我试图将它修改成临时表而不是表变量时,上面这一句老提示语法错误,不知怎么回事
rainbowsoftware 2009-12-18
  • 打赏
  • 举报
回复
我知道是树形结构,不过我想详细知道它的实现方法。
-狙击手- 2009-12-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 fcuandy 的回复:]
似曾相识,不知道我有没有写过,记不起来了。
[/Quote]

我认识你
fcuandy 2009-12-18
  • 打赏
  • 举报
回复
似曾相识,不知道我有没有写过,记不起来了。
-狙击手- 2009-12-18
  • 打赏
  • 举报
回复
树型结构
Dream_1986 2009-12-18
  • 打赏
  • 举报
回复
帮顶
zjj1028 2009-12-18
  • 打赏
  • 举报
回复
我也想知道,嘻..,给点分吧
dawugui 2009-12-18
  • 打赏
  • 举报
回复
友情帮顶.
小坏猪猪 2009-12-18
  • 打赏
  • 举报
回复
别告诉我们,要一条一条给你解释哦
~在路上~ 2009-12-18
  • 打赏
  • 举报
回复
动态构成了几条语句,怎么构成是功夫活了,不用讲
,执行到最后呢,就是执行@SQL里的SQL语句了。
@SQL执行后就是下面的样子
下面是一步步的讲解了
--建表
DECLARE @TMP TABLE(
[PID_NUM] [INT] NULL, --上级ID
[ID_NUM] [int] IDENTITY (1, 1) NOT NULL ,
[ReportsTo] [nvarchar] (20) NULL ,
[EmployeeID] [nvarchar] (20) NOT NULL ,
[LastName] [ntext] NULL,
PATH NVARCHAR(1000) NULL,
NEXT_PARENTID INT NULL,
PRE_PARENTID INT NULL,
PATHCHAR NVARCHAR(1000) DEFAULT('') NULL,
ISFIRST BIT DEFAULT(1) NULL
)
INSERT @TMP ([ReportsTo],[EmployeeID],[LastName])
SELECT [ReportsTo],[EmployeeID],[LastName] FROM Northwind..Employees order by ReportsTo,EmployeeID
--把每条记录的上级ID即PID_NUM指定
UPDATE A SET PID_NUM=B.ID_NUM,PATH=CAST(A.ID_NUM AS NVARCHAR),NEXT_PARENTID=B.ID_NUM
FROM @TMP A LEFT JOIN @TMP B ON A.ReportsTo=B.EmployeeID
--一直UPDATE到没有符合条件的记录(更新过的记录NEXT_PARENTID就是空的,条件里是IS NOT NULL)
--NEXT_PARENTID不是空的(空的表示最高一级,或已更新过)每更新一次就把最近一级的更新为空
--,并更新pathchar(将更新本级最大的ID_num更新为└──否则就更新为├──)更新一次就在前面加一前
WHILE @@ROWCOUNT!=0
UPDATE A SET
A.PATH=ISNULL(CAST(A.NEXT_PARENTID AS NVARCHAR)+'.','')+A.PATH --这里只记录层级没关系其实没用到。ID.ID 的形式
,A.PATHCHAR=CASE WHEN A.ISFIRST=1 THEN --这个A.ISFIRST=1其实就是记录一下是不是第一级,以后就没啥用了因为第一级的├──和└──而不是第一级就要├──前面加一个“|”和TAB,有点不一样
CASE WHEN not exists (select * from @TMP where PID_NUM=A.NEXT_PARENTID and ID_NUM>A.ID_NUM ) THEN
'└' + replicate('─', 2) + A.PATHCHAR
ELSE
'├' +replicate('─', 2) + A.PATHCHAR
END
ELSE
CASE WHEN exists (select * from @TMP where PID_NUM=A.NEXT_PARENTID and ID_NUM>( select ID_NUM from @TMP where ID_NUM=A.PRE_PARENTID) ) THEN
'│' + replicate(' ', 2) +A.PATHCHAR
ELSE
replicate(' ', 3) +A.PATHCHAR
END
END
,A.PRE_PARENTID=A.NEXT_PARENTID --这个不管它其实没啥用的。不要都行
--主要要看清from后面的 ON A.NEXT_PARENTID=B.ID_NUM 也就是把更新过的设置成第一级的NULL 了,因为顶级的PID_NUM就是NULL值
--,然后把PRE_PARENTID设置成最顶级的ID_NUM,以方便下次更新又把它更新成空的,因为顶级的PID_NUM就是NULL值
,A.NEXT_PARENTID=B.PID_NUM
,A.ISFIRST=0 --这个说过了为什么了
FROM @TMP A LEFT JOIN @TMP B ON A.NEXT_PARENTID=B.ID_NUM
WHERE A.NEXT_PARENTID IS NOT NULL --当然只能更新非NULL值的记录了。因为前面说了,只有顶级和被更新过的才会是NULL。

--这个简单了,就是把那些树状图形加上名字显示出了。
SELECT PATHCHAR+CAST([LastName] AS NVARCHAR) AS [Label_LastName],[EmployeeID],[ReportsTo]
FROM @TMP
ORDER BY PATH
--这个很绕,一步一步看还可以理解了。
--关键的地方就是ISFIRST来判断是不是第一层,只影响PATHCHAR里的内容“├──”前面要不要加"|"和tab符
--PATHCHAR就是记录树图了
feixianxxx 2009-12-18
  • 打赏
  • 举报
回复
围观 2个互相认识的人
--小F-- 2009-12-18
  • 打赏
  • 举报
回复
一条一条的分批看 这个能怎么解释?
bancxc 2009-12-18
  • 打赏
  • 举报
回复
楼上的我都不认识

34,875

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧