【学习04】组合where、通配符及正则表达式

一、数据过滤

组合WHERE子句以建立功能更强的更高级的搜索条件。 我们还将学习如何使用NOT和IN操作符。

1.1、组合WHERE子句

  为了进行更强的过滤控制,MySQL允许给出多个WHERE子句。这些子 句可以两种方式使用:以AND子句的方式或OR子句的方式使用。

操作符(operator): 用来联结或改变WHERE子句中的子句的关键 字。也称为逻辑操作符(logical operator)。

1.1.1、AND操作符

  为了通过不止一个列进行过滤,可使用AND操作符给WHERE子句附加 条件。下面的代码给出了一个例子:

SELECT prod_id,prod_price,prod_name
FROM products
WHERE vend_id = 1003 AND prod_price <= 10;

分析: 此SQL语句检索由供应商1003制造且价格小于等于10美元的所有产品的名称和价格。这条SELECT语句中的WHERE子句包含两个条件,并且用AND关键字联结它们。AND指示DBMS只返回满足所有给 定条件的行。如果某个产品由供应商1003制造,但它的价格高于10美元, 则不检索它。类似,如果产品价格小于10美元,但不是由指定供应商制造的也不被检索。这条SQL语句产生的输出如下:
输出:
在这里插入图片描述

AND 用在WHERE子句中的关键字,用来指示检索满足所有给定 条件的行。

上述例子中使用了只包含一个关键字AND的语句,把两个过滤条件组 合在一起。还可以添加多个过滤条件,每添加一条就要使用一个AND。

1.1.2、OR操作符

  OR操作符与AND操作符不同,它指示MySQL检索匹配任一条件的行。请看如下的SELECT语句:
输入:

SELECT prod_price,prod_name
FROM products
WHERE vend_id = 1003 OR vend_id <= 1002;

分析: 此SQL语句检索由任一个指定供应商制造的所有产品的产品 名和价格。OR操作符告诉DBMS匹配任一条件而不是同时匹配两个条件。如果这里使用的是AND操作符,则没有数据返回(此时创建的WHERE子句不会检索到匹配的产品)。这条SQL语句产生的输出如下:
输出:
在这里插入图片描述

OR WHERE子句中使用的关键字,用来表示检索匹配任一给定 条件的行。

1.1.3、计算次序

  WHERE可包含任意数目的AND和OR操作符。允许两者结合以进行复杂 和高级的过滤。
  但是,组合AND和OR带来了一个有趣的问题。为了说明这个问题,来 看一个例子。假如需要列出价格为10美元(含)以上且由1002或1003制 造的所有产品。下面的SELECT语句使用AND和OR操作符的组合建立了一个 WHERE子句:
输入:

SELECT prod_name,prod_price
FROM products
WHERE (vend_id = 1003 OR vend_id = 1002) AND prod_price >= 10;

分析:
SQL(像多数语言一样)在处理OR操作符前,优先处理AND操作符。是使用圆括号明确地分组相应的操作符。前两个条件用圆括号括了起来。因为圆括号具有较AND或OR操作符高 的计算次序,DBMS首先过滤圆括号内的OR条件。这时,SQL语句变成了 选择由供应商1002或1003制造的且价格都在10美元(含)以上的任何产 品,这正是我们所希望的。
输出:
在这里插入图片描述

在WHERE子句中使用圆括号: 任何时候使用具有AND和OR操作 符的WHERE子句,都应该使用圆括号明确地分组操作符。不要 过分依赖默认计算次序,即使它确实是你想要的东西也是如 此。使用圆括号没有什么坏处,它能消除歧义。

1.2、IN操作符

  圆括号在WHERE子句中还有另外一种用法。IN操作符用来指定条件范 围,范围中的每个条件都可以进行匹配。IN取合法值的由逗号分隔的清 单,全都括在圆括号中。下面的例子说明了这个操作符:
输入:

SELECT prod_name,prod_price
FROM products
WHERE vend_id IN (1002,1003)
ORDER BY prod_name;

输出:
在这里插入图片描述
分析: 此SELECT语句检索供应商1002和1003制造的所有产品。IN操 作符后跟由逗号分隔的合法值清单,整个清单必须括在圆括号
中。
  IN操作符完成与OR相同的功能,为什么要使用IN操作符?其优点具体如下。

  • 在使用长的合法选项清单时,IN操作符的语法更清楚且更直观。
  • 在使用IN时,计算的次序更容易管理(因为使用的操作符更少)。
  • IN操作符一般比OR操作符清单执行更快。
  • IN的最大优点是可以包含其他SELECT语句,使得能够更动态地建 立WHERE子句。第14章将对此进行详细介绍。

