MySQL LIKE 运算符
本章重点介绍如何在 MySQL 中使用 LIKE 运算符对字符串数据进行模式匹配。虽然之前章节中的 WHERE 子句允许使用 =, >, 或 < 等运算符进行精确匹配或比较,但 LIKE 运算符提供了一种灵活的方式来搜索匹配指定模式的数据,而不仅仅是完全相同的值。这对于查询基于文本的信息至关重要,因为你可能不知道确切的内容,但对其结构或部分内容有所了解。
1. LIKE 运算符简介
LIKE 运算符在 WHERE 子句中使用,用于在列中搜索指定的模式。当你需要查找字符串列包含特定字符序列、以特定字母开头、以特定后缀结尾或在特定位置具有特定字符的行时,它特别有用。LIKE 运算符与通配符 (wildcard characters) 结合使用来定义这些模式。
MySQL 支持两个主要的通配符与 LIKE 一起使用:
%(百分号):代表零个、一个或多个字符。_(下划线):代表单个字符。
2. 百分号 (%) 通配符
% 通配符作为任何零个或多个字符序列的占位符。它用途广泛,可以用在模式的开头、结尾或中间。
2.1 % 通配符使用示例
为了演示,我们使用 world 数据库中的 City(城市)表,其中包含城市名称。
1. 查找以特定序列开头的字符串:
SELECT
Name,
CountryCode,
District
FROM
world.city
WHERE
Name LIKE 'Lon%'; -- 查找名称以 'Lon' 开头的城市这个查询会检索出如 'London'(伦敦)、'Long Beach'(长滩)、'Longueuil'(朗基尔)等任何以 "Lon" 开头的城市名称,无论后面跟着什么字符。
2. 查找以特定序列结尾的字符串:
SELECT
Name,
CountryCode,
District
FROM
world.city
WHERE
Name LIKE '%ville'; -- 查找名称以 'ville' 结尾的城市这个查询将返回如 'Jacksonville'(杰克逊维尔)、'Louisville'(路易斯维尔)、'Nashville'(纳什维尔)等名称以 "ville" 结尾的城市。
3. 查找在任何位置包含特定序列的字符串:
SELECT
Name,
CountryCode,
District
FROM
world.city
WHERE
Name LIKE '%burg%'; -- 查找名称中任何位置包含 'burg' 的城市这个查询将匹配 'Hamburg'(汉堡)、'St. Petersburg'(圣彼得堡)、'Edinburgh'(爱丁堡)以及任何在任何位置包含 "burg" 序列的城市名称。
4. 查找以特定序列开头和结尾的字符串:
SELECT
Name,
CountryCode,
District
FROM
world.city
WHERE
Name LIKE 'San %isco'; -- 查找名称以 'San ' 开头且以 'isco' 结尾的城市这个特定模式 San %isco 主要会匹配 'San Francisco'(旧金山),因为 % 允许 "San " 和 "isco" 之间存在任何字符。
3. 下划线 (_) 通配符
_ 通配符充当单个字符的占位符。当你需要匹配特定字符位置未知或可变,但字符串片段长度固定的模式时,它非常有用。
3.1 _ 通配符使用示例
使用 world.city 表:
1. 查找具有特定字符数的字符串:
SELECT
Name,
CountryCode,
District
FROM
world.city
WHERE
Name LIKE '____'; -- 查找名称正好是四个字符长的城市这个查询将返回如 'Rome'(罗马)、'Oslo'(奥斯陆)、'Bern'(伯尔尼)、'Lima'(利马)、'Doha'(多哈)等正好由四个字符组成的城市名称。
2. 查找在已知位置具有特定字符的字符串:
SELECT
Name,
CountryCode,
District
FROM
world.city
WHERE
Name LIKE 'P_ris'; -- 查找名称以 'P' 开头,后跟任意单个字符,然后是 'ris' 的城市这个查询将匹配 'Paris'(巴黎),因为下划线专门占据了 'a' 字符的位置。它不会匹配 'Pariss' 或 'P_aris',这突出了 _ 的单字符限制。
3. 组合使用 _ 和 % 通配符:
SELECT
Name,
CountryCode,
District
FROM
world.city
WHERE
Name LIKE '_l%nd'; -- 查找名称的第二个字母是 'l' 并且以 'nd' 结尾的城市这个模式可以匹配 'Portland'(波特兰)、'Cleveland'(克利夫兰)、'Oakland'(奥克兰)等。_ 匹配第一个位置的任意单个字符,l 匹配第二个字符,% 匹配中间的任意字符序列,nd 匹配结尾序列。
4. 转义通配符 (Escaping Wildcards)
有时,你正在搜索的实际字符串可能包含字面意义上的 % 或 _ 字符。如果你直接使用 LIKE,MySQL 会将它们解释为通配符,这并非你的本意。要搜索这些字符本身,你需要“转义”它们。
ESCAPE 子句指定一个转义字符,它告诉 MySQL 将紧跟其后的字符视为字面字符而不是通配符。默认的转义字符是反斜杠 \,但你可以指定任何字符作为转义字符。
4.1 转义通配符示例
假设你有一个产品描述列,你想查找专门包含字符串 20% off 的产品。
SELECT
ProductName,
Description
FROM
products
WHERE
Description LIKE '%20\% off%'; -- 搜索字面字符串 '20% off'在这个例子中,\% 告诉 MySQL 将百分号视为一个字面字符。
如果你想搜索一个字面的下划线,你可以使用 \_。
你也可以指定一个自定义的转义字符:
SELECT
ProductName,
Description
FROM
products
WHERE
Description LIKE '%20#% off%' ESCAPE '#'; -- 使用 '#' 作为转义字符搜索 '20% off'这里,# 被声明为转义字符,所以 #% 被解释为一个字面意义上的百分号。
5. NOT LIKE 运算符
NOT LIKE 运算符用于检索字符串不匹配指定模式的行。它是 LIKE 的逻辑反面。
5.1 NOT LIKE 使用示例
要查找所有名称不以 'A' 开头的城市:
SELECT
Name,
CountryCode,
District
FROM
world.city
WHERE
Name NOT LIKE 'A%'; -- 查找名称不以 'A' 开头的城市这个查询将排除诸如 'Amsterdam'(阿姆斯特丹)、'Athens'(雅典)、'Atlanta'(亚特兰大)等以 'A' 开头的城市,返回所有其他的城市名称。
6. 实际考虑因素与性能优化
LIKE 运算符,特别是当模式以通配符(% 或 _)开头时,有时效率会低于精确匹配或范围搜索。这是因为对于以通配符开头的模式,MySQL 可能无法有效利用索引,从而可能导致全表扫描。
- 索引使用 (Index Usage): 如果
LIKE模式不以通配符开头(例如,Name LIKE 'Lon%'),MySQL 通常可以使用Name列上的索引,因为它能根据初始字符有效地缩小搜索范围。 - 全表扫描 (Full Table Scans): 如果
LIKE模式以通配符开头(例如,Name LIKE '%burg%'或Name LIKE '_l%nd'),MySQL 通常无法使用该列上的索引。这迫使数据库扫描表中的每一行来检查模式,在大型表上这会非常慢。 - 大小写敏感性 (Case Sensitivity): 默认情况下,对于许多常见的字符集,MySQL 中使用 LIKE 的字符串比较是不区分大小写的。例如,
LIKE 'london'将匹配 'London'、'london' 和 'LONDON'。如果需要区分大小写的匹配,可以使用BINARY运算符(例如,WHERE Name LIKE BINARY 'Lon%')。