• 移动节点处理的通用存储过程.sql


    CREATE PROC p_Move_CopyCode
    @TableName  sysname,        --调整编码规则的表名
    @FieldName  sysname,        --编码字段名
    @CodeRule   varchar(50),    --以逗号分隔的编码规则,每层编码的长度,比如1,2,3,表示有三层编码,第一层长度为1,第二层长度为2,第三层长度为3
    @Code      varchar(50),     --要复制或者移动的节点编码
    @ParentCode varchar(50),    --移动到该编码的节点下
    @IsCopy    bit=0            --0为移动处理,否则为复制处理
    AS
    --参数检查
    IF ISNULL(OBJECTPROPERTY(OBJECT_ID(@TableName),N'IsUserTable'),0)=0
    BEGIN
        RAISERROR(N'"%s"不存在,或者不是用户表',1,16,@TableName)
        RETURN
    END
    IF NOT EXISTS(SELECT * FROM SYSCOLUMNS WHERE ID=OBJECT_ID(@TableName) AND name=@FieldName)
    BEGIN
        RAISERROR(N'列名"%s"在用户表"%s"中无效',1,16,@FieldName,@TableName)
        RETURN    
    END
    IF ISNULL(@CodeRule,'')=''
    BEGIN
        RAISERROR(N'必须编码规则字符串',1,16)
        RETURN    
    END
    IF PATINDEX(N'%[^0-9^,]%',@CodeRule)>0
    BEGIN
        RAISERROR(N'编码规则字符串"%s"中只能包含数字和逗号(,)',1,16,@CodeRule)
        RETURN    
    END
    IF ISNULL(@Code,'')='' RETURN
            

    --生成编码规则修改字符串
    DECLARE @CodeLen int,@CodeLens varchar(10),@Pos varchar(10),
        @Old_CodeRule varchar(50),@New_CodeRule varchar(50),
        @s nvarchar(4000),
        @Code1 varchar(100),@Code2 varchar(100)

    IF ISNULL(@ParentCode,'')=''
        SELECT @ParentCode=N'',
            @New_CodeRule=@CodeRule
    SET @CodeLens=0
    WHILE CHARINDEX(N',',@CodeRule)>0
    BEGIN
        SET @CodeLen=LEFT(@CodeRule,CHARINDEX(N',',@CodeRule)-1)
        IF @CodeLens+@CodeLen=LEN(@Code)
        BEGIN
            SELECT @Old_CodeRule=@CodeRule,
                @Pos=@CodeLens
            IF @New_CodeRule>'' GOTO lb_CalcCodeLens
        END
        SELECT @CodeRule=STUFF(@CodeRule,1,CHARINDEX(N',',@CodeRule),N''),
            @CodeLens=@CodeLens+@CodeLen
        IF @CodeLens=LEN(@ParentCode)
        BEGIN
            SET @New_CodeRule=@CodeRule
            IF @Old_CodeRule>'' GOTO lb_CalcCodeLens
        END
    END
    IF @Old_CodeRule IS NULL AND CAST(@CodeLens as int)+@CodeRule=LEN(@Code)
        SELECT @Old_CodeRule=@CodeRule,
                @Pos=@CodeLens
    IF @New_CodeRule IS NULL AND CAST(@CodeLens as int)+@CodeRule=LEN(@ParentCode)
    BEGIN
        RAISERROR(N'移动编码"%s"到编码"%s"下导致编码长度溢出编码规则允许的长度',1,16,@Code,@ParentCode)
        RETURN
    END

    lb_CalcCodeLens:
    SET @s=N'SET @CodeLens=@CodeLens+'+REPLACE(@CodeRule,N',',N'+')
    EXEC sp_executesql @s,N'@CodeLens int OUTPUT',@CodeLens OUTPUT

    IF @Old_CodeRule IS NULL
    BEGIN
        RAISERROR(N'编码"%s"不符合指定的编码规则',1,16,@Code)
        RETURN
    END
    IF @New_CodeRule IS NULL
    BEGIN
        RAISERROR(N'编码"%s"不符合指定的编码规则',1,16,@ParentCode)
        RETURN
    END

    DECLARE @Parent_Chk nvarchar(4000),@Delete_old nvarchar(4000),@where nvarchar(4000)
    SELECT @TableName=QUOTENAME(@TableName),
        @FieldName=QUOTENAME(@FieldName),
        @s=CASE
            WHEN @Old_CodeRule=@New_CodeRule THEN N'New_no'
            ELSE dbo.f_ChangeCodeRule(@Old_CodeRule,@New_CodeRule,'',0,N'New_No')
        END,
        @Code1=QUOTENAME(@Code+N'%',N''''),
        @Code2=QUOTENAME(@Code,N''''),
        @ParentCode=QUOTENAME(@ParentCode,N''''),
        @Parent_Chk=CASE
            WHEN @ParentCode=N'''''' THEN N''
            ELSE 'IF NOT EXISTS(SELECT * FROM '+@TableName
                +N' WHERE '+@FieldName+N'='+@ParentCode+N')
        BEGIN
            RAISERROR(N''编码"%s"不存在'',1,16,'+@ParentCode+N')
            ROLLBACK TRAN
            RETURN
        END' END,
        @Delete_old=CASE
            WHEN @IsCopy=0
            THEN N'DELETE a FROM '+@TableName
                +N' a,# b WHERE a.'+@FieldName+N'=b.Old_No'
            ELSE N'' END,
        @where=CASE
            WHEN @IsCopy=0 THEN N'AND Old_No<>a.Old_No'
            ELSE N'' END
        
    --检查并完成删除处理
    EXEC(N'BEGIN TRAN
    '+@Parent_Chk+N'
    --将处理后的编码与处理前的编码保存到临时表
    SELECT Old_No,New_No='+@ParentCode+N'+'+@s+N'
    INTO # FROM(
        SELECT Old_No='+@FieldName+N',
            New_No=STUFF('+@FieldName+N',1,'+@Pos+N','''')
        FROM '+@TableName+N' WITH(XLOCK,TABLOCK)
        WHERE '+@FieldName+N' LIKE '+@Code1+N')a

    --编码重复检测
    SELECT Err=N''超过编码规则能处理的长度'',* INTO #1 FROM # WHERE LEN(New_No)>'+@CodeLens+N'
    UNION ALL
    SELECT Err=N''转换后编码重复'',* FROM # a
    WHERE EXISTS(
        SELECT * FROM # WHERE New_No=a.New_No AND Old_No<>a.Old_No)
    UNION ALL
    SELECT Err=N''转换后与表中现有的编码重复'',* FROM # a
    WHERE EXISTS(
        SELECT * FROM '+@TableName+N'
        WHERE '+@FieldName+N'=a.New_No '+@where+N')
    IF @@ROWCOUNT>0
        SELECT * FROM #1 ORDER BY Err,New_No
    ELSE
    BEGIN
        --移动编码
        SELECT a.* INTO #2
        FROM '+@TableName+N' a,# b
        WHERE a.'+@FieldName+N'=b.Old_No
        UPDATE a SET '+@FieldName+N'=b.New_No
        FROM #2 a,# b
        WHERE a.'+@FieldName+N'=b.Old_No
    '+@Delete_old+N' --如果是移动,先进行删除处理
        INSERT '+@TableName+N' SELECT * FROM #2
    END
    COMMIT TRAN')
  • 相关阅读:
    BSGS模板(互质与不互质) 洛谷P4195、P3846
    整除分块(数论分块)
    洛谷P3327 [SDOI2015]约数个数和——莫比乌斯反演
    模块二
    模块
    二分法 匿名函数
    3.26作业
    函数的递归调用
    yield表达式 三元表达式
    3.25作业
  • 原文地址:https://www.cnblogs.com/shihao/p/2526974.html
Copyright © 2020-2023  润新知