我在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. SQL SERVER 2012 只能识别20个CPU的问题

    背景 最近在给客户优化时时候发现客户的虚拟机环境分配了32C 但是只能识别20个,物理机64C,64G内存,本来没什么,CPU利用率在40%左右,但是优化后同时增加了 CPU和内存的分配,CPU32增 ...

  2. Flume采集处理日志文件

    Flume简介 Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据:同时,Flume提供对数据 ...

  3. chrome浏览器渲染白屏问题剖析

    刚截图十几次,终于捕捉到了这个白屏现象,hiahia~~ 大家可以很清晰地看到下边还木有渲染完毕的透明层,这是一个十分普遍的问题,经常遇到.我的浏览器版本是 到目前为止应该是最新版(release版本 ...

  4. [.net 面向对象编程基础] (17) 数组与集合

    [.net 面向对象编程基础] (17) 数组与集合 学习了前面的C#三大特性,及接口,抽象类这些相对抽象的东西以后,是不是有点很累的感觉.具体的东西总是容易理解,因此我们在介绍前面抽象概念的时候,总 ...

  5. java.logging的重定向?

    接着昨天的工作. 上面说要重定向java.util.logging.Logger的输出, 发现也不是不可能. package jmx; import java.util.logging.FileHan ...

  6. Atiti  attilax主要成果与解决方案与案例rsm版 v4

    Atiti  attilax主要成果与解决方案与案例rsm版 v4 版本历史记录1 1. ##----------主要成果与解决方案与 参与项目1 ###开发流程与培训系列1 #-----组织运营与文 ...

  7. Atitti css transition Animation differ区别

    Atitti  css   transition Animation differ区别 1.1. transition的优点在于简单易用,但是它有几个很大的局限.  1 1.2. Transition ...

  8. salesforce 零基础开发入门学习(六)简单的数据增删改查页面的构建

    VisualForce封装了很多的标签用来进行页面设计,本篇主要讲述简单的页面增删改查.使用的内容和设计到前台页面使用的标签相对简单,如果需要深入了解VF相关知识以及标签, 可以通过以下链接查看或下载 ...

  9. Java基础-继承-编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight。小车类Car是Vehicle的子类,其中包含的属性有载人数 loader。卡车类Truck是Car类的子类,其中包含的属性有载重量payload。每个 类都有构造方法和输出相关数据的方法。最后,写一个测试类来测试这些类的功 能。

    #29.编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight.小车类Car是Vehicle的子类,其中包含的属性有载人数 loader.卡车类T ...

  10. SQL Pass北京举办1周年活动(本次活动特别邀请到了来自微软的SQL Server大师何雷谈数据库职业规划)

    地点:北京微软(中国)有限公司[望京利星行],三层308室 时间:2013年 12 月28日 13:30-16:30 SQL PASS 北京QQ群号:2435349 新浪微群地址:http://q.w ...