在 SQL Server 中生成字母数字序列

如何解决在 SQL Server 中生成字母数字序列

我正在使用 sql Server 存储过程来生成具有以下模式的 10 位数字序列,其中 [CustomerCode] 表示“ABC”:

[CustomerCode]0000001
...
[CustomerCode]9999999
[CustomerCode]A000001
...
[CustomerCode]Z999999
[CustomerCode]ZA00001
...
[CustomerCode]ZZ99999
[CustomerCode]ZZA0001
...
[CustomerCode]ZZZZZZZ

所以这个存储过程将接受一个字符串作为输入参数,并返回下一个值,例如它需要'ABCZ999999'并返回'ABCZA00001'。

我有以下存储过程和函数,但它们不能完全工作,而且我似乎无法正确处理。

感谢任何帮助。

-- Function to increment numeric value
CREATE FUNCTION [dbo].[IncrementNumericValue] 
    (@CurrentValue Varchar(2))  
RETURNS Varchar(2)
AS  
BEGIN 
    DECLARE @RetValue Varchar(2)

    IF (@CurrentValue < CAST(9 AS Varchar(2)))
    BEGIN
        SET @RetValue = CAST((CAST(@CurrentValue AS Int) + Cast(1 AS Int)) AS Varchar(2))
    END
    ELSE IF (@CurrentValue >= CAST(9 AS Varchar(2)))
    BEGIN
        SET @RetValue = CAST(0 AS Varchar(2))
    END
    ELSE
    BEGIN
        SET @RetValue = CAST('-' AS Varchar(2))
    END
    
    RETURN (@RetValue)
END

-- Function to increment alpha value
CREATE FUNCTION [dbo].[IncrementAlphaValue] 
    (@CurrentValue Varchar(2))  
RETURNS Varchar(2)
AS  
BEGIN 
    DECLARE @RetValue Varchar(2)

    IF (@CurrentValue < CAST(9 AS Varchar(2)))
    BEGIN
        SET @RetValue = CAST((CAST(@CurrentValue AS Int) + CAST(1 AS Int)) AS Varchar(2))
    END
    ELSE IF (@CurrentValue = CAST(9 AS Varchar(2)))
    BEGIN
        SET @RetValue = CAST('A' As Varchar(2))
    END
    ELSE IF ((@CurrentValue >= CAST('A' AS Varchar(2))) 
             AND (@CurrentValue < CAST('Z' AS Varchar(2))))
    BEGIN
        SET @RetValue = CAST((Char((CAST(ASCII(@CurrentValue) AS Int) + CAST(1 AS Int)))) AS Varchar(2))
    END
    ELSE IF (@CurrentValue = CAST('Z' AS Varchar(2)))
    BEGIN
        SET @RetValue = CAST(0 AS Varchar(2))
    END
    ELSE
    BEGIN
        SET @RetValue = CAST('-' AS Varchar(2))
    END
    
    RETURN (@RetValue)
END

-- Function to calculate the next sequence of the pattern
CREATE PROCEDURE [dbo].[GetNextSequence]
    @NewTarget Varchar(10) OUTPUT
AS
BEGIN
    DECLARE @Lastvariable Varchar(10) 
    DECLARE @PositionIndex Int
    DECLARE @PassparameterWidth Int
    DECLARE @TargetWidth Int
    DECLARE @SelectedValue Varchar(2)
    DECLARE @NewValue Varchar(2)
    DECLARE @FinalValue Varchar(10)
    DECLARE @ReplaceStringLength Int
    DECLARE @ReplaceString Varchar(10)
    DECLARE @NewCODE Varchar(10)
    DECLARE @MaxTargetWidth Int
    DECLARE @customerCode char(3)
    DECLARE @NumberOfNine Int
    DECLARE @AlphaNumericPartWidth Int

    BEGIN
        BEGIN
            -- Input
            SET @customerCode = 'ABC'
            SELECT  @Lastvariable = 'ABCZ999999'

            SET @PassparameterWidth = Len(@Lastvariable)
            SET @AlphaNumericPartWidth = @PassparameterWidth - Len(@customerCode)
            SET @Lastvariable = SUBSTRING(@Lastvariable,4,7)
                                        
            SET @TargetWidth = Cast(4 AS Int)
            SET @MaxTargetWidth = Cast(7 AS Int)
            SET @NewValue = ''
            SET @FinalValue = ''
            SET @ReplaceStringLength = Cast(0 AS Int)
            SET @ReplaceString = ''
            SET @NumberOfNine = 0
         
            IF (@AlphaNumericPartWidth = CAST(7 AS Int))
            BEGIN
                SET @PositionIndex = @AlphaNumericPartWidth
            
                WHILE(@PositionIndex > 0)
                BEGIN
                    SET @SelectedValue = SUBSTRING(@Lastvariable,@PositionIndex,1)
                    IF (@SelectedValue LIKE '[A-Z]') -- Increment alpha
                        SET @NewValue = dbo.IncrementAlphaValue(@SelectedValue)
                    ELSE -- Increment numeric
                        SET @NewValue = dbo.IncrementNumericValue(@SelectedValue)
                    -- Right most digit
                    IF (@PositionIndex = 1)
                    BEGIN
                        IF (@SelectedValue = 'Z')
                        BEGIN
                            -- If left of 'Z' all '9' replace with 'ZA'
                            IF (LEN(REPLACE(PARSENAME(REPLACE(@Lastvariable,'Z','.'),1),'9','')) = 0)
                            BEGIN
                                SET @Lastvariable = REPLACE(@Lastvariable,'ZA');
                                SET @Lastvariable = REPLACE(@Lastvariable,'0');
                                RETURN
                            END
                        END
                        -- If prefixed with letter or All '9',increment alpha
                        IF (@NewValue LIKE '[A-Y]' OR LEN(REPLACE(@Lastvariable,'')) = 0)
                        BEGIN                           
                            SET @NewValue = dbo.IncrementAlphaValue(@SelectedValue)
                        END
                    END

                    SET @FinalValue = @NewValue + @FinalValue           

                    -- Break is it's 1
                    IF (@NewValue <> 9)
                        BREAK

                    -- Move position to left
                    SET @PositionIndex = @PositionIndex - Cast(1 As Int)
                END

                -- Check Final value length
                IF (LEN(@FinalValue) <= @MaxTargetWidth)
                BEGIN   
                    SET @Lastvariable = @customerCode + @Lastvariable
                    -- Get replace string length
                    SET @ReplaceStringLength = @PassparameterWidth -  Len(@FinalValue)
                    -- Get replace string
                    SET @ReplaceString = LEFT(@Lastvariable,@ReplaceStringLength)

                    -- NEW CODE
                    SET @NewCODE = @ReplaceString + @FinalValue
            
                    SET @NewTarget = @NewCODE
                END
                ELSE
                BEGIN
                    SET @NewTarget =  'ERROR1'
                END
            END
            ELSE
            BEGIN
                SET @NewTarget =  'ERROR222'
            END
        END
    END