IN WHERE子句中用来指定要匹配值的清单的关键字,功能与OR 相当。

1.3、NOT操作符

   WHERE子句中的NOT操作符有且只有一个功能,那就是否定它之后所 跟的任何条件。

NOT WHERE子句中用来否定后跟条件的关键字。

  下面的例子说明NOT的使用。为了列出除1002和1003之外的所有供应 商制造的产品,可编写如下的代码:
输入:

SELECT vend_id,prod_name,prod_price
FROM products
WHERE vend_id NOT IN (1002,1003)
ORDER BY prod_name;

输出:
在这里插入图片描述
分析: 这里的NOT否定跟在它之后的条件,因此,MySQL不是匹配1002 和1003的vend_id,而是匹配1002和1003之外供应商的 vend_id。
  对于简单的WHERE子句,使用NOT确实没有什么优 势。但在更复杂的子句中,NOT是非常有用的。例如,在与IN操作符联合 使用时,NOT使找出与条件列表不匹配的行非常简单。

MySQL中的NOT MySQL支持使用NOT对IN、BETWEEN和 EXISTS子句取反,这与多数其他DBMS允许使用NOT对各种条件取反有很大的差别。

二、使用通配符进行过滤

如何使用通配符以及怎样使用LIKE操作符 进行通配搜索,以便对数据进行复杂过滤。

2.1、LIKE操作符

  怎样搜索产品名中包含文本anvil的所有产品?用简单的比较操作符肯定不行,必须使用通配符。利用通配符可创建比较特定数据的搜索模式。在这个例子中,如果你想找出名称包含anvil的所有产品,可构造一个通配符搜索模式,找出产品名中任何位置出现anvil的产品。

通配符(wildcard) 用来匹配值的一部分的特殊字符。
搜索模式(search pattern) 由字面值、通配符或两者组合构 成的搜索条件。

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

谓词 操作符何时不是操作符?答案是在它作为谓词(predi- cate)时。从技术上说,LIKE是谓词而不是操作符。虽然最终的结果是相同的,但应该对此术语有所了解,以免在SQL文档中遇到此术语时不知道。

2.1.1、百分号(%)通配符

  最常使用的通配符是百分号(%)。在搜索串中,%表示任何字符出现 任意次数。例如,为了找出所有以词jet起头的产品,可使用以下SELECT 语句:
输入:

SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE 'jet%';

输出:
在这里插入图片描述
分析: 此例子使用了搜索模式’jet%’。在执行这条子句时,将检索任 意以jet起头的词。%告诉MySQL接受jet之后的任意字符,不 管它有多少字符。

区分大小写 根据MySQL的配置方式,搜索可以是区分大小 写的。如果区分大小写,'jet%'与JetPack 1000将不匹配。

  通配符可在搜索模式中任意位置使用,并且可以使用多个通配符。 下面的例子使用两个通配符,它们位于模式的两端:
输入:

SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE '%anvil%';

输出:
在这里插入图片描述
分析: 搜索模式’%anvil%'表示匹配任何位置包含文本anvil的值,而 不论它之前或之后出现什么字符。
  通配符也可以出现在搜索模式的中间,虽然这样做不太有用。下面的例子找出以s起头以e结尾的所有产品:
输入:

SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE 's%e';

输出:
在这里插入图片描述

  重要的是要注意到,除了一个或多个字符外,%还能匹配0个字符。% 代表搜索模式中给定位置的0个、1个或多个字符

注意尾空格 尾空格可能会干扰通配符匹配。例如,在保存词 anvil时,如果它后面有一个或多个空格,则子句WHERE prod_name LIKE '%anvil’将不会匹配它们,因为在最后的l 后有多余的字符。解决这个问题的一个简单的办法是在搜索模式最后附加一个%。一个更好的办法是使用函数去掉首尾空格(后面介绍)。

注意NULL 虽然似乎%通配符可以匹配任何东西,但有一个例 外,即NULL。即使是WHERE prod_name LIKE '%'也不能匹配 用值NULL作为产品名的行。

2.1.2、下划线(_)通配符

  另一个有用的通配符是下划线(_)。下划线的用途与%一样,但下划 线只匹配单个字符而不是多个字符。
举一个例子:
输入:

SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE '_ ton anvil';

输出:
在这里插入图片描述
分析: 此WHERE子句中的搜索模式给出了后面跟有文本的两个通配 符。结果只显示匹配搜索模式的行:第一行中下划线匹配1, 第二行中匹配2。.5 ton anvil产品没有匹配,因为搜索模式要求匹配两 个通配符而不是一个。对照一下,下面的SELECT语句使用%通配符,返回 三行产品:
输入:

SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE '% ton anvil';

