第七章 数据过滤
7.1 组合WHERE子句
在第六章介绍的所有WHERE
子句在过滤时,使用的都是单一的条件。为了进行更强的过滤控制,MySQL允许给出多个WHERE子句,并通过AND
或OR
操作符的方式组合使用。
- 操作符(operator)
用来联接或改变WHERE
子句中关键字,也成为逻辑操作符。
7.1.1 AND操作符
AND
操作符可以使用对多列的条件进行累加过滤。
- 输入:
SELECT prod_id, prod_price, prod_name FROM products WHERE vend_id = 1003 AND prod_price <= 10;
- 输出:略
- 分析:此语句检索由供应商1003制造,且价格小于等于10美元的产品的编号、名称和价格。
AND
操作符“并且”的语意。
7.1.2 OR操作符
OR操作符可以使用对多列的条件进行累加过滤。
- 输入:
SELECT prod_id, prod_price, prod_name FROM products WHERE vend_id = 1002 OR vend_id = 1003;
- 输出:略
- 分析:此语句检索由供应商1002或1003制造的所有产品的编号、名称和价格。
OR
操作符“或者”的语意。
7.1.3 计算次序
WHERE
子句可包含任意数目的AND
和OR
操作符。但是AND
的优先级比OR
高,应使用适当的圆括号分组操作符。
- 输入:
SELECT prod_id, prod_price, prod_name FROM products WHERE (vend_id = 1002 OR vend_id = 1003) AND prod_price >= 10;
- 输出:略
- 分析:此语句检索由供应商为1002,或1003,价格大于等于10美元的所有产品的编号、名称和价格。如果没有加圆括号,则
vend_id = 1003
先和prod_price >= 10
进行AND
操作,再与vend_id = 1002
进行OR
操作,得不到想要的结果。
注意:任何时候都不应该过分依赖默认计算次序,使用圆括号可以增加可读性,消除歧义。
7.2 IN操作符
IN
操作符用来指定条件范围,范围中每个条件都可以进行匹配。IN
的合法值由逗号分隔,并全部括在圆括号中。
- 输入:
SELECT prod_id, prod_price, prod_name FROM products WHERE vend_id IN (1002,1003);
- 输出:略
- 分析:此语句检索由供应商1002或1003制造的所有产品的编号、名称和价格。所完成的功能与
OR
类似。
使用IN
的优点为:
- 在使用长的合法选项清单时,IN操作符的语法更清楚更直观。
-
IN
操作符比OR
操作符清单执行更快 -
IN
操作符最大的优点是可以包含其他SELECT
语句(将在14章说明),能够更动态地建立WHERE
子句。
7.3 NOT操作符
WHERE子句中的NOT操作符有且只有一个功能,就是否定它之后的任何条件。
- 输入:
SELECT prod_id, prod_price, prod_name FROM products WHERE vend_id NOT IN (1002,1003);
- 输出:略
- 分析:此语句检索由供应商1002或1003以外供应商提供的所有产品的编号、名称和价格。
注意:MySQL支持使用NOT对IN、BETWEEN和EXISTS子句取反,这与其他大多数DBMS允许使用NOT对各种条件取反有很大区别。
第八章 使用通配符进行过滤
8.1 LIKE操作符
之前介绍的都是针对已知值的过滤。而对进行未知内容的匹配,可以使用通配符创建比较数据的搜索模式来完成。通配符的匹配,需要通过LIKE操作符指示MySQL完成。
通配符
用来匹配值的一部分的特殊字符。搜索模式
由字面值、通配符或两者组合成的搜索条件。谓词
从技术上说,LIKE
是谓词而不是操作符,虽然结果是相同的,但是需要明白此术语。
8.1.1 百分号(%)通配符
%
表示任何字符出现任意次。例如,为了找到所有以 jet
起头的产品,可使用以下SELECT
语句
- 输入:
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE 'jet%';
- 输出:略
- 分析:此例子使用了搜索模式
'jet%'
,它告诉MySQL接受jet
之后任意字符,不管有多少字符。
注意:
-
%
通配符可放在搜索模式的任意位置,例如'%anvil%'
表示匹配任何位置包含anvil
的字符;'s%e'
表示以s开头以e结尾的字符。 -
%
除了可以匹配一个或者多个字符外,还可以匹配0个字符。%代表给定位置的0、1或多个字符。 - 尾空格将影响匹配结果:
'%anvil '
将匹配不到anvil_Blank
。 -
WHERE prod_name LIKE '%'
也无法匹配NULL值作为产品名的行。
8.1.2 下划线(_)通配符
下划线(_
)通配符只匹配单个字符而不是多个字符。
- 输入:
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '_ ton anvil';
- 输出:略
- 分析:此例子使用了搜索模式
'_ ton anvil'
,它能够匹配1 ton anvil
和2 ton anvil
,但不能匹配.5 ton anvil
,因为下划线通配符只对应一个字,不可多也不能少 。
通配符使用技巧:
- 通配符的处理通常比值匹配花费的时间更多。不要过度使用通配符,能够用其他操作符达到同样目的时,应使用其他操作符。
- 除非确实有必要,否则尽量不要在模式搜索开始时使用通配符,否则速度尤其慢。
- 仔细注意通配符的位置,错误的位置将得不到想要的结果。
第九章 使用正则表达式进行搜索
9.1 正则表达式介绍
正则表达式是用来匹配文本的特殊串(字符集合),所有种类的程序设计语言、文本编辑器、操作系统等都支持正则表达式。
9.2 使用MySQL正则表达式
MySQL中的正则表达式仅是正则表达式的一个子集。
9.2.1 基本字符匹配
输入:
SELECT prod_name FROM products WHERE prod_name REGEXP '1000';
输出:略
分析:除关键词字
LIKE
被REGEXP
替代外,这条语句看上去非常像LIKE
语句,但不同在于LIKE
匹配整个行,REGEXP
在列值中进行匹配,如果被匹配的值在文本中出现则匹配成功。因此,对于以上输入,REGEXP
可以匹配到Jet 1000
,但LIKE
则匹配不到。REGEXP
可以通过定位符的使用,来匹配整个行,将在9.2.8中介绍定位符。输入:
SELECT prod_name FROM products WHERE prod_name REGEXP '.000';
输出:略
分析:这里使用了正则表达式
'.000'
。.
是正则表达式语言中一个特殊的字符。它表示匹配任意一个字符。因此JetPack 1000·
和JetPack 2000
都可以匹配返回。
9.2.2 进行OR匹配
为搜索两个串之一,使用(|
)。
- 输入:
SELECT prod_name FROM products WHERE prod_name REGEXP '1000|2000' ORDER BY prod_name ;
- 输出:略
- 分析:这里使用了正则表达式
'1000|2000'
。|
是正则表达式语言中的OR操作符。另外,|
还支持两个以上的条件,例如'1000|2000|3000'
。
9.2.3 匹配几个字符之一
如果想匹配特定的单一字符,可以使用[]将一组指定的内容括起来。
- 输入:
SELECT prod_name FROM products WHERE prod_name REGEXP '[123] ton' ORDER BY prod_name ;
*输出:略
分析:这里使用了正则表达式'[123] ton'
。[123]
定义一组字符,意为匹配1、2或3。因此,1 ton
、2 ton
、3 ton
都能匹配。[]是另一种形式的OR语句。
注意:
- 事实上,
'[123] ton'
是'[1|2|3] ton'
的缩写,也可以使用后者。 -
WHERE prod_name REGEXP '1|2|3 ton'
并不能得到想要的答案,因为被MySQL理解为'1'
或'2'
或‘3 ton’
。 - 字符集也可用于否定,只需要在集合开始处放置一个
^
即可。例如[^123]
可以匹配'1'
、'2'
、'3'
以外的其他字符。
9.2.4 匹配范围
集合可用来定义要匹配一个或多个字符,此时可以使用-
来定义一个范围,例如[0-9]
表示数字0到9,[a-z]
表示字母a到z。
- 输入:
SELECT prod_name FROM products WHERE prod_name REGEXP '[1-5] ton' ORDER BY prod_name ;
- 输出:略
- 分析:这里使用了正则表达式
'[1-5] ton'
。[1-5]
定义了一个范围,表示数字1到5。
9.2.5 匹配特殊字符
正则表达式语句由具有特定含义的特殊字符构成。例如|
或-
等。如果要表示一些特殊的字母,如含.
的值,则应该使用\\\
为前导。\\\-
表示查找-
,\\\.
表示查找.
。
- 输入:
SELECT prod_name FROM products WHERE prod_name REGEXP '\\\.' ORDER BY prod_name ;
- 输出:略
- 分析:这里使用了正则表达式
'\\\.'
,可以顺利匹配到.
。这种处理方式就是所谓的转义,正则表达式内具有特殊意义的所有字符都需要转义。包括. | [ ]
等,\\\\
也用来引用元字符,如下:
注意:
- 为匹配
\\
应使用\\\\\
。 - 多数正则表达式实现单个反斜杆转义特殊字符。但MySQL要求两个反斜杆(MySQL自己解释一个,正则表达式解释一个)。
9.2.6 匹配字符类
为方便常见字符集的查找,可以使用预定义的字符集。称为字符类。如下图所示:
9.2.7 匹配多个实例
目前为止使用的所有正则表达式都试图匹配单词出现。但有时需要对匹配的数目进行更强的控制,此时可以使用下列正则表达式重复元字符来完成。
输入:
SELECT prod_name FROM products WHERE prod_name REGEXP '\\\([0-9] sticks?\\\)' ORDER BY prod_name ;
输出:略
分析:这里使用了正则表达式'\\\([0-9] sticks?\\\)'
,?
表示,它前面的字母s出现0次或1次。输入:
SELECT prod_name FROM products WHERE prod_name REGEXP '[[:digit:]]{4}' ORDER BY prod_name ;
输出:略
分析:这里使用了正则表达式
'[[:digit:]]{4}'
,表示匹配连在一起的四位数字。
注意:使用正则表达式时,编写某个特定的表达式几乎总是有多种方法。
9.2.8 定位符
目前为止,所有例子都是匹配一个串中任意位置的文本,为了匹配特定位置的文本,需要使用定位符。
- 输入:
SELECT prod_name FROM products WHERE prod_name REGEXP '^[0-9\\.]' ORDER BY prod_name ;
- 输出:略
- 分析:
^
匹配串的开始,'^[0-9\\\.]'
表示匹配以数字或.
开始的串。
注意:
- ^有两个用法,在集合中(用
[]
定义),用来表示几何的否定,在集合外,用来表示串的起始。 -
REGEXP
用来匹配子串,LIKE用来匹配整个串,REGEXP
用^
做开头,用$
为结束时,作用与LIKE
相同。 - 可在不使用数据库的情况下,对正则表达式做简单测试,
REGEXP
检查总是返回0或1,后者表示匹配成功。例如:SELECT 'hello' FROM ‘[0-9]';
将返回0。