MySQL过滤搜索操作

[TOC]

本文主要介绍MySQL基本的过滤和搜索服务, 包括where子句的过滤操作,in, not in的操作符。更精确地,可以采用like,或者regexp写正则表达式进行匹配。

第六章 过滤数据

想象一下,我们现在有一个学生信息的表,学校要求开展关于少数民族的活动,我们想知道班级里有多少人是少数民族,于是我们需要抽取出民族非汉的所有学生,此时我们利用之前学习的检索是做不到的,这也就是我们接下来要介绍的过滤和搜索服务。

WHERE子句是执行过滤操作的关键字。

口令 用途 备注
SELECT prod_name,prod_price FROM products WHERE prod_price = 2.5; 过滤出prod_price为2.5的列 相等的过滤
=;<>(不等) ; !=(不等) ; < ; > ; <= ; >= ; BETWEEN a AND b 不同的where子句的操作符 BETWEEN的格式注意一下
SELECT prod_name,prod_price FROM products WHERE prod_name = “fuses”; 字符串相等 不区分大小写,也会匹配Fuses
SELECT prod_name,prod_price FROM products WHERE prod_price BETWEEN 5 AND 10; prod_price在5-10之间 包括两个端点处的值
SELECT prod_name FROM products WHERE prod_price IS NULL; 空值检查 注意0,空字符串,空格等都不属于空值

空值的场景,假设是在搜集估计的信息,可能有些顾客不愿意或者没有提供电子邮件或者电话号码,则会出现空值,我们通常会在创建数据库时指定某列是否允许空值。

注意:用其他的过滤条件不会找出具有NULL值的行,因为NULL与其他条件不匹配。

第七章 数据过滤

WHERE子句允许逻辑操作符,不同的WHERE子句用AND或OR进行连接。

口令 用途 备注
SELECT prod_id,prod_name,prod_price FROM products WHERE vend_id=1003 AND prod_price <= 10; AND逻辑操作符,与 集合中的交集操作
SELECT prod_name,prod_price FROM products WHERE vend_id =1002 OR vend_id =1003; OR逻辑操作符,或 集合中的并集操作
SELECT prod_name,prod_price FROM products WHERE vend_id IN (1002,1003) ORDER BY prod_name; IN指定条件范围,括号内所有值可以进行匹配,以逗号分隔 和OR起到的作用一致
SELECT prod_name,prod_price FROM products WHERE vend_id NOT IN (1002,1003) ORDER BY prod_name; NOT用来否定条件

注意:

  • 多使用圆括号操作符改变顺序,不然默认的计算次序AND > OR,有时会不经意间产生错误。所以我们建议多多使用圆括号;
  • IN比OR更清楚直观,执行速度更快;
  • NOT可以用来否定IN, BETWEEN, EXISTS等,注意这只在MySQL。

第八章 用通配符进行过滤

本章介绍如何使用通配符进行复杂过滤。

8.1 什么是通配符

当我们想要获取学生中姓高的学生信息的时候,用之前的检索和过滤操作符就不适用了,因为之前的操作符都是等价匹配,而不会有学生的姓名刚好只有高一个字,而会像高一,高二等,所以我们这章就是利用高来匹配高一高二,这就是通配符或者正则表达式。

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

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

8.2 通配符种类

通配符本身就是WHERE子句中具有特殊含义的字符,为了使用通配符,需要使用LIKE操作符。
这里还有一个谓词的概念,当某个操作符的返回值是TRUE,FALSE,UNKNOWN等时,操作符为谓词。

口令 用途 备注
SELECT prod_id,prod_name FROM products WHERE prod_name LIKE ‘jet%’; %用于任何字符出现任意次数,找出所有以jet开头的prod_name 当然也可以0次
SELECT prod_id,prod_name FROM products WHERE prod_name LIKE ‘%anvil%’; 可以使用多个通配符,anvil在中间的prod_name 因为可以是0次,所以开头或结尾都行
SELECT prod_id,prod_name FROM products WHERE prod_name LIKE ‘s%e’; 以s开头,e结尾的字符
SELECT prodid,prod_name FROM products WHERE prod_name LIKE ton anvil’; 下划线匹配一个字符