输出:
在这里插入图片描述
与%能匹配0个字符不一样,_总是匹配一个字符,不能多也不能少。

2.2、 使用通配符的技巧

  正如所见,MySQL的通配符很有用。但这种功能是有代价的:通配 符搜索的处理一般要比前面讨论的其他搜索所花时间更长。这里给出一 些使用通配符要记住的技巧。

  • 不要过度使用通配符。如果其他操作符能达到相同的目的,应该 使用其他操作符。
  • 在确实需要使用通配符时,除非绝对有必要,否则不要把它们用 在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起 来是最慢的。
  • 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据。

总之,通配符是一种极重要和有用的搜索工具,以后我们经常会用 到它。

三、用正则表达式进行搜索

在MySQL WHERE子句内使用正则表达式来更好地控 制数据过滤。

3.1、正则表达式介绍

  正则表达式是用来匹配文本 的特殊的串(字符集合)。如果你想从一个文本文件中提取电话号码,可 以使用正则表达式。如果你需要查找名字中间有数字的所有文件,可以 使用一个正则表达式。如果你想在一个文本块中找到所有重复的单词, 可以使用一个正则表达式。如果你想替换一个页面中的所有URL为这些 URL的实际HTML链接,也可以使用一个正则表达式(对于后这个例子, 或者是两个正则表达式)。
  正则表达式用正则表达式语言来建立,正则表达式语言是用来完成 刚讨论的所有工作以及更多工作的一种特殊语言。与任意语言一样,正 则表达式具有你必须学习的特殊的语法和指令。

3.2、 使用MySQL正则表达式

  正则表达式的作 用是匹配文本,将一个模式(正则表达式)与一个文本串进行比较。MySQL 用WHERE子句对正则表达式提供了初步的支持,允许指定正则表达式, 过滤SELECT检索出的数据。

仅为正则表达式语言的一个子集 如果你熟悉正则表达式,需要注意:MySQL仅支持多数正则表达式实现的一个很小的子集

3.2.1、基本字符匹配

我们从一个非常简单的例子开始。下面的语句检索列prod_name包含 文本1000的所有行:
输入:

SELECT prod_name
FROM products
WHERE prod_name REGEXP '1000'
ORDER BY prod_name;

输出:
在这里插入图片描述
分析: 除关键字LIKE被REGEXP替代外,这条语句看上去非常像使用 LIKE的语句。它告诉MySQL:REGEXP后所跟的东西作为正则表达式(与文字正文1000匹配的一个正则表达式)处理。

  为什么要费力地使用正则表达式?在刚才的例子中,正则表达式确 实没有带来太多好处(可能还会降低性能),不过,请考虑下面的例子:
输入:

SELECT prod_name
FROM products
WHERE prod_name REGEXP '.000'
ORDER BY prod_name;

输出:
在这里插入图片描述
分析: 这里使用了正则表达式.000。.是正则表达式语言中一个特殊 的字符。它表示匹配任意一个字符,因此,1000和2000都匹配
且返回。

3.2.2、进行OR匹配

为搜索两个串之一(或者为这个串,或者为另一个串),使用|,如 下所示:
输入:

SELECT prod_name
FROM products
WHERE prod_name REGEXP '1000|2000'
ORDER BY prod_name;

输出:
在这里插入图片描述
分析: 语句中使用了正则表达式1000|2000。|为正则表达式的OR操作 符。它表示匹配其中之一,因此1000和2000都匹配并返回。
  使用|从功能上类似于在SELECT语句中使用OR语句,多个OR条件可并 入单个正则表达式。

两个以上的OR条件 可以给出两个以上的OR条件。例如, '1000 | 2000 | 3000’将匹配1000或2000或3000。

3.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的缩写,也可以使用后者。但是,需要用[]来定义OR语句 查找什么。为更好地理解这一点,请看下面的例子:
输入:

SELECT prod_name
FROM products
WHERE prod_name REGEXP '1|2|3 Ton'
ORDER BY prod_name;

输出:
在这里插入图片描述
分析: 这并不是期望的输出。两个要求的行被检索出来,但还检索出 了另外3行。之所以这样是由于MySQL假定你的意思是’1’或 ‘2’或’3 ton’。除非把字符|括在一个集合中,否则它将应用于整个串。
  字符集合也可以被否定,即,它们将匹配除指定字符外的任何东西。 为否定一个字符集,在集合的开始处放置一个^即可。因此,尽管[123] 匹配字符1、2或3,但[^123]却匹配除这些字符外的任何东西。

3.2.4、匹配范围

  集合可用来定义要匹配的一个或多个字符。例如,下面的集合将匹 配数字0到9:
