在SQL Server中经常会用到模糊匹配字符串的情况,最简单的办法就是使用like关键字(like语法http://msdn.microsoft.com/en-us/library/ms179859.aspx)。但是如果我们使用的前后都加%的方式,是没办法用到索引进行快速查询的,所以很多情况下我们使用左匹配的方式。最常见的一个例子就是在搜索框中,用户输入了一部分关键字,系统可以通过用户的输入进行左匹配,找出相关的结果列出来。使用左匹配的好处是可以使用到SQL Server中对该字段建立的索引,使得查询效率很高,但是不好的SQL语句仍然会导致索引无法使用。

假设我们现在有个表YCMRSALE,其中有个字段MATNR存储了料号信息,如果我们要从这个表中查询出以AB开头的料号,如果使用NHibernate,那么我们常用的写法有:

//QueryOver的写法
var result = session.QueryOver<Ycmrsale>().WhereRestrictionOn(c => c.Matnr).IsLike("AB", MatchMode.Start).List<Ycmrsale>();
//Linq to NHibernate
result = session.Query<Ycmrsale>().Where(c => c.Matnr.StartsWith("AB")).ToList();
//Criteria写法
result = session.CreateCriteria<Ycmrsale>().Add(Expression.Like("Matnr", "AB", MatchMode.Start)).List<Ycmrsale>();

这几种写法本质上都是生成了如下的where条件语句:

where ycmrsale0_.Matnr like 'AB%'

如果使用EntityFramework,那么查询的C#代码也和NHibernate类似:

var result = bwEntities.YCMRSALEs.Select(s => s.MATNR).Where(s => s.StartsWith("AB"));

where条件也是一样的:

WHERE [Extent1].[MATNR] LIKE 'AB%'

这里只是举了最简单的情况,如果我们要查询的料号本身就包含%,比如要查询以”%00”开头的料号,那么怎么保证这里的%是百分号而不是表示模糊匹配的意思呢?

使用EntityFramework就很简单,什么都不需要修改,系统会根据传入的字符串生成不同的SQL语句:

var result = bwEntities.YCMRSALEs.Select(s => s.MATNR).Where(s => s.StartsWith("%00"));

生成的SQL Where条件:

WHERE [Extent1].[MATNR] LIKE '~%00%' ESCAPE '~'

对开发人员来说,真是很简单,什么输入都不用管。但是如果用NHibernate就要麻烦点了,我们必须要判断用户输入的字符串里面是否有特殊转移符,如果有,那么就需要进行替换,而且C#查询语句也有所不同。

string input = "%00";
Regex regex=new Regex(@"[~%\[\]_]");
input= regex.Replace(input, delegate(Match m) { return "~" + m.Value; });
var result = session.QueryOver<Ycmrsale>().WhereRestrictionOn(c => c.Matnr).IsLike(input, MatchMode.Start,'~').List<Ycmrsale>();
生成的SQL Where条件:
WHERE this_.Matnr like @p0 escape '~';@p0 = '~%00%'

以上说的都是在ORMapping的工具中进行左匹配查询,如果我们要在SQL语句中直接进行查询还有一种写法就是用left函数。同样以YCMRSALE表举例,如果我们有另一表matnr,该表中的matnr列存储了不完整的料号,现在需要将两个表join起来,使用matnr列进行左匹配,那么我们的SQL可以写成:

select *
from YCMRSALE s
inner join matnr m
on left(s.MATNR,len(m.matnr))=m.matnr

这个写法能够得到我们想要的结果,但是由于对MATNR列使用了函数,所以无法使用索引,所以查询速度很慢。

如果我们要改写成like的形式,那么就需要对matnr表中的matnr列进行处理,将特殊字符进行替换,将~%_[]这几个字符都替换掉。所以我们的SQL查询就会变成这样:

select *
from YCMRSALE s
inner join matnr m
on s.MATNR like replace(replace(replace(replace( replace(m.matnr,'~','~~'),'_','~_'),'[','~['),']','~]'),'%','~%')+'%' escape '~'

这里的SQL虽然看起来比较Ugly,但是却可以用上YCMRSALE表上对MATNR建立的索引,所以效率较高。

除了ESCAPE这个关键字的处理方式外,微软官方还给出了另一种解决办法,那就是使用“[]”将转义字符括起来。这种写法比escape关键字的写法要简单点,对应的SQL为:

select *
from YCMRSALE s
inner join matnr m
on s.MATNR like replace(replace(replace( m.matnr,'[','[[]'),'_','[_]'),'%','[%]')+'%'

甚至我们还可以先写个自定义函数对转移字符进行处理对于join的情况,那就非常复杂了。。。

create function OpStr(@input varchar(50))
returns varchar(100)
as
begin
declare @i int=1;
declare @result varchar(100)='';
declare @c char(1)
while(@i<=len(@input))
beginset @c=substring(@input,@i,1);if (@c='[' or @c='%' or @c='_')beginset @result+='['+@c+']';endelsebeginset @result+=@c;endset @i+=1;
end
return @result
end
然后在查询中调用这个自定义的函数即可。
select *
from YCMRSALE s
inner join matnr m
on s.MATNR like dbo.OpStr(m.matnr)+'%'

SQL Server字符串左匹配相关推荐

  1. sql server字符串替换函数REPLACE

    使用REPLACE(替换字符串)函数REPLACE函数将字符串中的子字符串替换为指定字符串. 语法: REPLACE (string_expression1, string_expression2, ...

  2. Sql Server 字符串操作总结

    SQL Server 支持两种字符数据类型---常规和Unicode:常规类型包括char 和varchar:unicode包括nchar 和nvarchar.常规的每个字符占用一个字节存储,而uni ...

  3. SQL Server 字符串操作

    为什么80%的码农都做不了架构师?>>>    ... 参考文档 [官方]LEFT (Transact-SQL) [官方]RIGHT (Transact-SQL) [官方]SUBST ...

  4. Sql Server 字符串、日期函数 收藏

    /**//*************************************************************************** DATEPART 返回代表指定日期的指 ...

  5. Sql Server 字符串、日期函数

    /**//*************************************************************************** DATEPART 返回代表指定日期的指 ...

  6. SQL Server字符串聚合拼接列值合并

    STUFF字符串函数是将字符串插入到另一个字符串中.它会删除开始位置第一个字符串中的指定长度的字符,然后将第二个字符串插入到开始位置的第一个字符串中,语法如下: STUFF(字符串/变量/列,开始位置 ...

  7. SQL SERVER 字符串函数 STRING_SPLIT()

    定义: STRING_SPLIT()函数根据指定的分隔符将字符串拆分为子字符串行. ※STRING_SPLIT 要求兼容性级别至少为 130. (即SSMS 2016及以上版本) ※级别低于 130 ...

  8. Sql Server字符串函数

    字符串函数用于对字符和二进制字符进行各种操作 1.ASCII()函数  ASCII(character_expression)函数用于返回字符串表达式中最左侧的ASCII代码值.参数character ...

  9. sql server 字符串转table

    -- ============================================= -- Author: gengc -- Create date: <2012-12-29> ...

最新文章

  1. Cloud Control 13c 13.3安装(二) agent 部署
  2. 众方网络电话VOIP FREEGO EIS系统命令
  3. 如何防止空链接,跳转到网页顶端
  4. java 记事本换行_[求助]记事本自动换行
  5. Java高级语法笔记-反射机制(Reflection) (1)
  6. uglifyjs报错 webpack_vue使用uglifyjs-webpack-plugin后打包报错
  7. 随想录(为什么循环队列具有先天的并行性)
  8. Graphics 单元中的类
  9. Push消息如何测试?
  10. keil窗口显示不全_使用Keil语言的嵌入式C编程教程(下)
  11. 2 Linux磁盘管理
  12. 【图像增强】基于matlab暗通道图像去雾【含Matlab源码 1226期】
  13. python实现协同过滤算法
  14. CentOS 6.5 Thinkpad 小红点(TrackPoint)设置
  15. 【原创】Python 使用jmpy模块加密|加固 python代码
  16. CSS简单实现一个箭头
  17. Pandas RuntimeWarning: More than 20 figures have been opened. Figures created plt.close()也不起作用
  18. 用Java写PTA 7-11 设计一个能处理异常的Loan类
  19. 华为网络技术学习打卡8(云计算大数据,openstack,docker)
  20. C++/JAVA 计算两篇文章的相似度

热门文章

  1. 在主线程执行_深入理解JavaScript执行机制
  2. bootstrap列高度_如何使Bootstrap列都具有相同的高度?
  3. python猫狗大战pytorch_深度学习实战---猫狗大战(pytorch实现)
  4. 红帽企业linux 6.4 64位上实现mysql 5.6主从复制_红帽企业Linux 6.4 64位上实现MySQL 5.6主从复制...
  5. c语言读取txt第二行数值,c语言读取文件的第二行
  6. 计算机操作员技术工作总结,计算机操作员工作总结
  7. oracle中累计求和_Excel中常见的7种求和公式
  8. sql server 比较大小
  9. BOMTool更新到1.3.0.10
  10. 谁是“顶会狂魔”?周明、张潼等上榜,清华第四,北大第六 | 2018 ML和NLP顶会论文统计出炉...