« Javascript变量声明:var语句UBB的跨站脚本攻击 »

无限级分类的非递归实现(存储过程版)

或多或少都做过树状目录、产品分类之类的二级或三级菜单,如果遇到更多级的分类,
就一般使用递归了。在程序中使用递归或多或少会增加一些性能上的开销。

之前我用ASP.net在程序中实现过非递归的无限级分类目录,但考虑到移植性不强,就改
成了存储过程,发出来大家共同研究一下,到目前为止,测试过程中还没发现问题,另
外,代码方面没经过什么优化。

通常情况下,我们更多的操作是读取目录,所以,在下面的实现中,读取我们只需要一
Select语句就够了,不使用递归,理论上无限级~!

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

表结构:

表名:Tb_Column

表结构(所有字段非空):

Column_ID int 主键(注:非标识)

Column_Name nvarchar(50)分类名称

Parent_ID int 父分类ID(默认值0)

Column_Path nvarchar(1000) 分类路径

Column_Depth int分类深度(默认值0)

Column_Order int排序(默认值0)

Column_Intro nvarchar(1000)分类说明

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

存储过程一:新建分类

CREATE PROCEDURE sp_Column_Insert

(

@Parent_ID int,

@Column_Name nvarchar(50),

@Column_Intro nvarchar(1000)

)

AS

Declare @Err As int

Set @Err=0

Begin Tran

--通过现有记录获取栏目ID

Declare @Column_ID As int

Declare @Column_Depth As int

Select @Column_ID = Max(Column_ID) From Tb_Column

IF @Column_ID Is Not Null

Set @Column_ID = @Column_ID+1

Else

Set @Column_ID = 1

--判断是否是顶级栏目,设置其Column_Path和Column_Order

Declare @Column_Path As nvarchar(1000)

Declare @Column_Order As int

IF @Parent_ID = 0

Begin

Set @Column_Path =Ltrim(Str(@Column_ID))

Select @Column_Order = Max(Column_Order) From Tb_Column

IF @Column_Order Is Not Null

Set @Column_Order = @Column_Order + 1

Else --如果没有查询到记录,说明这是第一条记录

Set @Column_Order = 1

--深度

Set @Column_Depth = 1

End

Else

Begin

--获取父节点的路径和深度

Select @Column_Path = Column_Path ,@Column_Depth = Column_Depth From Tb_Colu
mn Where

Column_ID=@Parent_ID

IF @Column_Path Is Null

Begin

Set @Err = 1

Goto theEnd

End

--获取同父节点下的最大序号

Select @Column_Order = Max(Column_Order) From Tb_PicColumn Where Column_Path
like

''+@Column_Path+'%' Or Column_ID = @Parent_ID

IF @Column_Order Is Not Null --如果序号存在,那么将该序号后的所有序号都加1

Begin

--更新当前要插入节点后所有节点的序号

Update Tb_Column Set Column_Order = Column_Order +1 Where Column_Order

>@Column_Order

--同父节点下的最大序号加上1,构成自己的序号

Set @Column_Order = @Column_Order + 1

End

Else

Begin

Set @Err=1

Goto theEnd

End

--父节点的路径加上自己的ID号,构成自己的路径

Set @Column_Path = @Column_Path + '' + Ltrim(Str(@Column_ID))

--深度

Set @Column_Depth = @Column_Depth+1

End

Insert Into Tb_Column(Column_ID,Column_Name,Parent_ID,Column_Path,Column_Dep
th,Column_Order,Column_Intro)

Values(@Column_ID,@Column_Name,@Parent_ID,@Column_Path,@Column_Depth,@Column
_Order,@Column_Intro)

IF @@Error<>0

Begin

Set @Err=1

Goto theEnd

End

--更新当前记录之后的记录的ORDER

--Update Tb_Column Set Column_Order = Column_Order+1 Where Column_Order > @
Column_Order

theEnd:

IF @Err=0

Begin

Commit Tran

Return @Column_ID

End

Else

Begin

Rollback Tran

Return 0

End

GO

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

存储过程二:删除分类

CREATE PROCEDURE sp_Column_Delete

(

@Column_ID int

)

AS

Declare @Err As int

Set @Err = 0

Begin Tran

--首先查询该节点下是否有子节点

Select Column_ID From Tb_Column Where Parent_ID = @Column_ID

IF @@RowCount<>0

Begin

Set @Err = 1

Goto theEnd

End

--获取该节点的Column_Order,为了删除后整理其他记录的顺序

Declare @Column_Order As int

Select @Column_Order = Column_Order From Tb_Column Where Column_ID = @Column
_ID

IF @Column_Order Is NUll

Begin

Set @Err =2

Goto theEnd

End

--更新其他记录的Column_Order

Update Tb_Column Set Column_Order = Column_Order -1 Where Column_Order >@Col
umn_Order

IF @@Error<>0

Begin

Set @Err =3

Goto theEnd

End

--删除操作

Delete From Tb_Column Where Column_ID=@Column_ID

IF @@Error<>0

Begin

Set @Err =4

Goto theEnd

End

--更新其他记录的Column_ID

--Update Tb_Column Set Column_ID= Column_ID - 1 Where Column_ID >@Column_ID


--IF @@Error<>0

-- Begin

-- Set @Err =5

-- Goto theEnd

-- End

theEnd:

IF @Err = 0

Begin

Commit Tran

Return 0 --删除成功

End

Else

Begin

IF @Err=1

Begin

Rollback Tran

Return 1 --有子节点

End

Else

Begin

Rollback Tran

Return 2--未知错误

End

End

GO

原创文章如转载,请注明:转载自悠悠博客 [ http://www.ajaxstu.com/ ]

相关文章:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。