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

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

之前我用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_Column  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_Depth,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  > @Column_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

存储过程三:编辑分类

 

CREATE   PROCEDURE  sp_Column_Update
(
@Column_ID   int ,
@Parent_ID   int ,
@Column_Name   nvarchar ( 50 ),
@Column_Intro   nvarchar ( 1000 )
)
AS
Declare   @Err   As   int
Set   @Err = 0

Begin   Tran

-- 获取修改前的:Parent_ID,Column_Depth,Column_Order
Declare   @oParent_ID   As   int
Declare   @oColumn_Depth   As   int
Declare   @oColumn_Order   As   int
Declare   @oColumn_Path   As   nvarchar ( 1000 )

Select   @oParent_ID   =  Parent_ID,  @oColumn_Depth   =  Column_Depth, @oColumn_Order   =  Column_Order,  @oColumn_Path   =  Column_Path   From  Tb_Column  Where  Column_ID  =   @Column_ID
IF   @oParent_ID   Is   Null
    
Begin
    
Set   @Err   =   1
    
Goto  theEnd
    
End

-- 如果父ID没有改变,则直接修改栏目名和栏目简介
IF   @oParent_ID   =   @Parent_ID
    
Begin
    
Update  Tb_Column  Set  Column_Name  =   @Column_Name ,Column_Intro  =   @Column_Intro   Where  Column_ID  =   @Column_ID
    
IF   @@Error   <>   0
    
Set   @Err   =   2
    
Goto  theEnd
    
End


Declare   @nColumn_Path   As   nvarchar ( 1000 )
Declare   @nColumn_Depth   As   int
Declare   @nColumn_Order   As   int

-- 获取当前节点作为父节点所包含的节点数[包括自身] 注:如果返回 “1” 说明是单节点
Declare   @theCount   As   int
Select   @theCount   =   Count (Column_ID)  From  Tb_Column  Where  Column_ID = @Column_ID   Or  Column_Path  like   '' + @oColumn_Path + ' |% '
IF   @theCount   Is   Null
Begin
    
Set   @Err   =   3
    
Goto  theEnd
End  

IF   @Parent_ID = 0   -- 如果是设置为顶级节点,将节点设置为最后一个顶级节点
Begin
-- Print '设置为顶级栏目'
Set   @nColumn_Path   =   Ltrim ( Str ( @Column_ID ))
Set   @nColumn_Depth   = 1

Select   @nColumn_Order   =   Max (Column_Order)  From  Tb_Column
IF   @nColumn_Order   Is   NULL
                  
Begin
     
Set   @Err   =   4
     
Goto  theEnd
     
End  

Set   @nColumn_Order   =   @nColumn_Order   -   @theCount   +   1

