用通配符进行过滤
6.1 LIKE 操作符
普通比较操作符仅能匹配已知精确值,无法实现内容模糊检索:
搜索产品名中包含文本 bean bag的所有产品?
此时需就借助通配符构建搜索模式, 实现字段内容的部分匹配。
- 通配符(wildcard)
- 用来匹配值的一部分的特殊字符。
- 搜索模式(search pattern)
- 由字面值、通配符或两者组合构成的搜索条件。
通配符必须搭配 LIKE 操作符使用,且仅适用于文本字段(字符串),非文本类型字段不可用。
- 谓词(predicate)
- 操作符何时不是操作符?答案是,它作为谓词时。从技术上说,LIKE是谓词而不是操作符。虽然最终的结果相同,但应对此术语有所了解,以免在 SQL文献或手册中遇到此术语时不知所云。
6.1.1 百分号 % 通配符
表示任何字符出现任意次数,可匹配 0 个、1 个及任意多个字符,无数量限制,由原始字符决定;
找出所有以 Fish 起头的产品:
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE 'Fish%'; 注意要点:
部分DBMS 查询区分大小写,’fish%’与 Fish bean bag toy 不匹配。
DBMS 字段尾部填充的空格会干扰匹配结果。
无法匹配值为 NULL 的数据行。
通配符可在搜索模式中的任意位置使用,并且可以使用多个通配符:
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE '%bean bag%'; '%bean bag%'表示匹配任何位置上包含文本 bean bag 的值,不论它之前或之后出现什么字符。
通配符也可以出现在搜索模式的中间,如根据部分信息搜索电子邮件地址:WHERE email LIKE'b%@gmail.com'。下面的例子找出以 F 起头、以 y 结尾的所有产品:
SELECT prod_name
FROM Products
WHERE prod_name LIKE 'F%y'; 说明:请注意后面所跟的空格
有些 DBMS 用空格来填补字段的内容。例如,如果某列有 50个字符,而存储的文本为 Fish bean bag toy(17个字符),则为填满该列需要在文本后附加 33个空格。这样做一般对数据及其使用没有影响,但是可能对上述 SQL 语句有负面影响。
子句 WHERE prod_name LIKE'F%y'只匹配以 F 开头、以 y 结尾的 prod_name。如果值后面跟空格,则不是以 y 结尾,所以 Fish bean bag toy 就不会检索出来。简单的解决办法是给搜索模式再增加一个%号:'F%%' 还匹配 y 之后的字符(或空格)。更好的解决办法是用函数去掉空格。请参阅第 8 课。
6.1.2 下划线 _ 通配符
严格匹配单个字符,数量不可多、不可少
DB2 不支持。
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE '__inch teddy bear'; 说明:请注意后面所跟的空格
与上例一样,可能需要给这个模式添加一个通配符。
这个 WHERE 子句中的搜索模式给出了后面跟有文本的两个通配符。结果只显示匹配搜索模式的行:第一行中下划线匹配 12,第二行中匹配18。8 inch teddy bear 产品没有匹配,因为搜索模式要求匹配两个通配符而不是一个。对照一下,下面的 SELECT 语句使用%通配符,返回三行产品:
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE '% inch teddy bear'; 6.1.3 方括号 [] 通配符
限定字符集合,仅匹配括号内任意单个字符。
仅微软的 SQL Server 支持集合,但 MySQL,Oracle,DB2,SQLite都不支持。
例如,找出所有名字以 J 或 M 起头的联系人,可进行如下查询:
SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE '[JM]%'
ORDER BY cust_contact; 此语句的 WHERE 子句中的模式为'[JM]%'。这一搜索模式使用了两个不同的通配符。[JM]匹配方括号中任意一个字符,它也只能匹配单个字符。因此,任何多于一个字符的名字都不匹配。[JM]之后的%通配符匹配第一个字符之后的任意数目的字符,返回所需结果。
取反用法:搭配^(脱字号)前缀来排除。
例如,下面的查询匹配以 J 和 M 之外的任意字符起头的任意联系人名(与前一个例子相反):
SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE '^JM%'
ORDER BY cust_contact; 当然,也可以使用 NOT 操作符得出类似的结果。^ 的唯一优点是在使用多个 WHERE 子句时可以简化语法:
SELECT cust_contact
FROM Customers
WHERE NOT cust_contact LIKE '[JM]%'
ORDER BY cust_contact; 6.2 使用通配符的技巧
通配符模糊搜索的执行效率低于普通等值查询,数据库处理耗时更长。
不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
尽量避免将通配符放在搜索模式最前端,此写法查询速度最慢。
严格把控通配符摆放位置,防止出现匹配结果偏差。
挑战题
编写 SQL 语句,从 Products 表中检索产品名称(prod_name)和描述(prod_desc),仅返回描述中包含 toy 一词的产品。
反过来再来一次。编写 SQL 语句,从 Products 表中检索产品名称(prod_name)和描述(prod_desc),仅返回描述中未出现 toy 一词的产品。这次,按产品名称对结果进行排序。
编写 SQL 语句,从 Products 表中检索产品名称(prod_name)和描述(prod_desc),仅返回描述中同时出现 toy 和 carrots 的产品。有好几种方法可以执行此操作,但对于这个挑战题,请使用 AND 和两个 LIKE 比较。
来个比较棘手的。我没有特别向你展示这个语法,而是想看看你根据目前已学的知识是否可以找到答案。编写SQL语句,从 Products 表中检索产品名称(prod_name)和描述(prod_desc),仅返回在描述中以先后顺序同时出现 toy 和 carrots 的产品。提示:只需要用带有三个
%符号的 LIKE 即可。