[0123456789]
  为简化这种类型的集合,可使用-来定义一个范围。下面的式子功能 上等同于上述数字列表:
[0-9]
  范围不限于完整的集合,[1-3]和[6-9]也是合法的范围。此外,范 围不一定只是数值的,[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,因此返回3个匹配行。由于5 ton匹配, 所以返回.5 ton。

3.2.5、匹配特殊字符

  正则表达式语言由具有特定含义的特殊字符构成。我们已经看到.、[]、 |和-等,还有其他一些字符。请问,如果你需要匹配这些字符,应该怎么 办呢?例如,如果要找出包含.字符的值,怎样搜索?请看下面的例子:
输入:

SELECT vend_name
FROM vendors
WHERE vend_name REGEXP '.'
ORDER BY vend_name;

输出:
在这里插入图片描述
分析: 这并不是期望的输出,.匹配任意字符,因此每个行都被检索出来。
为了匹配特殊字符,必须用\为前导。\-表示查找-,\.表示查找.。
输入:

SELECT vend_name
FROM vendors
WHERE vend_name REGEXP '\\.'
ORDER BY vend_name;

输出:
在这里插入图片描述
分析: 这才是期望的输出。\\.匹配.,所以只检索出一行。这种处理 就是所谓的转义(escaping),正则表达式内具有特殊意义的所 有字符都必须以这种方式转义。这包括.、|、[]以及迄今为止使用过的 其他特殊字符。
  \\也用来引用元字符(具有特殊含义的字符),如表所列。
在这里插入图片描述

匹配\ 为了匹配反斜杠(\)字符本身,需要使用\\。

\或\\? 多数正则表达式实现使用单个反斜杠转义特殊字符, 以便能使用这些字符本身。但MySQL要求两个反斜杠(MySQL自己解释一个,正则表达式库解释另一个)。

3.2.6、匹配字符类

  存在找出你自己经常使用的数字、所有字母字符或所有数字字母字 符等的匹配。为更方便工作,可以使用预定义的字符集,称为字符类 (character class)。列出字符类以及它们的含义。
在这里插入图片描述

3.2.7、匹配多个实例

  目前为止使用的所有正则表达式都试图匹配单次出现。如果存在一 个匹配,该行被检索出来,如果不存在,检索不出任何行。但有时需要 对匹配的数目进行更强的控制。例如,你可能需要寻找所有的数,不管 数中包含多少数字,或者你可能想寻找一个单词并且还能够适应一个尾 随的s(如果存在),等等。这可以用列出的正则表达式重复元字符来完成。
在这里插入图片描述
下面举几个例子。
输入:

SELECT prod_name
FROM products
WHERE prod_name REGEXP '\\([0-9] sticks?\\)'

输出:
在这里插入图片描述
分析: 正则表达式\\([0-9] sticks?\\)需要解说一下。\\(匹配), [0-9]匹配任意数字(这个例子中为1和5),sticks?匹配stick 和sticks(s后的?使s可选,因为?匹配它前面的任何字符的0次或1次出 现) ,\\)匹配)。没有?,匹配stick和sticks会非常困难。 以下是另一个例子。这次我们打算匹配连在一起的4位数字:
输入:

SELECT prod_name
FROM products
WHERE prod_name REGEXP '[[:digit:]]{4}'
ORDER BY prod_name;

输出:
在这里插入图片描述
分析: 如前所述,[:digit:]匹配任意数字,因而它为数字的一个集 合。{4}确切地要求它前面的字符(任意数字)出现4次,所以 [[:digit:]]{4}匹配连在一起的任意4位数字。
需要注意的是,在使用正则表达式时,编写某个特殊的表达式几乎 总是有不止一种方法。

3.2.8、定位符

  目前为止的所有例子都是匹配一个串中任意位置的文本。为了匹配特定位置的文本,需要使用表列出的定位符。
在这里插入图片描述
  例如,如果你想找出以一个数(包括以小数点开始的数)开始的所 有产品,怎么办?简单搜索[0-9\\.](或[[:digit:]\\.])不行,因为 它将在文本内任意位置查找匹配。解决办法是使用^定位符,如下所示:
输入:

SELECT prod_name
FROM products
WHERE prod_name REGEXP '^[0-9\\.]'
ORDER BY prod_name;

输出:
在这里插入图片描述
分析:匹配串的开始。因此,[0-9\.]只在.或任意数字为串中第 一个字符时才匹配它们。没有^,则还要多检索出4个别的行(那 些中间有数字的行)。

^的双重用途 ^有两种用法。在集合中(用[和]定义),用它 来否定该集合,否则,用来指串的开始处。

猜你喜欢

转载自blog.csdn.net/weixin_43800761/article/details/102910605
今日推荐