-- 更新三部分 1 节点本身 2 所有子节点 2 本树更改之前的后面记录的顺序
--
Print '更新本栏目之前位置后面的所有栏目[不包括本栏目下的子栏目]的:Column_Order'
Update  Tb_Column  Set  Column_Order  =  Column_Order - @theCount   Where  (Column_Order  > @oColumn_Order And  (Column_Path  Not   like   '' + @oColumn_Path + ' |% ' )
IF   @@Error   <>   0
    
Begin
    
Set   @Err   =   7
    
Goto  theEnd
    
End

-- Print '更新本栏目的:Parent_ID,Column_Path,Column_Depth,Column_Order,Column_Name,Column_Intro'
Print   ' Order :  ' + Ltrim ( Str ( @nColumn_Order ))
Update  Tb_Column  Set  Parent_ID = @Parent_ID ,Column_Path  =   @nColumn_Path ,Column_Depth  =   @nColumn_Depth ,Column_Order  =   @nColumn_Order , Column_Name  =   @Column_Name ,Column_Intro  =   @Column_Intro   Where  Column_ID  =   @Column_ID
IF   @@Error   <>   0
    
Begin
    
Set   @Err   =   5
    
Goto  theEnd
    
End

-- Print '更新本栏目下的所有子栏目的:Column_Path,Column_Depth,Column_Order'
              Update  Tb_Column  Set  Column_Path  =   Replace (Column_Path, @oColumn_Path , @nColumn_Path ),Column_Depth  =  Column_Depth  +  ( @nColumn_Depth - @oColumn_Depth ),Column_Order  =  Column_Order + @nColumn_Order - @oColumn_Order Where  Column_Path  like   '' + @oColumn_Path + ' |% '
IF   @@Error   <>   0
    
Begin
    
Set   @Err   =   6
    
Goto  theEnd
    
End


End  
Else
Begin
-- 获取未来父节点的相关信息,并设置本节点的相关值
Select   @nColumn_Depth   =  Column_Depth, @nColumn_Path   =  Column_Path  From  Tb_Column  Where  Column_ID  =   @Parent_ID
IF   @nColumn_Depth   Is    NULL   Or   @nColumn_Path   Is   Null
      
Begin
      
Set   @Err   =   8
      
Goto  theEnd
      
End  
Set   @nColumn_Depth   =   @nColumn_Depth   + 1
Select   @nColumn_Order   = Max (Column_Order)  From  Tb_Column  Where  Column_ID  =   @Parent_ID   Or   Column_Path  like   '' + @nColumn_Path + ' |% '
IF   @nColumn_Order   Is    NULL
      
Begin
      
Set   @Err   =   9
      
Goto  theEnd
      
End  

Set   @nColumn_Path   =   @nColumn_Path   + ' | ' +   Ltrim ( Str ( @Column_ID ))

IF   @nColumn_Order   =   @oColumn_Order + 1   -- 如果新的父节点是原来位置上端最近一个兄弟,则所有节点的顺序都不改变
                     Begin
Update  Tb_Column  Set  Parent_ID = @Parent_ID ,Column_Path  =   @nColumn_Path ,Column_Depth  =   @nColumn_Depth , Column_Name  =   @Column_Name ,Column_Intro  =   @Column_Intro   Where  Column_ID  =   @Column_ID
IF   @@Error   <>   0
    
Begin
    
Set   @Err   =   10
    
Goto  theEnd
    
End
       
End

Set    @nColumn_Order   =   @nColumn_Order   +   1  

-- 更新三部分 1 本树更改之前的后面(或前面)记录的顺序 1 节点本身  3 所有子节点
--
分为向上移或象下移
--
Print '更新本栏目之前位置后面的所有栏目[或者本栏目之后位置]  [不包括本栏目下的子栏目]的:Column_Order'
IF   @nColumn_Order   <   @oColumn_Order
Begin
Update  Tb_Column  Set  Column_Order  =  Column_Order + @theCount   Where  Column_Order < @oColumn_Order    And  Column_Order  >= @nColumn_Order   And  (Column_Path  Not   like   '' + @oColumn_Path + ' |% ' And  Column_ID <> @Column_ID
IF   @@Error   <>   0
        
Begin
        
Set   @Err   =   12
        
Goto  theEnd
        
End
End
Else
Begin
Update  Tb_Column  Set  Column_Order  =  Column_Order - @theCount   Where  Column_Order  > @oColumn_Order   And  Column_Order < @nColumn_Order    And  (Column_Path  Not   like   '' + @oColumn_Path + ' |% ' And  Column_ID <> @Column_ID
IF   @@Error   <>   0
        
Begin
        
Set   @Err   =   13
        
Goto  theEnd
        
End
End

-- Print '更新本栏目的:Parent_ID,Column_Path,Column_Depth,Column_Order,Column_Name,Column_Intro'
Print   ' Order :  ' + Ltrim ( Str ( @nColumn_Order ))
IF   @nColumn_Order   >   @oColumn_Order
Set   @nColumn_Order   =   @nColumn_Order   -   @theCount
Update  Tb_Column  Set  Parent_ID = @Parent_ID ,Column_Path  =   @nColumn_Path ,Column_Depth  =   @nColumn_Depth ,Column_Order  =   @nColumn_Order , Column_Name  =   @Column_Name ,Column_Intro  =   @Column_Intro   Where  Column_ID  =   @Column_ID
IF   @@Error   <>   0
    
Begin
    
Set   @Err   =   10
    
Goto  theEnd
    
End

-- Print '更新本栏目下的所有子栏目的:Column_Paht,Column_Depth,Column_Order'
              Update  Tb_Column  Set  Column_Path  =   Replace (Column_Path, @oColumn_Path , @nColumn_Path ),Column_Depth  =  Column_Depth  +  ( @nColumn_Depth - @oColumn_Depth ),Column_Order  =  Column_Order + ( @nColumn_Order - @oColumn_Order Where  Column_Path  like   '' + @oColumn_Path + ' |% '
IF   @@Error   <>   0
    
Begin
    
Set   @Err   =   11
    
Goto  theEnd
    
End
End

theEnd:
IF   @Err <> 0   -- 如果有错误则返回错误号
    Begin
   
Rollback   Tran
   
Return   @Err
   
End
Else       -- 如果没有错误就返回0
    Begin
   
Commit   Tran
   
Return   0
   
End
GO
=========================================
存储过程四:显示分类(只是一条select语句)
分类列表:
CREATE   PROCEDURE  sp_Column_List 
 
AS
SELECT  Column_ID, Column_Name, Parent_ID, Column_Path, Column_Depth, 
      Column_Order, Column_Intro
FROM  Tb_Column
ORDER   BY  Column_Order
GO


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升的信息化技术,让传统数据信息的管理升为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值