我在SQL Server获取下一个编码字符实现的博文中,虽然实现了这个问题,但是感觉维护起来比较麻烦,例如如果调整编码字符串的固定长度,就需要变更三个函数,这样的为何成本确实比较大。面向对象编程很重视讲究开放封闭原则,我认为数据库对象特别函数、存储等对象也要尽量封装成实现单一功能,维护起来简单,也方便后续人员的维护,便利别人也是便利自己。
 
    针对编码字符串的规则,继续延伸总结如下:
1、第一个字符必须是字母A-Z中任意一个字符,其长度可以为1位、2位、3位,……,6位、7位、8位、……;
2、编码字符串满足递进增加。如果编码字符串长度为5位,则编码字符串是A0000,下一个是A0001,直到A9999,其下一个是B0000,直到B9999,其下一个是C0000,……,如果编码是ZB999,下一个是ZC000,……,直到ZZZZZ;无论其长度为1位到N位中的任何一个长度,均要满足递进增加。
 
    我的实现方案是将编码字符串中每一位的字符对应的整数值加工转换为一个10进制整数值,再实现将一个将整数值转换为一个编码字符串,也就是将编码字符串和整数值相互转换。由于方案中是使用了POWER函数,受限其结果值的长度,此方案最多支持8位长度的编码字符串和整数值间的相互转换。
    
    通过以上规则分析,不同长度的编码字符均对应不同的最小和最大编码字符串,我的方案是编码字符串和整数相互转换,也就是不同长度的编码字符对应的不同的相对应的最小和最大整数值,也就是不同的长度对应的不同的整数范围,且这些不同长度对应的整数范围之间是不连续,比如长度1位对应的最大整数值和长度2位对应的最小整数不是相等。
    
    方案的具体实现思路如下:
1、由于使用到数字0-9和字母[A-Z](大写)字母这两类字符,将以上字符和10进制整数值之间的硬编码对应,将其封装为一个表值函数。
2、实现将一个编码字符串转换为一个整数值,此功能封装为一个标量函数。
3、针对不同长度的编码字符串对应的不同最小和最大整数,这个功能也可以检查一个整数值是否在满足转换为一个编码字符串,也封装为一个表值函数。
4、将一个整数值转换为一个编码字符串,此功能也封装在一个标量函数中。
    
    针对上实现方案主要重构的部分包括函数命名,针对表(表值或内联表)函数和标量函数尽量通过命名标识符来区分。还解决了编码字符串穿不同长度的实现来强制修改所涉及三个函数的缺陷。为了讲解方便,我根据该方案的实现思路的4个步骤,将其对应的部分分为:字符映射表值函数、获取编码字符串整数值标量函数、获取编码字符串长度和整数值范围表函数和获取整数值对应的编码字符串变量函数。
 
字符映射表值函数
 
该函数的T-SQL代码如下:
 IF OBJECT_ID(N'dbo.ufn_GetCharTable', 'TF') IS NOT NULL
BEGIN
DROP FUNCTION dbo.ufn_GetCharTable;
END
GO --==================================
-- 功能: 获取字符映射表表值函数
-- 说明: 编码字符只包含0-9和A-Z这两类字符
-- 将以上字符映射到对应十进制数值。
-- 作者: XXX
-- 创建: yyyy-MM-dd
-- 修改: yyyy-MM-dd XXX 修改内容描述
-- 调用: SELECT CodeChar, CodeValue FROM dbo.ufn_GetCharTable();
--==================================
CREATE FUNCTION dbo.ufn_GetCharTable
(
) RETURNS @tblChar TABLE (
[Char] CHAR() NOT NULL,
Value TINYINT NOT NULL
)
--$Encode$--
AS
BEGIN
DECLARE
@intStartIndexID AS TINYINT,
@intEndIndexID AS TINYINT; SELECT
@intStartIndexID = ,
@intEndIndexID = ; -- 初始化0-9数字字符
SELECT
@intStartIndexID = ASCII(''),
@intEndIndexID = ASCII('');
WHILE @intStartIndexID <= @intEndIndexID
BEGIN
INSERT INTO @tblChar ([Char], Value)
VALUES (CHAR(@intStartIndexID), ); SET @intStartIndexID = @intStartIndexID + ;
END -- 初始化A-Z字母字符
SELECT
@intStartIndexID = ASCII('A'),
@intEndIndexID = ASCII('Z');
WHILE @intStartIndexID <= @intEndIndexID
BEGIN
INSERT INTO @tblChar ([Char], Value)
VALUES (CHAR(@intStartIndexID), ); SET @intStartIndexID = @intStartIndexID + ;
END -- 修改每个字符对应的10进制整数值
;WITH tCodeData AS (
SELECT [Char], ROW_NUMBER() OVER (ORDER BY [Char] ASC) AS RowNum
FROM @tblChar
) UPDATE T2
SET T2.Value = T.RowNum -
FROM tCodeData AS T
INNER JOIN @tblChar AS T2
ON T.[Char] = T2.[Char]; RETURN;
END
GO
获取编码字符串整数值标量函数
该函数的T-SQL代码如下:
 IF OBJECT_ID(N'dbo.ufn_GetCodeCharsValue', 'FN') IS NOT NULL
