SQL Server字符串左匹配
在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字符串左匹配的更多相关文章
- sql server 字符串替换函数REPLACE
sql server 字符串替换函数REPLACE函数的使用 <pre name="code" class="sql">--参数1:需要替换字符的母 ...
- sql server字符串的类型
sql server字符串分为不同的类型,下面就将为您介绍几个sql server字符串的常见类型,希望对您学习sql server字符串能有所帮助. nchar 此数据类型可存储1~4000个定长U ...
- sql server 字符串转成日期格式
在SQL Server数据库中,SQL Server日期时间格式转换字符串可以改变SQL Server日期和时间的格式,是每个SQL数据库用户都应该掌握的.本文我们主要就介绍一下SQL Server日 ...
- [转]SQL Server字符串处理函数大全
select语句中只能使用sql函数对字段进行操作(链接sql server), select 字段1 from 表1 where 字段1.IndexOf("云")=1;这条语句不 ...
- SQL SERVER字符串函数
本篇文章还是学习<程序员的SQL金典>内容的记录,此次将讲解的是SQL SERVER的字符串函数. 其实数据库跟程序语言库一样,都会集成很多可以使用的API.这些API,如果你熟悉的话,将 ...
- Sql Server 字符串操作总结
SQL Server 支持两种字符数据类型---常规和Unicode:常规类型包括char 和varchar:unicode包括nchar 和nvarchar.常规的每个字符占用一个字节存储,而uni ...
- SQL Server ->> 字符串对比
今天同事问我关于SQL Server在字符串尾随着空格时进行字符串对比的做法.关于这个问题正好在这里讲一下,就是SQL Server是按照ANSI/ISO SQL-92中的定义做字符串对比的. 在KB ...
- sql server 字符串函数大全
平常会用到一些函数处理字符串,用的不算频繁,所以每次用到的时候就忘记了,这次在网上找了一篇文档,担心突然某一天这篇文章找不到了,然后就把文章的内容复制了一份: /* 1,ASCII返回字符表达式中最左 ...
- SQL SERVER 字符串函数 STRING_SPLIT()
定义: STRING_SPLIT()函数根据指定的分隔符将字符串拆分为子字符串行. ※STRING_SPLIT 要求兼容性级别至少为 130. (即SSMS 2016及以上版本) ※级别低于 130 ...
随机推荐
- An Introduction to Stored Procedures in MySQL 5
https://code.tutsplus.com/articles/an-introduction-to-stored-procedures-in-mysql-5--net-17843 MySQL ...
- Hack语言特性之类型化
Hack最基础的特性就是类型标注.PHP5已经开始支持对象的类型化,PHP7也提供了标量类型化声明.Hack提供了全面的类型标注支持,与其typecher配合使用,还可以实现快速.前置静态类型验证. ...
- 项目总结笔记系列 Maven Session1
主题:Maven 参考地址: 1.http://www.yiibai.com/maven/ 2.http://www.icoolxue.com/ 目录 1.环境搭建 2.pom.xml文件解析 3.m ...
- spring入门(一)
前面介绍了spring环境的搭建,在搭建spring环境的时候分为java环境和javaWeb环境,在javaWeb环境下通常会结合springMVC使用,在java项目中只需要把spring的包导入 ...
- According to TLD or attribute directive in tag file, attribute end does not accept any expressions
问题描述: 在 JSP 页面中使用 JSTL 标签库,访问 JSP 页面时抛出了如下异常信息: org.apache.jasper.JasperException: /WEB-INF/manageUs ...
- ubuntu 14.04 解决JavaMelody 图片中文乱码
从windows系统中,copy了MSYH.TTC和MSYHBD.TTC 2个文件到 服务器的%JAVA_HOME%\jre\lib\fonts\fallback 目录中, (如果fallback目录 ...
- 来自 Codrops 的7种创新的拖放交互界面
Codrops 分享了一些界面拖放的交互设计想法.基本的思路是在拖动一个项目的时候,为特定的操作呈现出可投掷的区域.这节省了大量的界面空间 ,并给出了一个有趣的动态的互动.有很多应用场景,例如分类和组 ...
- [原创]html5游戏_贪吃蛇
代码随便写写,尚有许多不足,PC与手机端皆可运行 手机端滑屏操作,PC端方向键操作 疑问: 生成食物,与判断是否可以移动方面 有两种实现方式, 1.使用js内存,数组循环判断 2.使用dom的quer ...
- JavaScript实战-菜单特效
以下是我自己用原生JS写的各种菜单特效,虽然网上一搜一大堆,但我还是喜欢自己来写一写! 这是上一篇:JavaScript实战(带收放动画效果的导航菜单) 下面是经过优化后的完整代码,优化了CSS样式. ...
- JavaScript学习笔记-正则表达式(语法篇)
正则表达式的模式规则是由一个字符系列组成的,包括所有字母和数字在内;大多数的字符(所有字母和数字)都是按字符的直接量来描述带匹配的字符;一些具有特殊语义的字符按照其特殊语义来进行匹配,有些字符需要通过 ...