注意:%不能匹配NULL值;

8.3 使用通配符的技巧

当我们使用通配符时,需要了解:

  • 通配符搜索花掉的时间更多;
  • 先使用其他操作符,再使用通配符效率会更高;
  • 统配符的位置不要放错。

第九章 用正则表达式进行搜索

正则表达式是用来匹配文本的特殊的集合,比如从文本文件中提取电话号码,邮箱等。MySQL仅支持多数正则表达式的一个很小的子集。

口令 用途 备注
SELECT prod_name FROM products WHERE prod_name REGEXP “1000” ORDER BY prod_name; 检索prod_name包含文本1000的所有行 他是在列值内进行匹配,如果能找到1000,则匹配成功,相当于操作对象为某列某行的字符串;而LIKE则是匹配整个列,而不是看列值是否包含。
SELECT prod_name FROM products WHERE prod_name REGEXP “.000” ORDER BY prod_name; .表示匹配任意一个字符 如果想要区分大小写,可以在REGEXP后加入BINARY
SELECT prod_name FROM products WHERE prod_name REGEXP “1000\ 2000” ORDER BY prod_name; \ 表示或者的关系 匹配1000或者2000
SELECT prod_name FROM products WHERE prod_name REGEXP “[123] ton”ORDER BY prod_name; [123]表示匹配方括号内任一个字符 []和\ 作用类似
SELECT prod_name FROM products WHERE prod_name REGEXP “[\^123] ton”ORDER BY prod_name; ^表示不匹配123之一,起否定作用 文本中有反斜杠,其实不对,应该扔掉,是因为在Markdown中,如果不加反斜杠的话,^会被解释为脚注,只是格式问题
SELECT prod_name FROM products WHERE prod_name REGEXP “[1-5] ton”ORDER BY prod_name; [1-5]匹配1,2,3,4,5任一字符 [a-z]
SELECT prod_name FROM products WHERE prod_name REGEXP “\\.“ORDER BY prod_name; 匹配特殊字符. 用两个转义字符\\匹配特殊字符
  • 假如相匹配 1 ton, 2 ton 或者 3 ton,则需要用”[123] ton”,或者”[1|2|3] ton”,就是不能使用 1|2|3 ton,他会默认是1或者2或者3 ton,从而检索出错。
  • \\f匹配换页,\\n匹配换行,\\r匹配回车,\\t匹配制表,\\v匹配纵向制表

9.1 MySQL的字符类

MySQL具有很多预定义的字符集,称为字符类:

字符类

9.2 匹配多个实例

当你想要匹配一个电话号码的时候,需要匹配11个数字,但如果写出[0-9]重复11次,则显得非常冗余,有没有什么方式可以指定匹配11个数字呢,我们有如下的特殊字符。

元字符 说明
* 匹配任意长度字符,可以为0
+ 至少一个字符
0个或1个
{n} n个
{n,} 至少n个
{n,m} n-m个,m不超过255
^ 文本的开始(在[]内部作否定使用)
$ 文本的结尾
[[:<:]] 词的开始(没有试验成功,不知使用方法)
[[:>:]] 词的结尾

下面我们给出一些示例。

口令 用途 备注
SELECT prod_name FROM products WHERE prod_name REGEXP ‘\\([0-9] sticks?\\)‘ ORDER BY prod_name; \\(\\)使得匹配圆括号;sticks?使得s可有可无
SELECT prod_name FROM products WHERE prod_name REGEXP ‘[[:digit:]]{4}’ ORDER BY prod_name; [:digit:]代表任意数字,{4}代表4次 [:digit:]可以想象成0-9
SELECT prod_name FROM products WHERE prod_name REGEXP ‘^[0-9\\.]’ ORDER BY prod_name; 以数字或者.开头的匹配
SELECT “hello” REGEXP ‘[0-9]’; 返回0 在不调用数据库情况下测试正则表达式