BEGIN
DROP FUNCTION dbo.ufn_GetCodeCharsValue;
END
GO --==================================
-- 功能: 获取编码字符串对应的10进制整数数值
-- 说明: 具体实现阐述
-- 作者: XXX
-- 创建: yyyy-MM-dd
-- 修改: yyyy-MM-dd XXX 修改内容描述
-- 调用: SELECT dbo.ufn_GetCodeIntegerValue('A0000')
--==================================
CREATE FUNCTION dbo.ufn_GetCodeCharsValue
(
@chvCodeChars VARCHAR() -- 编码字符串 ) RETURNS INT
--$Encode$--
AS
BEGIN
SET @chvCodeChars = ISNULL(@chvCodeChars, '');
SET @chvCodeChars = UPPER(@chvCodeChars); DECLARE @intCodeCharsValue AS BIGINT;
SET @intCodeCharsValue = ; DECLARE @tintLength AS TINYINT;
SET @tintLength = LEN(@chvCodeChars); IF @tintLength =
BEGIN
RETURN @intCodeCharsValue;
END DECLARE @tblChar TABLE(
[Char] CHAR() NOT NULL,
Value TINYINT NOT NULL
); INSERT INTO @tblChar ([Char], Value)
SELECT [Char], Value
FROM dbo.ufn_GetCharTable(); -- 编码字符串的首字母必须是A-Z字母字符的逻辑检查
IF NOT EXISTS (SELECT FROM @tblChar WHERE [Char] = SUBSTRING(@chvCodeChars, , ) AND Value >= )
BEGIN
RETURN @intCodeCharsValue;
END WHILE @tintLength >=
BEGIN
SELECT @intCodeCharsValue = @intCodeCharsValue + CAST(Value * POWER(, @tintLength - ) AS BIGINT)
FROM @tblChar
WHERE [Char] = SUBSTRING(@chvCodeChars, , ); SET @chvCodeChars = STUFF(@chvCodeChars, , , ''); SET @tintLength = @tintLength - ;
END RETURN @intCodeCharsValue;
END
GO

获取编码字符串长度和整数值范围表函数

该函数的T-SQL代码如下:
 IF OBJECT_ID(N'dbo.ufn_GetCodeCharsValueTable', 'TF') IS NOT NULL
BEGIN
DROP FUNCTION dbo.ufn_GetCodeCharsValueTable;
END
GO --==================================
-- 功能: 获取编码字符串不同长度对应的整数值范围
-- 说明: 具体实现阐述
-- 作者: XXX
-- 创建: yyyy-MM-dd
-- 修改: yyyy-MM-dd XXX 修改内容描述
-- 调用: SELECT StartValue, EndValue, FixLength FROM dbo.ufn_GetCodeCharsValueTable();
--==================================
CREATE FUNCTION dbo.ufn_GetCodeCharsValueTable
( ) RETURNS @tblCodeCharValue TABLE (
StartValue INT NOT NULL,
EndValue INT NOT NULL,
FixLength TINYINT NOT NULL
)
AS
BEGIN
DECLARE
@tintLength AS TINYINT,
@tintMaxLength AS TINYINT;
SELECT
@tintLength = ,
@tintMaxLength = ; WHILE @tintLength <= @tintMaxLength
BEGIN
INSERT INTO @tblCodeCharValue (StartValue, EndValue, FixLength)
VALUES (dbo.ufn_GetCodeCharsValue(CONCAT('A', REPLICATE('', @tintLength - ))), dbo.ufn_GetCodeCharsValue(CONCAT('Z', REPLICATE('Z', @tintLength - ))), @tintLength); SET @tintLength = @tintLength + ;
END RETURN;
END
GO
获取整数值对应的编码字符串变量函数。
该函数的T-SQL代码如下:
 IF OBJECT_ID(N'dbo.ufn_GetCodeChars', 'FN') IS NOT NULL
