SQL Server中检索语句中Like的算法实现

原创 2003年05月08日 14:15:00

本文主要对字串匹配Like的算法实现,在SQL ServerLike的匹配中主要有表现为对两个通配符的处理,分别为“_”代表一个字符,“%”代表任意个字符。由于“%”在匹配过程中的位置任意性,所以完全匹配、通配符“_”匹配与此不应该一起参与匹配运算,所以我们决定在匹配前先将子串按“%”分段,进行逐段匹配,显然降低了匹配算法的难度,下面讲解一下算法的实现过程:(后附实现源码)

1.   确定第一个“%”的位置,

目的:确定模式匹配的方式

a>     是以“%”开头则不需要左匹配(左匹配即要求子串的第一个字符必须与原串的第一个字符相一致)

b>     不是以“%”开头则需要进行左匹配

2.   进行KMP*算法进行模式匹配

KMP算法不能完全地实现本文提到的匹配算法,我们必须对此加以修正,主要是模式因子不适合,在这里必须认为“_”的因子值为与前一个任意字符一致,所以“_”越多,匹配时的回退的可能性将越少,当然其匹配速度比教课书上的模式查找要快。

3.   继续下一个子串段的匹配工作。

下面提供算法的源码,分为两个函数,

1.   _strat

为KMP*模式串查找函数,函数前有其使用说明。

2.   _strlike

Like的实现过程,内部用到_strat模式串匹配函数,实现的关键是对模式串的分段,来降低匹配的难度。

 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

////////////////////////////////////////////////////////////////////////////////

//     函数名称:int _strat(

//                          char * chText,

//                          char * chPattern,

//                          int nbegpos,

//                          int nlen

//                          bool bleft )

//     实现功能:模式串搜索

//     对全局变量的影响:无

//     参数说明:

//            chText                            原串

//            chPattern               模式串

//            nbegpos                       起始位置

//            nlen                      原串相对长度

//            bleft                      是否左对齐(即第一个字符必须一致)

//     返回结果说明:实际位置

//     待优化一:回退数不得大于nlen - len(chPattern),即回退后无法导致完全匹配

//     待优化二:计算模式串与字串搜索代码合并,减少计算量

////////////////////////////////////////////////////////////////////////////////

int _strat(char * chText , char * chPattern , int nbegpos /* = 0 */ , int nlen /* = -1 */ , bool bleft /* = false */)

{

       int nPatternLen = _tcslen(chPattern);

       int nTextLen = _tcslen(chText);

       if(nlen >= 0)

       {

              if(nbegpos + nlen < nTextLen)

                     nTextLen = nbegpos + nlen;

       }

       if(nbegpos + nPatternLen > nTextLen || nPatternLen > MAXLEN_PATTERN)

              return -1;

       if(nPatternLen == 0)

              return nbegpos;

       else

       {

              int nGeneralLen = 0;

              short chNext[MAXLEN_PATTERN] = { -1 };

              int nPattPos = 0 , nNext = -1;

              if(!bleft)

              {

                     //生成模式回退值

                     while(nPattPos < nPatternLen)

                     {

                            if( nNext == -1 || chPattern[nPattPos] == '_' || chPattern[nPattPos] == chPattern[nNext])

                            {

                                   nPattPos ++;

                                   nNext ++;

                                   chNext[nPattPos] = nNext;

                            }

                            else

                                   nNext = chNext[nNext];

                     }

              }

              int nTextPos = nbegpos;

              nPattPos = 0;

              //进行模式匹配

              while(nPattPos < nPatternLen && nTextPos < nTextLen)

              {

                     if(nPattPos == -1 || chPattern[nPattPos] == '_' || chPattern[nPattPos] == chText[nTextPos])

                     {

                            nPattPos ++;

                            nTextPos ++;

                     }

                     else

                     {

                            //要求左对齐时,不允许回退(回退时肯定不是左对齐的)

                            if(bleft)

                                   return -1;

                            else

                                   nPattPos = chNext[nPattPos];

                     }

              }

              //判断模式串是否已经完全被匹配,否则返回-1

              if(nPattPos == nPatternLen)

                     return nTextPos - nPattPos;

              else

                     return -1;

       }

}

 

////////////////////////////////////////////////////////////////////////////////

//     函数名称:bool _strlike(

//                          char * chText,

//                          char * chPattern,

//                          int nbegpos )

//     实现功能:两个字符串的匹配算法,带通配符

//     对全局变量的影响:无

//     参数说明:

//            chText                            原字符串

//            chPattern               模式串

//            nbegpos                       起始位置

//     返回结果说明:

//            =true       表示相似或一致

//            =false       表示不相似或不一致

////////////////////////////////////////////////////////////////////////////////

 

bool _strlike(char * chText , char * chPattern , int nbegpos /* = 0 */)

