zoukankan      html  css  js  c++  java
  • 无限级分类存储过程版

    /*
    无限级分类存储过程版

    (未作详细测试)
    自己写的无限级分类存储过程版,参照网上那个的无限级分类存储过程版的实现原理,主要修改了:1、为表的

    排序字段添加聚集索引,速度更快;2、修改更新节点的存储过程的程序,相对比较难实现;3、其它略作修改
    */


    --数据表名:Category
    --数据字段:
    /*
    [CategoryId] [int] NOT NULL (主键,非聚集)
    [ParentId] [int] NOT NULL
    [Name] [nvarchar](50)
    [Depth] [int] NOT NULL
    [OrderId] [int] NOT NULL(聚集索引)
    [Path] [nvarchar](1000)
    [Intro] [nvarchar](1000)
    */
    ------------------------------------------------------------------

    --1、创建表:
    --对象: Table [dbo].[Category]
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE [dbo].[Category]
    (
        [CategoryId] [int] NOT NULL,
        [ParentId] [int] NOT NULL,
        [Name] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
        [Depth] [int] NOT NULL,    --深度
        [OrderId] [int] NOT NULL,    --排序
        [Path] [nvarchar](1000) COLLATE Chinese_PRC_CI_AS NOT NULL,    --路径
        [Intro] [nvarchar](1000) COLLATE Chinese_PRC_CI_AS NULL,    --简介

    --CONSTRAINT [PK_Category] PRIMARY KEY NONCLUSTERED ([CategoryId] ASC)WITH (IGNORE_DUP_KEY =

    OFF) ON [PRIMARY]
    -- 定义主键并去除默认的 聚焦索引 2k 不可用
    )
    ON [PRIMARY]

    --2、创建聚集索引
    -- 对象: Index [IX_Category_OrderId]
    CREATE CLUSTERED INDEX [IX_Category_OrderId] ON [dbo].[Category]
    (
        [OrderId] ASC
    )
    -- 2k 不可用
    --WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON

    [PRIMARY]

    --3、创建添加、修改、删除、查询 四个存储过程
    --添加:
    --对象: StoredProcedure [dbo].[Category_Insert]
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO


    -- exec Category_Insert 0,"a","desc"
    -- exec Category_Insert 0,"b","desc"
    -- exec Category_Insert 0,"c","desc"


        -- exec Category_Insert 1,"a_1","desc"
        -- exec Category_Insert 1,"a_2","desc"
        -- exec Category_Insert 1,"a_3","desc"


        -- exec Category_Insert 2,"b_1","desc"
        -- exec Category_Insert 2,"b_2","desc"
        -- exec Category_Insert 2,"b_3","desc"


        -- exec Category_Insert 3,"c_1","desc"
        -- exec Category_Insert 3,"c_2","desc"
        -- exec Category_Insert 3,"c_3","desc"


        -- exec Category_Insert 5,"a_2_1","desc"
        -- exec Category_Insert 5,"a_2_2","desc"
        -- exec Category_Insert 5,"a_2_3","desc"

    CREATE PROCEDURE [dbo].[Category_Insert]
        @ParentId int,
        @Name nvarchar(50),
        @Intro nvarchar(1000)
    AS
    BEGIN
        SET NOCOUNT ON;
        DECLARE @ERR int
        SET @ERR=0
        BEGIN TRAN
        IF @ParentId<0 OR ISNULL(@Name,'')=''
            BEGIN
                SET @ERR=1
                GOTO theEnd
            END
        DECLARE @CategoryId int,@Depth int,@OrderId int,@Path nvarchar(1000)

        --计算@CategoryId
        SELECT @CategoryId=ISNULL(MAX(CategoryId)+1,1) FROM Category

        IF @ParentId=0
            BEGIN
                --计算@Depth
                SET @Depth=1
                --计算@OrderId
                SELECT @OrderId=ISNULL(MAX(OrderId)+1,1) FROM Category
                --计算@Path
                SET @Path=LTRIM(@CategoryId)
            END
        ELSE
            BEGIN
                --计算@Depth,以及@Path的前半部分,即父节点的Path,计算@OrderId时需要用到
                SELECT @Depth=Depth+1,@Path=Path FROM Category WHERE CategoryId=@ParentId
                --计算@OrderId
                SELECT @OrderId=MAX(OrderId)+1 FROM Category
                    WHERE CategoryId=@ParentId OR Path LIKE @Path+'|%'
                --向后移动插入位置后面的所有节点
                UPDATE Category SET OrderId=OrderId+1 WHERE OrderId>=@OrderId
                --计算@Path
                SET @Path=@Path+'|'+LTRIM(@CategoryId)
            END

        INSERT INTO Category(CategoryId,ParentId,Name,Depth,OrderId,Path,Intro) VALUES

    (@CategoryId,@ParentId,@Name,@Depth,@OrderId,@Path,@Intro)

        IF @@ERROR<>0
            SET @ERR=-1
        theEnd:
        IF @ERR=0
            BEGIN
            COMMIT TRAN
            RETURN 0
            END
        ELSE
            BEGIN
            ROLLBACK TRAN
            RETURN @ERR
            END
           
    END


    --修改:
    --对象: StoredProcedure [dbo].[Category_Update]    脚本日期: 12/11/2007 作者:Figo Chen
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO


    --    exec Category_Update 4,12,'c_3--',''

    CREATE PROCEDURE [dbo].[Category_Update]
        @CategoryId int,
        @ParentId int,
        @Name nvarchar(50),
        @Intro nvarchar(1000)
    AS
    BEGIN
        SET NOCOUNT ON;
        DECLARE @ERR int
        SET @ERR=0
        BEGIN TRAN
        --如果参数不正确,取消操作
        IF(@CategoryId<=0 OR @ParentId<0 OR @CategoryId=@ParentId OR ISNULL(@Name,'')='')
            BEGIN
            SET @ERR=1
            GOTO theEnd
            END       
        --如果不存在此节点,则取消操作
        IF(NOT EXISTS(SELECT CategoryId FROM Category WHERE CategoryId=@CategoryId))
            BEGIN
            SET @ERR=2
            GOTO theEnd
            END   
        --如果不存在父节点,则取消操作
        IF(NOT EXISTS(SELECT CategoryId FROM Category WHERE CategoryId=@ParentId) AND @ParentId<>0)
            BEGIN
            SET @ERR=3
            GOTO theEnd
            END

        --先获取原来的值
        DECLARE @oldParentId int,@oldDepth int,@oldOrderId int,@oldPath nvarchar(1000)
        SELECT @oldParentId=ParentId,@oldDepth=Depth,@oldOrderId=OrderId,@oldPath=Path
            FROM Category WHERE CategoryId=@CategoryId
        --如果新的父节点是当前节点的子(孙)节点,则取消操作
        IF(EXISTS(SELECT CategoryId FROM Category WHERE CategoryId=@ParentId AND Path LIKE

    @oldPath+'|%'))
            BEGIN
            SET @ERR=4
            GOTO theEnd
            END
        --根据是否需要修改父节点,分两种情况更新
        IF @ParentId=@oldParentId
            BEGIN
                UPDATE Category SET Name=@Name,Intro=@Intro WHERE CategoryId=@CategoryId
            END
        ELSE
            BEGIN
                --获取要移动的节点个数[当前节点加上当前节点的子(孙)节点]
                DECLARE @MoveCount int
                SELECT @MoveCount=COUNT(CategoryId) FROM Category WHERE Path LIKE @oldPath+'%'
                --获取新父节点的信息,根据新父节点的信息获得当前节点的新值
                DECLARE @Parent_Depth int,@Parent_oldOrderId int,@Parent_newOrderId int,@Parent_Path

    nvarchar(1000)
                DECLARE @newDepth int,@newOrderId int,@newPath nvarchar(1000)
                ----根据父节点是否根节点,分两种情况
                IF @ParentId=0
                    BEGIN
                    SET @Parent_Depth=0
                    SET @Parent_Path=''
                    SELECT @Parent_oldOrderId=MAX(OrderId)+1 FROM Category WHERE ParentId=@ParentId
                    SET @newDepth=1
                    SET @newPath=LTRIM(@CategoryId)
                    END
                ELSE
                    BEGIN
                    SELECT @Parent_Depth=Depth,@Parent_Path=Path,@Parent_oldOrderId=OrderId FROM

    Category WHERE CategoryId=@ParentId
                    SET @newDepth=@Parent_Depth+1
                    SET @newPath=@Parent_Path+'|'+LTRIM(@CategoryId)
                    END
                SET @newOrderId=@oldOrderId --初始化,因为有可能OrderId最终没有变化
                --移动相关节点,并获取当前节点的新序号值
                DECLARE @temp_newOrderId int,@StartOrderId int,@EndOrderId int,@Offset int
                --获得移动前当前节点目标位置原来的序号
                SELECT @temp_newOrderId=MAX(OrderId)+1 FROM Category
                    WHERE Path LIKE @Parent_Path+'%' AND Path NOT LIKE @oldPath+'%'
                IF @temp_newOrderId<@oldOrderId --向前移动
                    BEGIN
                        SELECT @StartOrderId=MAX(OrderId)+1 FROM Category WHERE Path LIKE

    @Parent_Path+'%'
                        SET @EndOrderId=@oldOrderId-1
                        SET @Offset=@MoveCount
                        SET @newOrderId=@StartOrderId --获取当前节点新序号值方法之一(1)
                    END
                ELSE IF @temp_newOrderId>@oldOrderId --向后移动
                    BEGIN
                        SET @StartOrderId=@oldOrderId+@MoveCount
                        SELECT @EndOrderId=MAX(OrderId) FROM Category WHERE Path LIKE

    @Parent_Path+'%'
                        SET @Offset=-@MoveCount
                        SET @newOrderId=@EndOrderId-@MoveCount+1 --获取当前节点新序号值方法之一(2)
                    END
                IF @newOrderId<>@oldOrderId
                    UPDATE Category SET OrderId=OrderId+@Offset
                        WHERE OrderId BETWEEN @StartOrderId AND @EndOrderId AND Path NOT LIKE

    @oldPath+'%'
                --获取当前节点新序号值方法之二(方法一效率高,方法二可读性强)
                --SELECT @newOrderId=MAX(OrderId)+1 FROM Category WHERE Path LIKE @Parent_Path+'%'

    AND @EndOrderId AND Path NOT LIKE @oldPath+'%'
                --更新当前节点
                UPDATE Category SET

    ParentId=@ParentId,Name=@Name,Depth=@newDepth,OrderId=@newOrderId,Path=@newPath,Intro=@Intro
                    WHERE CategoryId=@CategoryId
                --更新子节点
                UPDATE Category SET Depth=Depth-@oldDepth+@newDepth,OrderId=OrderId-

    @oldOrderId+@newOrderId,Path=REPLACE(Path,@oldPath,@newPath)
                    WHERE Path LIKE @oldPath+'|%'
            END

        IF @@ERROR<>0
            SET @ERR=-1
        theEnd:
        IF @ERR=0
            BEGIN
            COMMIT TRAN
            RETURN 0
            END
        ELSE
            BEGIN
            ROLLBACK TRAN
            RETURN @ERR
            END
    END


    --删除:
    --对象: StoredProcedure [dbo].[Category_Delete]
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO


    CREATE PROCEDURE [dbo].[Category_Delete]
        @CategoryId int
    AS
    BEGIN
        SET NOCOUNT ON;
        DECLARE @ERR int
        SET @ERR=0

        BEGIN TRAN
        --如果参数不正确,则取消操作
        IF(@CategoryId<=0)
            BEGIN
            SET @ERR=1
            GOTO theEnd
            END   
        --如果不存在此节点,则取消操作
        IF(NOT EXISTS(SELECT CategoryId FROM Category WHERE CategoryId=@CategoryId))
            BEGIN
            SET @ERR=2
            GOTO theEnd
            END   
        --如果存在子节点,则不删除
        IF(EXISTS(SELECT CategoryId FROM Category WHERE ParentId=@CategoryId))
            BEGIN
            SET @ERR=3
            GOTO theEnd
            END
        DECLARE @OrderId int
        --先提取节点的序号值,供以后使用
        SELECT @OrderId=OrderId FROM Category WHERE CategoryId=@CategoryId
        --删除节点
        DELETE FROM Category WHERE CategoryId=@CategoryId
        --向前移动后面的所有节点的位置
        UPDATE Category SET OrderId=OrderId-1 FROM Category WHERE OrderId>@OrderId
        IF @@ERROR<>0
            SET @ERR=-1
        theEnd:
        IF @ERR=0
            BEGIN
            COMMIT TRAN
            RETURN 0
            END
        ELSE
            BEGIN
            ROLLBACK TRAN
            RETURN @ERR
            END
    END


    --选择:
    --对象: StoredProcedure [dbo].[Category_Select]
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE PROCEDURE [dbo].[Category_Select]
    AS
    BEGIN
        SET NOCOUNT ON;
        SELECT CategoryId,ParentId,Name,Depth,Intro FROM Category ORDER BY OrderId ASC
    END

     

  • 相关阅读:
    RocketMQ学习笔记(14)----RocketMQ的去重策略
    RocketMQ学习笔记(13)----RocketMQ的Consumer消息重试
    RocketMQ学习笔记(12)----RocketMQ的Consumer API简介
    RocketMQ学习笔记(11)----RocketMQ的PushConsumer和PullConsumer
    RocketMQ学习笔记(10)----RocketMQ的Producer 事务消息使用
    RocketMQ学习笔记(9)----RocketMQ的Producer 顺序消息
    RocketMQ学习笔记(8)----RocketMQ的Producer API简介
    RocketMQ学习笔记(7)----RocketMQ的整体架构
    RocketMQ学习笔记(6)----RocketMQ的Client的使用 Producer/Consumer
    RocketMQ学习笔记(5)----RocketMQ监控平台rocketmq-console-ng的搭建
  • 原文地址:https://www.cnblogs.com/0000/p/1600951.html
Copyright © 2011-2022 走看看