通用固定长度编码格式的字符串查找算法的实现

Posted magenfeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通用固定长度编码格式的字符串查找算法的实现相关的知识,希望对你有一定的参考价值。

 


             
通用固定长度编码格式的字符串查找算法的实现

 
 

字符串的查找是数据库应用中必不可少的操作,而且每种数据库产品(ORACLE、DB2、SYBASE、MS SQL SERVER、mysql等等)也都提供了对应的字符串处理函数,比如DB2的LOCATE函数。

但在实际的工作中,还是会遇到一些特殊情况的处理,这使得直接使用字符串查找函数,得到的结果可能是错误的,比如本文中提到的固定长度编码格式的字符串的查找。值得注意的是,本文提出的算法可以稍加修改即移植到其它关系数据库系统或者前端开发工具中。

在实际数据库应用系统中,会经常遇到有些数据表中的一些字段,实际上是采用了某些固定格式的编码规则,比如在本人工作单位中的OLTP数据库中,有一个出口流水表TB_OUTLISTGW中的ROADCOMB字段、ROADSSTARTSTATION字段、ROADSSTARTSTATION字段中都是经过固定长度编码格式的数据,ROADCOMB记录了在广东省高速公路上行驶的车辆所经过的所有高速公路的组合,采用16进制编码,每两位表示一条高速公路的16进制编码,比如11代表10进制的17,即广惠高速公路。

举个例子来说,要统计哪些流水是经过了广惠高速公路(实际上需求比这复杂得多)。大家都会给出以下的SQL 语句(DB2格式)

SELECT *

FROMDEVELOP.TB_OUTLISTGW

WHERELOCATE(ROADCOMB,’11’)>0

FETCH FIRST 100ROW ONLY

WITH UR;

但实际上,这条语句是有一定问题的,ROADCOMB是每两位的16进制数据代表了一条路段,查找的时候需要每两个字符跟目标路段匹配一次,而不是每个字符+后面的字符跟目标字符串逐次进行匹配,本人采取的是以下的做法,建立了一个固定长度编码格式的字符串匹配通用函数,大家可以用其它关系数据库系统的SQL语法格式来翻译过去,这样就可以在其它数据库系统使用了。以下是笔者用万能数据库查询分析器的中文版本《DB 查询分析器》来创建并调用 这个通用的固定长度编码格式的字符串查找函数的过程。(具体方法详见我的博文DB 查询分析器 6.03 方便地创建DB2自定义函数》  http://blog.csdn.net/magenfeng/article/details/45694907 )

 

DROP FUNCTION DEVELOP.F_LOCATE_FIXED

$$


---通用的固定长度编码格式的字符串查找函数

CREATE FUNCTION DEVELOP.F_LOCATE_FIXED(IN V_SRC VARCHAR(4096),IN V_DES VARCHAR(4096))

RETURNS INTEGER

LANGUAGE SQL

DETERMINISTIC 

NO EXTERNAL ACTION

CONTAINS SQL

BEGIN ATOMIC

DECLARE v_resultINTEGERDEFAULT 0;

DECLARE str_roadVARCHAR(4096); 

DECLARE v_len_srcINTEGER;

DECLARE v_len_desINTEGER;

DECLARE v_pos_srcINTEGER DEFAULT 1;

SET v_len_des=LENGTH(TRIM(V_DES));

SET v_len_src=LENGTH(TRIM(V_SRC));

SET v_result=0;

AUTHLOOP:

WHILE v_pos_src+v_len_src<=v_len_des DO

SET str_road=SUBSTR(V_DES,v_pos_src,v_len_src); 

IF ( str_road=V_SRC ) THEN

SET v_result=v_pos_src;  --函数返回匹配的实际物理位置

SET v_result=v_result/v_len_src+1;  --函数返回匹配的逻辑位置,即第几个子串位置;这一条语句如果注释掉,函数将返回匹配的实际物理位置

LEAVE AUTHLOOP;

ELSE

SET v_pos_src=v_pos_src+v_len_src; 

END IF;  

END WHILE;

RETURN v_result;

END

$$


values  DEVELOP.F_LOCATE_FIXED('11','4F0A0B0D231154533F01')

$$


values  DEVELOP.F_LOCATE_FIXED('11','01100110011001100110011001100110')

$$

 

SELECT *

FROMDEVELOP.TB_OUTLISTGW

WHERE DEVELOP. F_LOCATE_FIXED ('11',ROADCOMB)>0

FETCH FIRST 100ROW ONLY

WITH UR;

$$

 



图1   SQL 语句执行前





图2   SQL 语句执行后(一)





图3   SQL 语句执行后(二) values  DEVELOP.F_LOCATE_FIXED('11','4F0A0B0D231154533F01')的返回结果






图4   SQL 语句执行后(三) values  DEVELOP.F_LOCATE_FIXED('11','01100110011001100110011001100110')的返回结果

在字符串'01100110011001100110011001100110'中查找子串'11',关系数据库系统正常匹配会返回1;但实际情况字符串是2位一组,按照某种编码规则来编码,这种情况下进行固定2位长度进行匹配则会失败,应该返回0 。values DEVELOP.F_LOCATE_FIXED('11','01100110011001100110011001100110')也确实是返回了0。