近期在项目中遇到版本号的比较问题,如
5.4.3.2 与
5.4.2.3,
这种格式直接比较字符串大小即可。
但是如果遇到
5.4.3.2 与
5.4.3.10,
那么直接比较字符串大小,则是错误的结果。
可能这种问题在java中比较好处理,但在关系型数据库里(如MySQL、Oracle)中处理起来,则会麻烦一些:
处理思路是:
1.先将原始版本号字符串追加虚拟版本号。如5.7.3.8后追加.0.0,处理成5.7.3.8.0.0这个样子,这样做的原因是保持字符串左对齐。
2.分别提取主版本(5)、子版本信息(4)、阶段版本(3)、(2)等具体值。
3.每种提取的版本值左边补0,补够10位(视业务而定),如主版本为5,补齐后为0000000005,阶段版本为10,补齐后为0000000010。
4.按照主版本、子版本、阶段版本的顺序,拼凑成一个字符串。
5.比较拼凑的2个字符串的大小。
MySQL:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
复习用到的一些函数:
1.SUBSTRING_INDEX(str, delim, count)
str:原始字符串;delim:分隔符;count:分隔符在str中出现的次数
函数作用:返回分隔符在str中出现的次数之前的部分。
select SUBSTRING_INDEX('5.4.3.2 .1','.',3); //返回5.4.3
select SUBSTRING_INDEX('5.4.3.2 .1','.',2); //返回5.4
2.SUBSTRING,截取字符串,有多个重构函数,这个不消多说。
select SUBSTRING('5.4.3.2.1',3);
3.INSTR(str, substr)
str:原始字符串;substr:子串
函数作用:返回子串在原始字符串中第一次出现的位置
select INSTR('5.4.3.2.1','.'); //返回2
4.LPAD(str, len, padstr)
str:原始字符串;len:填充后的字符串总长度;padstr:待填充的字符
函数作用:在原始字符串左侧补充“待填充的字符”,填充后总长度为len。RPAD(str, len, padstr)同理。
select lpad('5', 10, '0'); //返回0000000005
#fetch 1st parameter(5), pad prefix with 0,the length of handled string is 10.
select SUBSTRING_INDEX('5.4.3.2.1','.',1);
#fetch 2nd parameter(4),with suffix 10 times of 0.
select substring(SUBSTRING_INDEX('5.4.3.2.1','.',2),INSTR(SUBSTRING_INDEX('5.4.3.2.1','.',2),'.')+1);
select substring(SUBSTRING_INDEX('5.4.3.2.1','.',2), LENGTH(SUBSTRING_INDEX('5.4.3.2.1','.',1))+2);
#fetch 3rd parameter(3),pad prefix with 0,the length of handled string is 10.
select substring(substring(SUBSTRING_INDEX('5.4.3.2.1','.',3),INSTR(SUBSTRING_INDEX('5.4.3.2.1','.',3),'.')+1),INSTR(substring(SUBSTRING_INDEX('5.4.3.2.1','.',3),INSTR(SUBSTRING_INDEX('5.4.3.2.1','.',3),'.')+1),'.')+1);
select substring(SUBSTRING_INDEX('5.4.3.2.1','.',3), LENGTH(SUBSTRING_INDEX('5.4.3.2.1','.',2))+2);
#fetch 4th parameter(2),pad prefix with 0,the length of handled string is 10.
select substring(SUBSTRING_INDEX('5.4.3.2.1','.',4), LENGTH(SUBSTRING_INDEX('5.4.3.2.1','.',3))+2);
然后使用lpad函数在左侧补0,最后使用concat函数按书序拼凑各个版本号。
拼凑后的结果如:
0000000005000000000400000000030000000002(原始为5.4.3.2)
0000000005000000000400000000030000000010(原始为5.4.3.10)
这时,再比较这2个字符串,就可以比较粗真实的大小。
Oracle:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Oracle中函数使用方法与MySQL中大体相同,但是功能更强。
事例sql脚本如下:
select
cntindex,status,syncerrorcode,
lpad(substr(substr(concat(syncerrorcode,'.0.0'), 1, instr(concat(syncerrorcode,'.0.0'),'.',1,3)-1),1,instr(substr(concat(syncerrorcode,'.0.0'), 1, instr(concat(syncerrorcode,'.0.0'),'.',1,3)-1),'.',1,1)-1),5,'0')||lpad(substr(substr(substr(concat(syncerrorcode,'.0.0'), 1, instr(concat(syncerrorcode,'.0.0'),'.',1,3)-1) , instr(substr(concat(syncerrorcode,'.0.0'), 1, instr(concat(syncerrorcode,'.0.0'),'.',1,3)-1),'.',1,1)+1 ),1,instr(substr(substr(concat(syncerrorcode,'.0.0'), 1, instr(concat(syncerrorcode,'.0.0'),'.',1,3)-1) , instr(substr(concat(syncerrorcode,'.0.0'), 1, instr(concat(syncerrorcode,'.0.0'),'.',1,3)-1),'.',1,1)+1),'.',1,1)-1 ),5,'0')||lpad(substr(substr(concat(syncerrorcode,'.0.0'), 1, instr(concat(syncerrorcode,'.0.0'),'.',1,3)-1), instr(substr(concat(syncerrorcode,'.0.0'), 1, instr(concat(syncerrorcode,'.0.0'),'.',1,3)-1),'.',1,2)+1) ,5,'0') as prefix_syncerrorcode,fileindex from mcnt_file