zoukankan      html  css  js  c++  java
  • SQL Server获取下一个编码字符实现

        周末看到SQL Server 大V潇湘隐者获取下一个编码字符串问题,本来作为以上博文的回复,也许回复内容长度超过其允许限制,无法提交。鉴于此,特记录SQL Server实现过程,方便自己回顾和查阅。


        我简单总结编码字符的规则如下:
    1、5位长度,只能包含0-9数字字符和A-Z(大写)字母字符,且第一位从A开始,最小编码字符为A0000,最大编码字符为ZZZZZ。
    2、编码字符是递进增加的,例如:首个编码是A0000,下一个是A0001,直到A9999,其下一个是B0000,直到B9999,其下一个是C0000,……,如果编码是ZB999,下一个是ZC000,……,直到ZZZZZ。
    具体的规则请参看获取下一个编码字符串问题
     
        从规则入手分析规则2,编码字符是递进增加,间隔为1,也就是一个连续的整数序列,开始整数值和结束整数值固定的。如果编码字符和整数数值之间实现某种相互转换,那么这个问题也就解决啦。
     
        从规则1来看,需要定义硬编码实现0-9数字字符和A-Z(大写)字母字符与相应10进制整数值的对应;还需要实现将一个编码字符转化为整数数值;当然也需要实现将一个整数数值转化为一个编码字符;目前仅是满足5位长度,如果以后扩充到6位,更多位数的需求产生了呢,这个需要设置编码字符的统一固定长度。以上四个方面我分别定义其对应的函数来实现:硬编码字符映射表值函数、转换编码字符为整数数值的标量函数、转换整数数值为编码字符的标量函数和设置编码字符固定长度的标量函数。
     
     
     硬编码字符映射表值函数
     
    该函数的T-SQL代码如下:
     1 IF OBJECT_ID(N'dbo.ufn_GetCodeChars', 'TF') IS NOT NULL
     2 BEGIN
     3     DROP FUNCTION dbo.ufn_GetCodeChars;
     4 END
     5 GO
     6  
     7 --==================================
     8 -- 功能: 获取编码字符表函数
     9 -- 说明: 编码字符只包含0-9和A-Z这两类字符
    10 --       将以上字符映射到对应十进制数值。
    11 -- 作者: XXX
    12 -- 创建: yyyy-MM-dd
    13 -- 修改: yyyy-MM-dd XXX 修改内容描述
    14 -- 调用: SELECT CodeChar, CodeValue FROM dbo.ufn_GetCodeChars();
    15 --==================================
    16 CREATE FUNCTION dbo.ufn_GetCodeChars
    17 (
    18 ) RETURNS @tblCodeChars TABLE (
    19     CodeChar CHAR(1) NOT NULL,
    20     CodeValue TINYINT NOT NULL
    21 )
    22     --$Encode$--
    23 AS
    24 BEGIN
    25     DECLARE
    26         @intStartIndexID AS TINYINT,
    27         @intEndIndexID AS TINYINT;
    28  
    29     SELECT
    30         @intStartIndexID = 0,
    31         @intEndIndexID = 0;
    32  
    33     -- 初始化0-9数字字符
    34     SELECT
    35         @intStartIndexID = ASCII('0'),
    36         @intEndIndexID = ASCII('9');
    37     WHILE @intStartIndexID <= @intEndIndexID
    38     BEGIN
    39         INSERT INTO @tblCodeChars (CodeChar, CodeValue)
    40         VALUES (CHAR(@intStartIndexID), 0);
    41  
    42         SET @intStartIndexID = @intStartIndexID + 1;         
    43     END
    44  
    45     -- 初始化A-Z字母字符
    46     SELECT
    47         @intStartIndexID = ASCII('A'),
    48         @intEndIndexID = ASCII('Z');
    49     WHILE @intStartIndexID <= @intEndIndexID
    50     BEGIN
    51         INSERT INTO @tblCodeChars (CodeChar, CodeValue)
    52         VALUES (CHAR(@intStartIndexID), 0);
    53  
    54         SET @intStartIndexID = @intStartIndexID + 1;         
    55     END
    56  
    57     -- 修改每个编码字符对应的编码值
    58     ;WITH tCodeData AS (
    59         SELECT CodeChar, ROW_NUMBER() OVER (ORDER BY CodeChar ASC) AS RowNum
    60         FROM @tblCodeChars
    61     )
    62  
    63     UPDATE T2
    64     SET T2.CodeValue = T.RowNum - 1
    65     FROM tCodeData AS T
    66         INNER JOIN @tblCodeChars AS T2
    67             ON T.CodeChar = T2.CodeChar;
    68  
    69     RETURN;
    70 END
    71 GO

     

    设置编码字符固定长度的标量函数
     
    该函数的T-SQL代码如下:
     
     1 IF OBJECT_ID(N'dbo.ufn_GetCodeCharFixLength', 'FN') IS NOT NULL
     2 BEGIN
     3     DROP FUNCTION dbo.ufn_GetCodeCharFixLength;
     4 END
     5 GO
     6  
     7 --==================================
     8 -- 功能: 获取编码字符组合的固定长度
     9 -- 说明: 如果转化为int数据类,只能是8位整数,且字符串编码的固定长度只能是8,仅支持5到8位编码字符的组合
    10 -- 作者: XXX
    11 -- 创建: yyyy-MM-dd
    12 -- 修改: yyyy-MM-dd XXX 修改内容描述
    13 -- 调用: SELECT dbo.ufn_GetCodeCharFixLength();
    14 --==================================
    15 CREATE FUNCTION ufn_GetCodeCharFixLength
    16 (
    17 ) RETURNS TINYINT
    18     --$Encode$--
    19 AS
    20 BEGIN
    21     RETURN CAST(5 AS TINYINT);
    22 END
    23 GO

    转换编码字符为整数数值的标量函数

     
    该函数的T-SQL代码如下:
     1 IF OBJECT_ID(N'dbo.ufn_GetCodeIntegerValue', 'FN') IS NOT NULL
     2 BEGIN
     3     DROP FUNCTION dbo.ufn_GetCodeIntegerValue;
     4 END
     5 GO
     6  
     7 --==================================
     8 -- 功能: 通过编码字符获取其对应的整数数值
     9 -- 说明: 具体实现阐述
    10 -- 作者: XXX
    11 -- 创建: yyyy-MM-dd
    12 -- 修改: yyyy-MM-dd XXX 修改内容描述
    13 -- 调用: SELECT dbo.ufn_GetCodeIntegerValue('A0000')
    14 --==================================
    15 CREATE FUNCTION dbo.ufn_GetCodeIntegerValue
    16 (
    17     @chCodeChar CHAR(5)
    18  
    19 ) RETURNS INT
    20     --$Encode$--
    21 AS
    22 BEGIN
    23     SET @chCodeChar = ISNULL(@chCodeChar, '');    
    24     SET @chCodeChar = UPPER(@chCodeChar);
    25     DECLARE @intCodeIntegerValue AS INT;
    26     SET @intCodeIntegerValue = 0;
    27  
    28     DECLARE @tintFixLength AS TINYINT;
    29     SET @tintFixLength =dbo.ufn_GetCodeCharFixLength();
    30  
    31     DECLARE @tintLength AS TINYINT;
    32     SET @tintLength = LEN(@chCodeChar);
    33  
    34     IF @tintLength <= (@tintFixLength - 1) OR @tintLength >= (@tintFixLength + 1)
    35     BEGIN
    36         RETURN @intCodeIntegerValue;
    37     END
    38  
    39     DECLARE @tblCodeChars TABLE(
    40         CodeChar CHAR(1) NOT NULL,
    41         CodeValue TINYINT NOT NULL
    42     );
    43  
    44     INSERT INTO  @tblCodeChars (CodeChar, CodeValue)
    45     SELECT CodeChar, CodeValue
    46     FROM dbo.ufn_GetCodeChars();
    47  
    48     WHILE @tintLength >= 1
    49     BEGIN    
    50         SELECT @intCodeIntegerValue = @intCodeIntegerValue + CodeValue * POWER(10, @tintFixLength - @tintLength)
    51         FROM @tblCodeChars
    52         WHERE CodeChar = SUBSTRING(@chCodeChar, @tintLength, 1);
    53  
    54         SET @tintLength = @tintLength - 1;        
    55     END
    56  
    57     RETURN @intCodeIntegerValue;
    58 END
    59 GO

     

    转换为整数数值为编码字符的标量函数
    该函数的T-SQL代码如下:
     1 IF OBJECT_ID(N'dbo.ufn_GetCodeChar', 'FN') IS NOT NULL
     2 BEGIN
     3     DROP FUNCTION dbo.ufn_GetCodeChar;
     4 END
     5 GO
     6  
     7 --==================================
     8 -- 功能: 通过编码整数值获取对应的编码字符
     9 -- 说明: 具体实现阐述 
    10 -- 作者: XXX
    11 -- 创建: yyyy-MM-dd
    12 -- 修改: yyyy-MM-dd XXX 修改内容描述
    13 --==================================
    14 CREATE FUNCTION dbo.ufn_GetCodeChar
    15 (
    16     @intCodeIntegerValue INT
    17 ) RETURNS CHAR(5)
    18     --$Encode$--
    19 AS
    20 BEGIN
    21     SET @intCodeIntegerValue = ISNULL(@intCodeIntegerValue, 0);
    22     DECLARE @chCodeChar AS VARCHAR(9);
    23     SET @chCodeChar = '';
    24  
    25     DECLARE @tintFixLength AS TINYINT;
    26     SET @tintFixLength =dbo.ufn_GetCodeCharFixLength();
    27  
    28     IF @intCodeIntegerValue NOT BETWEEN dbo.ufn_GetCodeIntegerValue('A' + REPLICATE('0', @tintFixLength - 1)) AND dbo.ufn_GetCodeIntegerValue(REPLICATE('Z', @tintFixLength))
    29     BEGIN
    30         RETURN @chCodeChar;
    31     END
    32  
    33     DECLARE @tblCodeChars TABLE(
    34         CodeChar CHAR(1) NOT NULL,
    35         CodeValue TINYINT NOT NULL
    36     );
    37  
    38     INSERT INTO  @tblCodeChars (CodeChar, CodeValue)
    39     SELECT CodeChar , CodeValue
    40     FROM dbo.ufn_GetCodeChars();
    41  
    42     DECLARE @tintPerCodeValue TINYINT;
    43     SET @tintPerCodeValue = 0;
    44  
    45     WHILE @tintFixLength >= 1
    46     BEGIN        
    47         SET @tintPerCodeValue =  @intCodeIntegerValue / POWER(10, @tintFixLength - 1);
    48  
    49         SELECT TOP 1 @chCodeChar = @chCodeChar + CodeChar, @tintPerCodeValue = CodeValue 
    50         FROM @tblCodeChars
    51         WHERE CodeValue <= @tintPerCodeValue
    52         ORDER BY CodeValue DESC;
    53  
    54         SET @intCodeIntegerValue = @intCodeIntegerValue - @tintPerCodeValue * POWER(10, @tintFixLength - 1);
    55  
    56         SET @tintFixLength = @tintFixLength - 1;
    57     END
    58  
    59     RETURN @chCodeChar;
    60 END
    61 GO
    62  

    测试实现效果

     
    测试的T-SQL代码如下:
     1 DECLARE @chCodeChar AS CHAR(8);
     2 SET @chCodeChar = 'A0000';
     3 DECLARE @intValue AS INT;
     4 SET @intValue = dbo.ufn_GetCodeIntegerValue(@chCodeChar);
     5  
     6 SELECT @chCodeChar AS CurrentCodeChar, @intValue AS CurrentCodeIntegerValue, dbo.ufn_GetCodeChar(@intValue + 1) AS NextCodeChar;
     7 GO
     8  
     9 DECLARE @chCodeChar AS CHAR(8);
    10 SET @chCodeChar = 'ZZZZY';
    11 DECLARE @intValue AS INT;
    12 SET @intValue = dbo.ufn_GetCodeIntegerValue(@chCodeChar);
    13  
    14 SELECT @chCodeChar AS CurrentCodeChar, @intValue AS CurrentCodeIntegerValue, dbo.ufn_GetCodeChar(@intValue + 1) AS NextCodeChar;
    15 GO

     

    执行后的查询结果如下:
     
    实现方案的限制
     
        该实现方案只能实现编码字符长度最多为8位的编码字符与整数数值的相互转换。如果要要实现编码字符固定长度更长的(比如编码字符固定长度为6位、7位或8位)功能,必须要修改三个函数,具体的修改处如下图:
     
     
    以上图红色矩形框标注的地方,务必要一致才可以的。如果全部更改为6,那就满足编码字符固定长度为6位的实现;也可以修改为7或8,最多只能修改为8。
     
    博友如有其他更好的解决方案,也请不吝赐教,万分感谢。
     
     
  • 相关阅读:
    hud 1166 敌兵布阵
    zznu 1914 asd的甩锅计划
    poj 1860 Currency Exchange
    poj 3026 Borg Maze (BFS + Prim)
    poj 2349 Arctic Network
    POJ 1502 MPI Maelstrom
    poj 1308 Is It A Tree?
    hdu 1272 小希的迷宫
    poj 1679 http://poj.org/problem?id=1679
    POJ 2492 A Bug's Life
  • 原文地址:https://www.cnblogs.com/dzy863/p/5083164.html
Copyright © 2011-2022 走看看