END

解决方法

这样的事情应该可以解决问题:

--declare @test varchar(10) = 'ABCZZ99999';
--declare @test varchar(10) = 'ABC0000001';
declare @test varchar(10) = 'ABCZZZZZZG';
--declare @test varchar(10) = 'ABC9999999';
--declare @test varchar(10) = 'ABCA000001';
--declare @test varchar(10) = 'ABCE999999';
--declare @test varchar(10) = 'ABCZ999999';
--declare @test varchar(10) = 'ABCZG99999';
--declare @test varchar(10) = 'ABCZA00001';
--declare @test varchar(10) = 'ABCZZ99999';

declare @idpart varchar(7) = SUBSTRING(@test,4,7);
declare @custpart varchar(7) = SUBSTRING(@test,1,3);

declare @numpos int = (SELECT PATINDEX('%[0-9]%',@idpart));

declare @numpart varchar(7);
declare @letterpart varchar(7);

if @numpos > 0
    BEGIN
        SET @numpart = SUBSTRING(@idpart,@numpos,8 - @numpos);
        SET @letterpart = SUBSTRING(@idpart,@numpos - 1);
    END
ELSE
    BEGIN
        SET @numpart = '';
        SET @letterpart = @idpart;
    END

declare @newnumpart varchar(7);
declare @newletterpart varchar(7);

IF @numpart = ''
    BEGIN
        SET @newletterpart = (SELECT REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE
                                    (REPLACE(@letterpart,'Y','Z'),'X','Y'),'W','X'),'V','W'),'U','V'),'T','U'),'S','T'),'R','S'),'Q','R'),'P','Q'),'O','P'),'N','O'),'M','N'),'L','M'),'K','L'),'J','K'),'I','J'),'H','I'),'G','H'),'F','G'),'E','F'),'D','E'),'C','D'),'B','C'),'A','B'));
        SET @newnumpart = '';
    END
ELSE
    BEGIN
        declare @non9 int = (SELECT PATINDEX('%[0-8]%',@numpart));

        IF @non9 > 0
            BEGIN
                --Number part is not all 9s so we can cast as int add 1 and cast back to varchar
                declare @numint int = (SELECT CAST(@numpart as int) + 1);
                declare @numstr varchar(7) = (SELECT CAST(@numint as varchar(7)));
                SET @newnumpart = (SELECT REPLICATE('0',LEN(@numpart) - LEN(@numstr)) + @numstr);
                SET @newletterpart = @letterpart;
            END
        ELSE
            IF @letterpart = ''
                BEGIN
                    SET @newnumpart = '000001';
                    SET @newletterpart = 'A';
                END
            ELSE
                BEGIN
                    declare @nonZ int = (SELECT PATINDEX('%[A-Y]%',@letterpart));
                    IF @nonZ > 0
                        BEGIN
                            SET @newletterpart = (SELECT REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE
                                                        (REPLACE(@letterpart,'B'));
                            SET @newnumpart = (SELECT REPLICATE('0',LEN(@numpart) - 1) + '1'); 
                        END
                    ELSE
                        BEGIN
                            SET @newletterpart = @letterpart + 'A';
                            SET @newnumpart = (SELECT REPLICATE('0',LEN(@numpart) - 2) + '1'); 
                        END
                END
    END

    SELECT @custpart + @newletterpart + @newnumpart;

显然,我只是将其作为直接查询完成,但是从中生成存储过程是微不足道的。两个关键的测试用例是数字元素是否全部为 9,字母元素是否全部为 Z。如果数字元素不是全部 9,那么我们通过强制转换为 int 加 1 并使用 REPLICATE 填充零返回到 varchar 来获得下一个数字部分。如果数字元素全为零,那么第二个关键案例就出现了。我们是否有一个可以递增的字母,或者我们是否在末尾添加了一个额外的“A”,因为我们只有 Zs。我通过多个“REPLACE”增加字母 A-Y 的方式至少在优雅方面可能会有所改进,但它很快!

不过有一件事让我感到困惑。如果这是一个遗留问题,以前的开发人员是如何产生下一个价值的。大概他们是这样做的吧?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?