BEGIN
DROP FUNCTION dbo.ufn_GetCodeChars;
END
GO --==================================
-- 功能: 获取一个整数值对应的编码字符串
-- 说明: 具体实现阐述
-- 作者: XXX
-- 创建: yyyy-MM-dd
-- 修改: yyyy-MM-dd XXX 修改内容描述
--==================================
CREATE FUNCTION dbo.ufn_GetCodeChars
(
@intCodeCharsValue INT -- 编码字符串整数值
) RETURNS VARCHAR()
--$Encode$--
AS
BEGIN
SET @intCodeCharsValue = ISNULL(@intCodeCharsValue, );
DECLARE @chvCodeChars AS VARCHAR();
SET @chvCodeChars = ''; -- 整数值长度变量
DECLARE @tintFixLength AS TINYINT;
SET @tintFixLength = ; SELECT @tintFixLength = FixLength
FROM dbo.ufn_GetCodeCharsValueTable()
WHERE @intCodeCharsValue BETWEEN StartValue AND EndValue; -- 整数值范围的逻辑检查
IF @tintFixLength =
BEGIN
RETURN @chvCodeChars;
END DECLARE @tblChar TABLE(
[Char] CHAR() NOT NULL,
Value TINYINT NOT NULL
); INSERT INTO @tblChar ([Char], Value)
SELECT [Char], Value
FROM dbo.ufn_GetCharTable(); DECLARE @tintPerCodeValue TINYINT;
SET @tintPerCodeValue = ; WHILE @tintFixLength >=
BEGIN
SET @tintPerCodeValue = @intCodeCharsValue / POWER(, @tintFixLength - ); SELECT TOP @chvCodeChars = @chvCodeChars + [Char], @tintPerCodeValue = Value
FROM @tblChar
WHERE Value <= @tintPerCodeValue
ORDER BY Value DESC; SET @intCodeCharsValue = @intCodeCharsValue - @tintPerCodeValue * POWER(, @tintFixLength - ); SET @tintFixLength = @tintFixLength - ;
END RETURN @chvCodeChars;
END
GO
测试实现效果
 
测试T-SQL代码如下:
 DECLARE @chvCodeChars AS VARCHAR();
SET @chvCodeChars = CONCAT('A', REPLICATE('', - ));
DECLARE @intCodeCharsValue AS INT;
SET @intCodeCharsValue = dbo.ufn_GetCodeCharsValue(@chvCodeChars); SELECT @chvCodeChars AS CurrentCodeChars, @intCodeCharsValue AS CurrentCodeCharsValue, dbo.ufn_GetCodeChars(@intCodeCharsValue + ) AS NextCodeChars
GO
执行后的查询结果如下:
 
博友如有其他更好的解决方案,也请不吝赐教,万分感谢。

