上一节介绍的过滤数据的方式都是在已知条件下,例如知道生产商的ID,价格的范围等等,但是有的时候我们只知道部分条件,上一节的操作符就不起作用了,所以需要使用通配符以及正则表达式来进行更复杂的过滤。

本节对应《Mysql必知必会》八、九章

用通配符进行过滤

通配符(wildcard)  用来匹配值的一部分的特殊字符

搜索模式(search  pattern)  由字面值、通配符或两者组合构成的搜索条件。

LIKE操作符

为在搜索子句中使用通配符,必须使用LIKE操作符。LIKE指示MySQL后跟的搜索模式利用通配符匹配而不是直接相等匹配进行比较。

百分号( % )通配符

#查找以jet开头的产品名的相关信息
select prod_id,prod_name,prod_price from products where prod_name like 'jet%';

mysql sum 带过滤条件 mysql数据过滤_正则表达式

% 表示Mysql接受jet后面的任何字符

通配符可在搜索模式中任意位置使用,并且可以使用多个通配符

#查询产品名中包含 anvi 的产品信息
select prod_id,prod_name,prod_price from products where prod_name like '%anvi%';

mysql sum 带过滤条件 mysql数据过滤_mysql sum 带过滤条件_02

只要注意%可以代表0个、1个或多个字符,但是不能匹配NULL

下划线( _ )通配符

下划线( _ )也是匹配字符,但是只能匹配一个字符

#查找以 ton anvil结尾的产品
select prod_id,prod_name from products where prod_name like '% ton anvil';

mysql sum 带过滤条件 mysql数据过滤_mysql sum 带过滤条件_03

下面用下划线测试一下

select prod_id,prod_name from products where prod_name like '_ ton anvil';

mysql sum 带过滤条件 mysql数据过滤_mysql sum 带过滤条件_04

可以看出 .5 ton anvil没有查询出来,是因为下划线只匹配单个字符

使用通配符的技巧

通配符虽然好用但是效率很低,所以能不用就不用,下面给出几条使用技巧

1.不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。

2.在确实需要使用通配符时,除非绝对有必要,否则不要把它们用在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起来是最慢的。

3.仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据。

用正则表达式进行搜索

正则表达式在各个程序设计语言、文本编辑器,操作系统都有,用正则表达式进行字符串匹配十分方便,但是Mysql只支持正则表达式的子集。

基本字符匹配

#查询产品名包含1000的产品信息
select prod_name,prod_price from products where prod_name regexp '1000' order by prod_name;

mysql sum 带过滤条件 mysql数据过滤_搜索_05

REGEXP表示后面跟的是正则表达式,需要注意的是regexp和like是不一样的,下面看个例子

select prod_name,prod_price from products where prod_name like '1000' order by prod_name;

mysql sum 带过滤条件 mysql数据过滤_字符串_06

可以看到查询结果为空,原因是like是精准匹配,找的是产品名是 '1000',而regexp表示名字中包含字符串 '1000'

上面提到下划线( _ )表示任意一个字符,正则表达式中则是用点( . )

#查询商品名中包含000的商品信息
select prod_name,prod_price from products where prod_name regexp '.000' order by prod_name;

 

mysql sum 带过滤条件 mysql数据过滤_mysql sum 带过滤条件_07

可以看出1000和2000都匹配上了

注:Mysql默认正则表达式也是不区分大小写的,如果需要区分大小写需要加BINARY关键字

#查询商品名中包含JetPack 000的商品信息
select prod_name,prod_price from products where prod_name regexp binary 'JetPack .000' order by prod_name;

mysql sum 带过滤条件 mysql数据过滤_搜索_08

如果换成小写

#查询商品名中包含JetPack 000的商品信息
select prod_name,prod_price from products where prod_name regexp binary 'jetpack .000' order by prod_name;

mysql sum 带过滤条件 mysql数据过滤_mysql sum 带过滤条件_09

结果为空

进行OR匹配

为了搜索多个字符串之一,使用 | ,表示逻辑或

#查询商品名中包含1000或2000的商品信息
select prod_name,prod_price from products where prod_name regexp '1000|2000';

mysql sum 带过滤条件 mysql数据过滤_搜索_10

匹配几个字符之一

用 [ 和 ] 表示多个候选

#查询产品名包含 1 Ton 、 2 Ton 、 3 Ton 的产品信息
select prod_name,prod_price from products where prod_name regexp '[123] Ton' order by prod_name;

