在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))
begin
set @c=substring(@input,@i,1);
if (@c='[' or @c='%' or @c='_')
begin
set @result+='['+@c+']';
end
else
begin
set @result+=@c;
end
set @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

    sql server 字符串替换函数REPLACE函数的使用 <pre name="code" class="sql">--参数1:需要替换字符的母 ...

  2. sql server字符串的类型

    sql server字符串分为不同的类型,下面就将为您介绍几个sql server字符串的常见类型,希望对您学习sql server字符串能有所帮助. nchar 此数据类型可存储1~4000个定长U ...

  3. sql server 字符串转成日期格式

    在SQL Server数据库中,SQL Server日期时间格式转换字符串可以改变SQL Server日期和时间的格式,是每个SQL数据库用户都应该掌握的.本文我们主要就介绍一下SQL Server日 ...

  4. [转]SQL Server字符串处理函数大全

    select语句中只能使用sql函数对字段进行操作(链接sql server), select 字段1 from 表1 where 字段1.IndexOf("云")=1;这条语句不 ...

  5. SQL SERVER字符串函数

    本篇文章还是学习<程序员的SQL金典>内容的记录,此次将讲解的是SQL SERVER的字符串函数. 其实数据库跟程序语言库一样,都会集成很多可以使用的API.这些API,如果你熟悉的话,将 ...

  6. Sql Server 字符串操作总结

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

  7. SQL Server ->> 字符串对比

    今天同事问我关于SQL Server在字符串尾随着空格时进行字符串对比的做法.关于这个问题正好在这里讲一下,就是SQL Server是按照ANSI/ISO SQL-92中的定义做字符串对比的. 在KB ...

  8. sql server 字符串函数大全

    平常会用到一些函数处理字符串,用的不算频繁,所以每次用到的时候就忘记了,这次在网上找了一篇文档,担心突然某一天这篇文章找不到了,然后就把文章的内容复制了一份: /* 1,ASCII返回字符表达式中最左 ...

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

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

随机推荐

  1. setcookie第三个值为什么写0

  2. MySQL Information Functions

    Table 12.18 Information Functions Name Description BENCHMARK() Repeatedly execute an expression CHAR ...

  3. Android 添加桌面快捷方式操作

    /** * 为程序创建桌面快捷方式 */ private void addShortcut(){ Intent shortcut = new Intent(“com.android.launcher. ...

  4. 第 19 章 CSS 其他样式

    学习要点: 1.颜色和透明度 2.盒子阴影和轮廓 3.光标样式 主讲教师:李炎恢 本章主要探讨 HTML5 中 CSS 其他剩下几个常用的样式,包括颜色.透明度.盒子的阴影轮廓以及光标的样式. 一.颜 ...

  5. PMP47个过程的ITO

  6. MUI(5)

    今天实现9宫格菜单.先上效果图: 就是这个效果咯,界面不太美观,底部导航栏是为了苹果用户没有返回按键设计的,只是为了方便演示而已,没有做过多的处理.首先先说一下这个底部导航栏如何实现,这个底部导航栏小 ...

  7. 【转】MyEclipse 2015优化技巧

    MyEclipse 2015优化技巧 MyEclipse 2015优化速度方案仍然主要有这么几个方面:去除无需加载的模块.取消冗余的配置.去除不必要的检查.关闭更新. 第一步: 去除不需要加载的模块 ...

  8. Bootstrap源码分析之transition、affix

    一.Transition(过滤) 作为一个基础支持的组件,被其他组件多次引用.实现根据浏览器支持transition的能力,然后绑定动画的结束事件:首先:创建一个Element:然后:迭代查看此元素支 ...

  9. Sticker.js – 帮助你在网站中加入贴纸效果

    Sticker.js 是一个很小的 JavaScript 库,它允许您在网页中创建漂亮的贴纸效果.没有依赖关系(不需要 jQuery),可以在大多数支持 CSS3 的主流浏览器工作.下面有简单的使用示 ...

  10. Web前端面试题目汇总

    以下是收集一些面试中经常会遇到的经典面试题以及自己面试过程中有一些未解决的问题,通过对知识的整理以及经验的总结,重新巩固自身的前端基础知识,如有错误或更好的答案,欢迎指正,水平有限,望各位不吝指教.: ...