SQL Server获取下一个编码字符实现继续重构与增强的更多相关文章

  1. SQL Server获取下一个编码字符实现

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

  2. SQL Server获取下一个编码字符串的实现方案分割和进位

        我在前一种解决方案SQL Server获取下一个编码字符实现和后一种解决方案SQL Server获取下一个编码字符实现继续重构与增强两篇博文中均提供了一种解决编码的方案,考虑良久对比以上两种方 ...

  3. 【转】sql server 获取每一个类别中值最大的一条数据

    /* 数据如下: name val memo a 2 a2(a的第二个值) a 1 a1--a的第一个值 a 3 a3:a的第三个值 b 1 b1--b的第一个值 b 3 b3:b的第三个值 b 2 ...

  4. sql server 获取每一个类别中值最大的一条数据

    /* 数据如下: name val memo a 2 a2(a的第二个值) a 1 a1--a的第一个值 a 3 a3:a的第三个值 b 1 b1--b的第一个值 b 3 b3:b的第三个值 b 2 ...

  5. 第1/24周 SQL Server 如何执行一个查询

    大家好,欢迎来到第1周的SQL Server性能调优培训.在我们进入SQL Server性能调优里枯燥难懂的细节内容之前,我想通过讲解SQL Server如何执行一个查询来建立基础.这个部分非常重要, ...

  6. 第1周 SQL Server 如何执行一个查询

    原文:第1周 SQL Server 如何执行一个查询 大家好,欢迎来到第1周的SQL Server性能调优培训.在我们进入SQL Server性能调优里枯燥难懂的细节内容之前,我想通过讲解SQL Se ...

  7. SQL Server 2008下日志清理方法 2

    SQL Server 2008下日志清理方法 (2011-07-14 10:30:45) 转自 http://blog.sina.com.cn/s/blog_4bdd3d0b0100wfvq.html ...

  8. SQL Server获取索引创建时间&重建时间&重组时间

    之前写过一篇博客"SQL Server中是否可以准确获取最后一次索引重建的时间?",里面主要讲述了三个问题:我们能否找到索引的创建时间?最后一次索引重建(Index Rebuild ...

  9. SQLServer数据库之SQL Server 获取本周,本月,本年等时间内记录

    本文主要向大家介绍了SQLServer数据库之SQL Server 获取本周,本月,本年等时间内记录,通过具体的内容向大家展现,希望对大家学习SQLServer数据库有所帮助. datediff(we ...

随机推荐

  1. Wix 安装部署教程(十四) -- 多语言安装包之用户许可协议

    在上一篇中,留下了许可协议的问题,目前已经解决.感谢网友武全的指点! 问题 一般我们是用WixVariable 来设定许可协议.如下所示: <WixVariable Id="WixUI ...

  2. TDD(测试驱动开发)培训录

    2014年我一直从事在敏捷实践咨询项目,这也是我颇有收获的一年,特别是咨询项目的每一点改变,不管是代码质量的提高,还是自组织团队的建设,都能让我们感到欣慰.涉及人的问题都是复杂问题,改变人,改变一个组 ...

  3. js中的console很强大

    今天闲来没事,瞎逛, 发现了淘宝首页的这个: 想起来之前在百度的 页面中也曾看到过.于是乎自己试一试. 于是便见识到了console对象其实很强大,用好它对调试真的有很大帮助. 代码: <!DO ...

  4. Hello Mybatis 03 数据关联

    ResultMap 在实际的开发中,数据库不总是我们希望看到的样子.比如我们希望User的主键是id但是数据库偏偏喜欢叫它u_id,这样一来原先的resultType似乎就失效了,不带这么玩的,整个人 ...

  5. django开发个人简易Blog——构建项目结构

    开发之前第一步,就是构造整个的项目结构.这就好比作一幅画,第一步就是描绘轮廓,有了轮廓,剩下的就是慢慢的填充细节.项目结构规划如下图: 项目结构描述: 本项目以fengzhengBlog为根目录. a ...

  6. AngularJS快速入门指南15:API

    thead>tr>th, table.reference>tbody>tr>th, table.reference>tfoot>tr>th, table ...

  7. SQL——索引

    索引是根据表中一列或若干列按照一定顺序建立的列值与记录行之间的对应关系表.在数据库系统中建立索引主要有以下作用: l快速存取数据: l保证数据记录的唯一性: l实现表与表之间的参照完整性: l在使用O ...

  8. Linux应用总结(1):自动删除n天前日志

    linux是一个很能自动产生文件的系统,日志.邮件.备份等.虽然现在硬盘廉价,我们可以有很多硬盘空间供这些文件浪费,让系统定时清理一些不需要的文件很有一种爽快的事情.不用你去每天惦记着是否需要清理日志 ...

  9. Atitit usrqbg1821 Tls 线程本地存储(ThreadLocal Storage 规范标准化草案解决方案ThreadStatic

    Atitit usrqbg1821 Tls 线程本地存储(ThreadLocal Storage 规范标准化草案解决方案ThreadStatic 1.1. ThreadLocal 设计模式1 1.2. ...

  10. Asp.net WebApi 项目示例(增删改查)

    1.WebApi是什么 ASP.NET Web API 是一种框架,用于轻松构建可以由多种客户端(包括浏览器和移动设备)访问的 HTTP 服务.ASP.NET Web API 是一种用于在 .NET ...