mysql sum 带过滤条件 mysql数据过滤_正则表达式_11

[123]表示的是[1|2|3],相当于OR,但需要特别注意 '[123] Ton'不要写成了'1|2|3 Ton',后者表示匹配1或2或3 Ton

select prod_name,prod_price from products where prod_name regexp '1|2|3 Ton' order by prod_name;

mysql sum 带过滤条件 mysql数据过滤_正则表达式_12

字符串集合也可以被否定,例如[^123]表示匹配除1 2 3之外的字符

#查询产品名不包含 1 Ton 、 2 Ton 、 3 Ton 的产品信息
select prod_name,prod_price from products where prod_name regexp '[^123] Ton' order by prod_name;

mysql sum 带过滤条件 mysql数据过滤_mysql sum 带过滤条件_13

匹配范围

[0-9]表示[0123456789],为了简化表示,用 - 表示范围,[a-z]表示任意字母字符

#查询1-5 Ton的产品信息
select prod_name,prod_price from products where prod_name regexp '[1-5] Ton';

mysql sum 带过滤条件 mysql数据过滤_字符串_14

匹配特殊字符

有些特殊字符例如 '.' ,是不能直接匹配的,举个例子

#想查找供应商名字包含.的,但实际结果不对
select vend_name from vendors where vend_name regexp '.' order by vend_name;

mysql sum 带过滤条件 mysql数据过滤_字符串_15

'.' 表示任意字符,所以所有行都被匹配出来了

为了匹配特殊字符,需要用 \\ 来进行转义,需要注意的是高级语言一般用一个 \ 表示转义,mysql是两个

select vend_name from vendors where vend_name regexp '\\.' order by vend_name;

mysql sum 带过滤条件 mysql数据过滤_搜索_16

如果需要匹配 \ ,需要用 \\\

\\ 也可以用来引用元字符(具有特殊含义的字符)

元字符

说明

\\f

换页

\\n

换行

\\r

回车

\\t

制表

\\v

纵向制表

匹配多个实例

上面的匹配都是单次出现,现在用正则表达式重复元字符来完成

元字符

说明

*

0个或多个匹配

+

1个或多个匹配(等于{1,})

?

0个或1个匹配(等于{0,1})

{n}

指定数目n的匹配

{n,}

不少于指定数目的匹配

{n,m}

匹配数目的范围(m不超过255)

举个例子

select prod_name from products where prod_name regexp '\\([0-9] sticks?\\)' order by prod_name;

mysql sum 带过滤条件 mysql数据过滤_字符串_17

这个sql语句的意思是找出产品名字中包含格式为 (数字 stick或sticks) 的产品名

\\( 和 \\) 对应的是括号,[0-9]表示的是任意一个数字,sticks?表示最后的字母s出现0次或1次

另一个例子,匹配连在一起的四位数字

select prod_name from products where prod_name regexp '[[:digit:]]{4}' order by prod_name;

mysql sum 带过滤条件 mysql数据过滤_正则表达式_18

[:digit:]表示[0-9],{4}表示出现四次,所以是任意一个四位数字

上述sql语句与下面的sql语句等价

select prod_name from products where prod_name regexp '[0-9][0-9][0-9][0-9]' order by prod_name;

定位符

上面的都是匹配任意位置的文本,现在学习匹配特定位置的文本

定位元字符

说明

^

文本的开始

$

文本的结尾

[[:<:]]

词的开始

[[:>:]]

词的结尾

举个例子,我们现在想找以数字(或小数点开始的数)开始的所有产品,假如用[0-9\\.]来匹配

select prod_name from products where prod_name regexp '[0-9\\.]';

mysql sum 带过滤条件 mysql数据过滤_正则表达式_19

结果发现并不是我们想要的结果,后面四条结果是错误的

所以需要用 ^[0-9\\.]来进行匹配,它的意思是只有开始是数字或小数点开始的数字才会匹配

select prod_name from products where prod_name regexp '^[0-9\\.]';

mysql sum 带过滤条件 mysql数据过滤_mysql sum 带过滤条件_20

需要注意的是 ^ 有两个用途,集合里面( [和] )表示否定该集合,否则是表示字符串的开始

可以在不使用数据库的情况下用SELECT来测试正则表达式,REGEXP匹配上返回1,否则返回0

select 'hello' regexp '[0-9]';

mysql sum 带过滤条件 mysql数据过滤_字符串_21

hello字符串里面没有数字,所以返回0

下一节讲述创建计算字段和使用数据处理函数