{

       bool bLeftMatch = true , bLast = false;

       int nTextLen = _tcslen(chText);

       //作最基础的匹配,即存在模式串的情况下再作比较

       if(_tcslen(chPattern) == 0)

              if(_tcslen(chText) == 0)

                     return true;

              else

                     return false;

       do

       {

              char * chFirstPattern , * chSecondPattern;

              if(chPattern[0] == '%')

              {

                     do

                     {

                            chPattern ++;

                     }while(chPattern[0] == '%');

                     if(chPattern == NULL || _tcslen(chPattern) == 0)

                            return true;

                     bLeftMatch = false;

              }

              else

                     bLeftMatch = true;

              //初始化模式串

              chSecondPattern = _tcschr(chPattern , '%');

 

              int nPatternLen;

              if(chSecondPattern == NULL)

              {

                     bLast = true;

                     nPatternLen = _tcslen(chPattern);

                     if(!bLeftMatch)

                     {

                            //若以%开头,并且没有剩余模式串时,只要考虑右对齐匹配的方式即可(实际上也是左对齐)

                            if(nbegpos + nPatternLen <= nTextLen)

                            {

                                   nbegpos = nTextLen - nPatternLen;

                                   bLeftMatch = true;

                            }

                            else

                                   return false;

                     }

                     else

                            if(nbegpos + nPatternLen != nTextLen)

                                   return false;

                    

              }

              else

              {

                     //模式串不得长于原串

                     nPatternLen = chSecondPattern - chPattern;

                     if(nbegpos + nPatternLen > nTextLen)

                            return false;

              }

 

              //初始化模式串与修改剩余串

              chFirstPattern = new char[nPatternLen + 1];

              memcpy(chFirstPattern , chPattern , nPatternLen);

              chFirstPattern[nPatternLen] = 0;

              chPattern = chSecondPattern;

 

              int npos = _strat(chText , chFirstPattern , nbegpos , bLeftMatch ? nPatternLen : nTextLen - nbegpos , bLeftMatch);

              delete chFirstPattern;

              if(npos < 0)

              {

                     return false;

              }

              else

              {

                     //定下一查找位置的起点

                     if(bLeftMatch)

                     {

                            if(npos != nbegpos)

                                   return false;

                     }

                     else

                            nbegpos = npos;

                     if(bLast)

                     {

                            if(nPatternLen + npos == nTextLen)

                                   return true;

                            else

                                   return false;

                     }

                     else

                            nbegpos += nPatternLen;

              }

       }while(true);

}

sql中的一些操作符,like,||,以及字符串连接

Like: 如果你想从数据库中选出一部分数据并把它们添到一个模板中并且不需要非常精确的匹 配你可以用= 来对每一种可能的情况进行操作但是这一过程烦琐而又耗时这时 你可以使用LIKE      我...
  • Hell_Android
  • Hell_Android
  • 2013年09月11日 15:01
  • 6912

sql搜索like通配符的用法详解

有很多朋友写了几年的like搜索,可能对like后面通配符的用法都不了解,甚至于%的作用是什么都不清楚。在这篇文章中,我们就一起来学习一下like查询中通配符的用法吧。 我们写的最多的查询语句可...
  • qk5200
  • qk5200
  • 2013年08月06日 10:33
  • 3006

Sql语句中,Contains与Like查询结果不相同的问题

我们知道,要模糊查询数据表的话,一般会用到Like语法,而对数据表相应的字段进行全文索引之后,还可以使用速度更快的Contains方法、 但是,我发现,分别使用这两个方法查询出来的结果不一致! ...
  • caomiao2006
  • caomiao2006
  • 2016年07月30日 23:31
  • 1107

全文索引快的原因以及contains与like查找区别比较

1、中文分词器Chinese_vgram_lexer的属性mixed_case_ascii7可以用来设置是否要区分英文字母的大小写,默认是不区分大小写的,即你在查询中输入“T”还是“t”,都能查到字母...
  • caomiao2006
  • caomiao2006
  • 2016年07月30日 23:28
  • 2766

数据库SQL语句 SELECT LIKE like用法详解

在SQL结构化查询语言中,LIKE语句有着至关重要的作用。 LIKE语句的语法格式是:select * from 表名 where 字段名 like 对应值(子串),它主要是针对字符型字段的,它...
  • u010694337
  • u010694337
  • 2016年09月20日 17:59
  • 4656

请问SQL语句中go有什么作用?

GO Signals the end of a batch of Transact-SQL statements to the Microsoft® SQL Server™ utilities. S...
  • bruno231
  • bruno231
  • 2013年12月24日 02:37
  • 1796

SQL SERVER中的汉字转拼音-实现根据拼音搜索汉字

在项目中,有时需要根据拼音来搜索对应的汉字,找了许多资料,也参考了一些示例,这个sql函数总是解决了这个问题,而且性能是找的资料中最好的。 原理是通过这个函数将中文汉字的字段中的数据转换成拼音,再根...
  • lisky119
  • lisky119
  • 2013年03月12日 11:11
  • 3764

sql语句中where 1=1和1=0的作用

where 1=1和 0=1 的作用 where 1=1; 这个条件始终为True,在不定数量查询条件情况下,1=1可以很方便的规范语句。 一、不用where 1=1 在多条件查询中的困扰   ...
  • u014292162
  • u014292162
  • 2016年07月29日 09:46
  • 3829

【SQL Server性能优化】运用SQL Server的全文检索来提高模糊匹配的效率

今天去面试,这个公司的业务需要模糊查询数据,之前他们通过mongodb来存储数据,但他们说会有丢数据的问题,我从业务上了解到,显然对他们公司而言,丢数是绝对不能允许的。   另外,他们说之前也用过...
  • yupeigu
  • yupeigu
  • 2013年09月04日 19:16
  • 6153

SQL 语句中的通配符

地址:http://blog.sina.com.cn/s/blog_4291fcdb010009ry.html SQL 语句中的通配符 通配符: 通配符 描述 ...
  • anlidengshiwei
  • anlidengshiwei
  • 2014年11月28日 16:27
  • 611
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SQL Server中检索语句中Like的算法实现
举报原因:
原因补充:

(最多只允许输入30个字)