热门:网页模板.net视频教程JQueryMVCjsonExtJs源码示例三级联动JQuery菜单
您现在的位置:.Net中文社区>> 数据库>>正文内容

无限级分类 存储过程

发布时间:2010年03月06日点击数: 佚名

曾祥展

创建:

  1. if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Class]'and OBJECTPROPERTY(id, N'IsUserTable') = 1)    
  2. drop table [dbo].[Class]    
  3. GO    
  4.    
  5. Create TABLE [dbo].[Class] (    
  6.      [Class_Id] [intNOT NULL ,    
  7.      [Class_Name] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,    
  8.      [Parent_ID] [intNULL ,    
  9.      [Class_Path] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,    
  10.      [Class_Depth] [intNULL ,    
  11.      [Class_Order] [intNULL ,    
  12.      [Class_Intro] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL     
  13. ON [PRIMARY]    
  14. GO    
  15.  
  16.  
  17.  
  18. Alter TABLE [dbo].[Class] ADD     
  19.      CONSTRAINT [DF_Class_Parent_ID] DEFAULT (0) FOR [Parent_ID],    
  20.      CONSTRAINT [DF_Class_Class_Depth] DEFAULT (0) FOR [Class_Depth],    
  21.      CONSTRAINT [DF_Class_Class_Order] DEFAULT (0) FOR [Class_Order],    
  22.      CONSTRAINT [PK_Class] PRIMARY KEY   CLUSTERED     
  23.      (    
  24.          [Class_Id]    
  25.      )   ON [PRIMARY]     
  26. GO    
  27.  
  28. exec sp_addextendedproperty N'MS_Description', N'分类深度(默认值0)', N'user', N'dbo', N'table', N'Class', N'column', N'Class_Depth'   
  29. GO    
  30. exec sp_addextendedproperty N'MS_Description', N'int 主键(注:非标识)', N'user', N'dbo', N'table', N'Class', N'column', N'Class_Id'   
  31. GO    
  32. exec sp_addextendedproperty N'MS_Description', N'分类说明', N'user', N'dbo', N'table', N'Class', N'column', N'Class_Intro'   
  33. GO    
  34. exec sp_addextendedproperty N'MS_Description', N'分类名称', N'user', N'dbo', N'table', N'Class', N'column', N'Class_Name'   
  35. GO    
  36. exec sp_addextendedproperty N'MS_Description', N'排序(默认值0)', N'user', N'dbo', N'table', N'Class', N'column', N'Class_Order'   
  37. GO    
  38. exec sp_addextendedproperty N'MS_Description', N'分类路径', N'user', N'dbo', N'table', N'Class', N'column', N'Class_Path'   
  39. GO    
  40. exec sp_addextendedproperty N'MS_Description', N'父分类ID(默认值0)', N'user', N'dbo', N'table', N'Class', N'column', N'Parent_ID'   
  41.    

增加:

  1. Create PROCEDURE sp_Class_Insert    
  2. (    
  3. @Parent_ID int,    
  4. @Class_Name nvarchar(50),    
  5. @Class_Intro nvarchar(1000)    
  6. )    
  7. AS    
  8. Declare @Err As int   
  9. Set @Err=0    
  10.    
  11. Begin Tran    
  12. --通过现有记录获取栏目ID    
  13. Declare @Class_Id As int   
  14. Declare @Class_Depth As int   
  15. Select @Class_Id = Max(Class_Id) From Class    
  16. IF @Class_Id Is Not Null    
  17. Set @Class_Id = @Class_Id+1    
  18. Else    
  19. Set @Class_Id = 1    
  20.    
  21. --判断是否是顶级栏目,设置其Class_Path和Class_Order    
  22. Declare @Class_Path As nvarchar(1000)    
  23. Declare @Class_Order As int   
  24. IF @Parent_ID = 0    
  25. Begin    
  26. Set @Class_Path =Ltrim(Str(@Class_Id))    
  27. Select @Class_Order = Max(Class_Order) From Class    
  28. IF @Class_Order Is Not Null    
  29. Set @Class_Order = @Class_Order + 1    
  30. Else --如果没有查询到记录,说明这是第一条记录    
  31. Set @Class_Order = 1    
  32.    
  33. --深度    
  34. Set @Class_Depth = 1    
  35. End    
  36. Else    
  37. Begin    
  38. --获取父节点的路径和深度    
  39. Select @Class_Path = Class_Path ,@Class_Depth = Class_Depth From Class Where     
  40.    
  41. Class_Id=@Parent_ID    
  42. IF @Class_Path Is Null    
  43. Begin    
  44. Set @Err = 1    
  45. Goto theEnd    
  46. End    
  47.    
  48. --获取同父节点下的最大序号    
  49. Select @Class_Order = Max(Class_Order) From Class Where Class_Path like     
  50.    
  51. ''+@Class_Path+'|%'   or Class_Id = @Parent_ID    
  52. IF @Class_Order Is Not Null --如果序号存在,那么将该序号后的所有序号都加1    
  53. Begin     
  54. --更新当前要插入节点后所有节点的序号    
  55. Update Class Set Class_Order = Class_Order +1 Where Class_Order     
  56.    
  57. >@Class_Order    
  58. --同父节点下的最大序号加上1,构成自己的序号    
  59. Set @Class_Order = @Class_Order + 1    
  60. End     
  61. Else    
  62. Begin    
  63. Set @Err=1    
  64. Goto theEnd    
  65. End    
  66.    
  67. --父节点的路径加上自己的ID号,构成自己的路径    
  68. Set @Class_Path = @Class_Path + '|' + Ltrim(Str(@Class_Id))    
  69.    
  70. --深度    
  71. Set @Class_Depth = @Class_Depth+1    
  72.    
  73. End    
  74.    
  75. Insert Into Class(Class_Id,Class_Name,Parent_ID,Class_Path,Class_Depth,Class_Order,Class_Intro)     
  76.    
  77. Values(@Class_Id,@Class_Name,@Parent_ID,@Class_Path,@Class_Depth,@Class_Order,@Class_Intro)    
  78.    
  79. IF @@Error<>0     
  80. Begin    
  81. Set @Err=1    
  82. Goto theEnd    
  83. End    
  84.    
  85. --更新当前记录之后的记录的ORDER    
  86. --Update Class Set Class_Order = Class_Order+1 Where Class_Order   > @Class_Order     
  87.    
  88. theEnd:    
  89. IF @Err=0    
  90. Begin    
  91. Commit Tran    
  92. Return @Class_Id    
  93. End    
  94. Else    
  95. Begin    
  96.      Rollback Tran    
  97. Return 0    
  98. End    
  99. GO    

删除:

  1. Create PROCEDURE sp_Class_Delete    
  2. (    
  3.    @Class_Id int   
  4. )    
  5. AS    
  6. Declare @Err As int   
  7. Set @Err = 0    
  8. Begin Tran    
  9. --首先查询该节点下是否有子节点    
  10. Select Class_Id From Class Where Parent_ID = @Class_Id    
  11. IF @@RowCount<>0    
  12.      Begin    
  13.      Set @Err = 1    
  14.      Goto theEnd    
  15.      End    
  16.    
  17. --获取该节点的Class_Order,为了删除后整理其他记录的顺序    
  18. Declare @Class_Order As int   
  19. Select @Class_Order = Class_Order From Class Where Class_Id = @Class_Id    
  20. IF @Class_Order Is NUll    
  21.      Begin    
  22.        Set @Err =2    
  23.        Goto theEnd    
  24.      End     
  25.    
  26. --更新其他记录的Class_Order    
  27. Update Class Set Class_Order = Class_Order -1 Where Class_Order >@Class_Order     
  28. IF @@Error<>0    
  29.      Begin    
  30.        Set @Err =3    
  31.        Goto theEnd    
  32.      End     
  33.    
  34. --删除操作    
  35. Delete From Class Where Class_Id=@Class_Id    
  36. IF @@Error<>0    
  37.      Begin    
  38.        Set @Err =4    
  39.        Goto theEnd    
  40.    End     
  41.    
  42. --更新其他记录的Class_Id    
  43. --Update Class Set Class_Id= Class_Id - 1 Where Class_Id >@Class_Id     
  44. --IF @@Error<>0    
  45. --   Begin    
  46. --     Set @Err =5    
  47. --     Goto theEnd    
  48. --   End     
  49. --   
  50. theEnd:    
  51. IF @Err = 0     
  52.      Begin    
  53.        Commit Tran    
  54.        Return 0 --删除成功    
  55.      End    
  56. Else    
  57.      Begin    
  58.        IF @Err=1    
  59.    Begin    
  60.        Rollback Tran    
  61.        Return 1 --有子节点    
  62. End    
  63.        Else    
  64. Begin    
  65.        Rollback Tran    
  66.        Return 2--未知错误    
  67. End    
  68.      End    
  69. GO    

更新:

  1. Create PROCEDURE sp_Class_Update    
  2. (    
  3. @Class_Id int,    
  4. @Parent_ID int,    
  5. @Class_Name nvarchar(50),    
  6. @Class_Intro nvarchar(1000)    
  7. )    
  8. AS    
  9. Declare @Err As int   
  10. Set @Err=0    
  11.    
  12. Begin Tran    
  13.    
  14. --获取修改前的:Parent_ID,Class_Depth,Class_Order    
  15. Declare @oParent_ID As int   
  16. Declare @oClass_Depth As int   
  17. Declare @oClass_Order As int   
  18. Declare @oClass_Path As nvarchar(1000)    
  19.    
  20. Select @oParent_ID = Parent_ID, @oClass_Depth = Class_Depth,@oClass_Order = Class_Order, @oClass_Path = Class_Path   From Class Where Class_Id = @Class_Id    
  21. IF @oParent_ID Is Null    
  22.      Begin    
  23.      Set @Err = 1    
  24.      Goto theEnd    
  25.      End    
  26.    
  27. --如果父ID没有改变,则直接修改栏目名和栏目简介    
  28. IF @oParent_ID = @Parent_ID    
  29.      Begin    
  30.      Update Class Set Class_Name = @Class_Name,Class_Intro = @Class_Intro Where Class_Id = @Class_Id    
  31.      IF @@Error <> 0    
  32.      Set @Err = 2    
  33.      Goto theEnd    
  34.      End    
  35.    
  36.    
  37. Declare @nClass_Path As nvarchar(1000)    
  38. Declare @nClass_Depth As int   
  39. Declare @nClass_Order As int   
  40.    
  41. --获取当前节点作为父节点所包含的节点数[包括自身] 注:如果返回 “1” 说明是单节点    
  42. Declare @theCount As int   
  43. Select @theCount = Count(Class_Id) From Class Where Class_Id=@Class_Id or Class_Path like ''+@oClass_Path+'|%'   
  44. IF @theCount Is Null    
  45. Begin    
  46.      Set @Err = 3    
  47.      Goto theEnd    
  48. End     
  49.    
  50. IF @Parent_ID=0 --如果是设置为顶级节点,将节点设置为最后一个顶级节点    
  51. Begin    
  52. --Print '设置为顶级栏目'   
  53. Set @nClass_Path = Ltrim(Str(@Class_Id))    
  54. Set @nClass_Depth =1    
  55.    
  56. Select @nClass_Order = Max(Class_Order) From Class    
  57. IF @nClass_Order Is NULL    
  58.                    Begin    
  59.       Set @Err = 4    
  60.       Goto theEnd    
  61.       End     
  62.    
  63. Set @nClass_Order = @nClass_Order - @theCount + 1    
  64.    
  65. --更新三部分 1 节点本身 2 所有子节点 2 本树更改之前的后面记录的顺序    
  66. --Print '更新本栏目之前位置后面的所有栏目[不包括本栏目下的子栏目]的:Class_Order'   
  67. Update Class Set Class_Order = Class_Order-@theCount Where (Class_Order >@oClass_Order) And (Class_Path Not like ''+@oClass_Path+'|%')    
  68. IF @@Error <> 0    
  69.      Begin    
  70.      Set @Err = 7    
  71.      Goto theEnd    
  72.      End    
  73.    
  74. --Print '更新本栏目的:Parent_ID,Class_Path,Class_Depth,Class_Order,Class_Name,Class_Intro'   
  75. Print 'Order : '+Ltrim(Str(@nClass_Order))    
  76. Update Class Set Parent_ID=@Parent_ID,Class_Path = @nClass_Path,Class_Depth = @nClass_Depth,Class_Order = @nClass_Order, Class_Name = @Class_Name,Class_Intro = @Class_Intro Where Class_Id = @Class_Id    
  77. IF @@Error <> 0    
  78.      Begin    
  79.      Set @Err = 5    
  80.      Goto theEnd    
  81.      End    
  82.    
  83. --Print '更新本栏目下的所有子栏目的:Class_Path,Class_Depth,Class_Order'   
  84.               Update Class Set Class_Path = Replace(Class_Path,@oClass_Path,@nClass_Path),Class_Depth = Class_Depth + (@nClass_Depth-@oClass_Depth),Class_Order = Class_Order+( @nClass_Order-@oClass_Order) Where Class_Path like ''+@oClass_Path+'|%'   
  85. IF @@Error <> 0    
  86.      Begin    
  87.      Set @Err = 6    
  88.      Goto theEnd    
  89.      End    
  90.    
  91.    
  92. End     
  93. Else    
  94. Begin    
  95. --获取未来父节点的相关信息,并设置本节点的相关值    
  96. Select @nClass_Depth = Class_Depth,@nClass_Path = Class_Path From Class Where Class_Id = @Parent_ID    
  97. IF @nClass_Depth Is   NULL or @nClass_Path Is Null    
  98.        Begin    
  99.        Set @Err = 8    
  100.        Goto theEnd    
  101.        End     
  102. Set @nClass_Depth = @nClass_Depth +1    
  103. Select @nClass_Order =Max(Class_Order) From Class Where Class_Id = @Parent_ID or   Class_Path like ''+@nClass_Path+'|%'   
  104. IF @nClass_Order Is   NULL    
  105.        Begin    
  106.        Set @Err = 9    
  107.        Goto theEnd    
  108.        End     
  109.    
  110. Set @nClass_Path = @nClass_Path +'|'+ Ltrim(Str(@Class_Id))    
  111.    
  112. IF @nClass_Order = @oClass_Order+1 --如果新的父节点是原来位置上端最近一个兄弟,则所有节点的顺序都不改变    
  113.                      Begin    
  114. Update Class Set Parent_ID=@Parent_ID,Class_Path = @nClass_Path,Class_Depth = @nClass_Depth, Class_Name = @Class_Name,Class_Intro = @Class_Intro Where Class_Id = @Class_Id    
  115. IF @@Error <> 0    
  116.      Begin    
  117.      Set @Err = 10    
  118.      Goto theEnd    
  119.      End    
  120.         End    
  121.    
  122. Set   @nClass_Order = @nClass_Order + 1     
  123.    
  124. --更新三部分 1 本树更改之前的后面(或前面)记录的顺序 1 节点本身   3 所有子节点    
  125. --分为向上移或象下移    
  126. --Print '更新本栏目之前位置后面的所有栏目[或者本栏目之后位置]   [不包括本栏目下的子栏目]的:Class_Order'   
  127. IF @nClass_Order < @oClass_Order    
  128. Begin    
  129. Update Class Set Class_Order = Class_Order+@theCount Where Class_Order<@oClass_Order   And Class_Order >=@nClass_Order And (Class_Path Not like ''+@oClass_Path+'|%'And Class_Id<>@Class_Id    
  130. IF @@Error <> 0    
  131.          Begin    
  132.          Set @Err = 12    
  133.          Goto theEnd    
  134.          End    
  135. End    
  136. Else    
  137. Begin    
  138. Update Class Set Class_Order = Class_Order-@theCount Where Class_Order >@oClass_Order And Class_Order<@nClass_Order   And (Class_Path Not like ''+@oClass_Path+'|%'And Class_Id<>@Class_Id    
  139. IF @@Error <> 0    
  140.          Begin    
  141.          Set @Err = 13    
  142.          Goto theEnd    
  143.          End    
  144. End    
  145.    
  146. --Print '更新本栏目的:Parent_ID,Class_Path,Class_Depth,Class_Order,Class_Name,Class_Intro'   
  147. Print 'Order : '+Ltrim(Str(@nClass_Order))    
  148. IF @nClass_Order > @oClass_Order    
  149. Set @nClass_Order = @nClass_Order - @theCount    
  150. Update Class Set Parent_ID=@Parent_ID,Class_Path = @nClass_Path,Class_Depth = @nClass_Depth,Class_Order = @nClass_Order, Class_Name = @Class_Name,Class_Intro = @Class_Intro Where Class_Id = @Class_Id    
  151. IF @@Error <> 0    
  152.      Begin    
  153.      Set @Err = 10    
  154.      Goto theEnd    
  155.      End    
  156.    
  157. --Print '更新本栏目下的所有子栏目的:Class_Paht,Class_Depth,Class_Order'   
  158.               Update Class Set Class_Path = Replace(Class_Path,@oClass_Path,@nClass_Path),Class_Depth = Class_Depth + (@nClass_Depth-@oClass_Depth),Class_Order = Class_Order+(@nClass_Order-@oClass_Order) Where Class_Path like ''+@oClass_Path+'|%'   
  159. IF @@Error <> 0    
  160.      Begin    
  161.      Set @Err = 11    
  162.      Goto theEnd    
  163.      End    
  164. End    
  165.    
  166. theEnd:    
  167. IF @Err<>0 --如果有错误则返回错误号    
  168.     Begin    
  169.     Rollback Tran    
  170.     Return @Err    
  171.     End    
  172. Else      --如果没有错误就返回0    
  173.     Begin    
  174.     Commit Tran    
  175.     Return 0    
  176.     End    

查询:

  1. Create PROCEDURE sp_Class_List     
  2. AS    
  3. Select Class_Id, Class_Name, Parent_ID, Class_Path, Class_Depth,     
  4.        Class_Order, Class_Intro    
  5. FROM Class    
  6. orDER BY Class_Order    
  7. GO 

调用:

  1. exec sp_Class_Insert 4,"家具4","jiaju4" --parent_id,,, 
  2. exec sp_Class_List  
  3.  
  4. exec sp_Class_Delete 2 
  5.  
  6. exec sp_Class_Update 4,2, "家具a","jiajua" --class_id  parent_id  name .. 
  7.  
  8. select * from Class  
  9.  
  10. delete class from class where class_name like '%家具%' 

本站热点业务

更多模板/案例展示

关于我们 | 联系我们 | 团队日志 | 网站地图 | 网站合作