检索出的数据并非以纯粹的随机顺序显示的。若是不排序,数据通常将以它在底层表中出现的顺序显示。这能够是数据最初添加到表中的顺序。可是,若是数据后来进行过更新或删除,则此顺序将会受到MySQL重用回收存储空间的影响。所以,若是不明确控制的话,不能依赖该排序顺序。git
关系数据库设计理论认为,若是不明确规定排序顺序,则不该该假定检索出的数据的顺序有意义。正则表达式
子句的解释:一个子句一般由一个关键字和所提供的数据组成。SQL语句由子句构成,有些子句是必需的,而有些是可选的。数据库
为了明确地排序用SELECT语句检索出的数据,可以使用ORDER BY子句。ORDER BY子句取一个或多个列的名字,据此对输出进行排序。排序顺序有两种:升序(ASC关键字)和降序(DESC关键字),api
格式:数据库设计
# 升序(默认不写就是升序) SELECT field1,field2,... FROM <table_name> ORDER BY field1,field2,...; SELECT field1,field2,... FROM <table_name> ORDER BY field1,field2,... ; # 降序 SELECT field1,field2,... FROM <table_name> ORDER BY field1,field2,... DESC; # 对field1降序,对field2升序(相似这样的例子也是能够的) SELECT field1,field2,... FROM <table_name> ORDER BY field1 DESC,field2 ASC,... ;
注意:函数
# UTF8 SELECT fiedl1,... FROM <表名> ORDER BY CONVERT(field1 using gbk);
单列,多列的升序和降序排序例子就不说了,若是使用ORDER BY子句和LIMIT的组合,则能够找出表的一个列中的最大或最小的值。学习
小结:学习了如何用SELECT语句的ORDER BY子句对检索出的数据进行排序。测试
若是想要按某条件从表中查询数据,那么就须要使用WHERE子句来指定搜索条件(过滤条件)进行过滤。WHERE子句在表名(FROM子句)后给出。优化
格式:spa
SELECT field1,field2,... FROM <表名> WHERE condition1 AND/OR condition2 ...;
搜索条件是一个表达式,它支持如下操做符
操做符 | 说明 |
---|---|
= | 等于 |
<> | 不等于 |
!= | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
BETWEEN..AND.. | 在指定两个值之间(都包括) |
单值查询:查询学生表中名为李四的学生
SELECT stu_name, stu_sex FROM student WHERE stu_name='李四';
不匹配查询:查询学生表中女性的学生
SELECT stu_name, stu_sex FROM student WHERE stu_sex<>'男';
范围查询:查询学生表中id从2到4的学生
SELECT stu_name, stu_sex FROM student WHERE stu_id BETWEEN 2 AND 4;
空值检查:空值就是NULL,空值不是0不是空字符串,使用WHERE子句也能够查询,下面的例子不是很好,但搜索条件的格式就是:IS NULL。
SELECT stu_name, stu_sex FROM student WHERE stu_sex IS NULL;
小结:介绍了如何使用SELECT语句的WHERE子句过滤返回的数据。也学习了如何对相等、不相等、大于、小于、值得范围以及NULL值等测试。
可使用逻辑操做符来进行多个条件的组合查询。
AND:用在WHERE子句中的关键字,表示检索知足全部给定条件的行。
格式:
SELECT field1,field2,... FROM <表名> WHERE condition1 AND condition2 AND ...;
能够有多个过滤条件。
OR:用在WHERE子句中的关键字,表示检索匹配任一给定条件的行。(也就是有任意一个条件知足就输出,不用所有同时匹配)
格式:
SELECT field1,field2,... FROM <表名> WHERE condition1 OR condition2 OR ...;
WHERE子句可包含任意数目的AND和OR操做符。而且容许二者结合以进行复杂和高级的过滤。
可是要注意这两个操做符的优先级问题:MySQL优先处理AND操做符.
任什么时候候使用具备AND和OR操做符的WHERE子句,都应该使用圆括号明确地分组操做符。不要过度依赖默认计算次序,即便它确实是你想要的结果也是如此。并且使用圆括号也没什么坏处,还能够消除歧义。
IN:用来指定条件范围,范围中的每个条件均可以进行匹配。IN取合法值的由逗号分隔的清单,全都括在圆括号中。
格式:
SELECT field1,field2,... FROM <表名> WHERE field1 IN(n,m,...);
IN操做符跟OR操做符的功能是同样的。
SELECT field1,field2,... FROM <表名> WHERE field1 IN(n,m,...); # 等于 SELECT field1,field2,... FROM <表名> WHERE field1=n OR field1=m OR ...;
IN操做符的优势以下:
WHERE子句中得NOT操做符有且只有一个功能,那就是否认它以后所跟得任何条件。
MySQL支持使用NOT对IN、BETWEEN和EXIST子句取反,这与多数其余DBMS容许使用NOT对各类条件取反有很大差异。
例子:
# 查询学生表中学生的性别不为空的学生 SELECT stu_name, stu_sex FROM student WHERE stu_sex IS NOT NULL; # 查询学生表中学生的姓名不为小乔的学生 SELECT stu_name, stu_sex FROM student WHERE NOT stu_name='小乔'; # 若是是带有逻辑运算符,NOT只做用于一个搜索条件,除非用括号括起来 SELECT stu_name, stu_sex FROM student WHERE NOT (stu_name='小乔' OR stu_name='大乔');
前面的都是针对具体值过滤的。但有时须要进行模糊查询,好比:查询某个字符或子字符串开头的字符串,有时查询包含某个字符或子字符串的字符串,有时查询某个字符或子字符串结尾的字符串。那么就须要构造一个通配符搜索模式来查询。
通配符(wildcard):用来匹配值的一部分的特殊字符。通配符能够在搜索模式中任意位置使用,而且可使用多个通配符。
搜索模式(search pattern)由字面值,通配符或二者组合构成的搜索条件
为在搜索子句中使用通配符,必须使用LIKE操做符。LIKE操做符表示MySQL后跟的搜索模式利用通配符匹配而不是直接相等匹配进行比较。
百分号通配符(%):表示任何字符出现任意次数。也就是可以匹配出现0次以上的字符。
# 以xx开头或以XX开头的字符串 SELECT field1,field2,... FROM <table_name> WHERE field1 LIKE 'xx%'; # 包含xx或包含XX的字符串 SELECT field1,field2,... FROM <table_name> WHERE field1 LIKE '%xx%'; # 以xx结尾或以XX结尾的字符串 SELECT field1,field2,... FROM <table_name> WHERE field1 LIKE '%xx';
注意:MySQL是不区分大小写的,也就是'xx%'能够匹配'XX%'和'xx%'。
若是想要在查询时区分大小写,能够加个BINARY关键字来区分大小写:
# 包含xx的字符串 SELECT field1,field2,... FROM <table_name> WHERE BINARY field1 LIKE '%xx%';
也能够在建立表的时候,在列定义上加上BINARY关键字,就表示该列区分大小写。
CREATE TABLE <table_name>( field1 BINARY, ... );
虽然看似%通配符能够匹配任何字符,可是有一个例外,即NULL。即便用搜索模式:'%',也不会匹配到NULL。
还得注意尾空格,尾空格可能会干扰通配符匹配,好比搜索模式为:'%xx '(有个空格)就不会匹配以xx结尾或以XX结尾的字符串,而是会匹配以xx 结尾(有个空格)或以XX 结尾(有个空格)的字符串。即加了尾空格表示匹配具体的值了,即尾空格。若是想要避免,最好使用函数(TRIM(搜索模式))来去掉。(函数待说,能够先看这个去空格的函数)
SELECT stu_name FROM student WHERE stu_name LIKE TRIM('%xx ');
下划线通配符(_):只匹配单个字符。即1个,不能多也不能少,不然就没有。
# 以xx开头或以XX开头长度为3的字符串 SELECT field1,field2,... FROM <table_name> WHERE field1 LIKE 'xx_'; # 包含xx或包含XX长度为4的字符串 SELECT field1,field2,... FROM <table_name> WHERE field1 LIKE '_xx_'; # 以xx结尾或以XX结尾长度为3的的字符串 SELECT field1,field2,... FROM <table_name> WHERE field1 LIKE '_xx';
百分号通配符和下划线通配符能够一块儿使用。
可能注意到了,在搜索模式中不使用通配符,即具体值也能够匹配,以下:
SELECT field1,field2,... FROM <table_name> WHERE field1 LIKE 'xx'; # 等于 SELECT field1,field2,... FROM <table_name> WHERE field1 = 'xx%';
二者均可以搜索具体值,使用 哪一种好?通配符搜索的处理通常要比前面讨论的其余搜索所花时间更长。
下面给出使用通配符要记住的技巧:
总结目前能够优化数据库的点子:
小结:介绍了如何用AND和OR操做符组合成WHERE子句,并且还介绍了如何明确地管理计算的次序,如何使用IN和NOT操做符。
前面的过滤例子容许使用匹配、比较和通配操做符查询数据。对于基本的过滤,学这些就足够了。可是随着过滤条件的复杂性的增长,WHERE子句自己的复杂性也有必要增长。
这就是正则表达式变得有用的地方。正则表达式是用来匹配文本的特殊的串(字符集合)。
下面只是作个基础的正则表达式学习,若是要完整覆盖正则表达式的之后再整。
正则表达式的做用是匹配文本,将一个模式(正则表达式)和一个文本串进行比较。MySQL用WHERE子句对正则表达式提供了初步的支持,,使用REGEXP关键字指定正则表达式,过滤SELECT检索出的数据。
MySQL仅支持多数正则表达式实现的一个很小的子集。
格式:
# fieldN的N表示一个整数。 SELECT field1,field2,... FROM <table_name> WHERE fieldN REGEXP '字符串';
好比:
# 会匹配包含乔的姓名的学生。 SELECT stu_name FROM student WHERE stu_name REGEXP '乔';
固然这个例子也可使用LIKE和通配符来操做。下面说一下它们的区别:
MySQL的正则表达式匹配仍是不区分大小写。若是要区分大小写,使用BINARY关键字,上面也有说。好比:
..... WHERE BINARY fieldN REGEXP '...'; # 或 ..... WHERE fieldN REGEXP BINARY '...';
还可用使用 . (点),. (点)是正则表达式语言中一个特殊的字符,它表示匹配任意一个字符。
# fieldN的N表示一个整数。 SELECT field1,field2,... FROM <table_name> WHERE fieldN REGEXP '.字符串';
注意:上面语句中的 .(点)是表示匹配任意一个字符。而不是表示普通键盘上的特殊字符.(点)。待会会将怎么匹配特殊字符。
OR操做符前面讲了,在这里的功能也是同样:为搜索两个串之一,可是注意写法:
SELECT field1,field2,... FROM <table_name> WHERE fieldN REGEXP '字符串1|字符串2|...';
即:使用 | 表示OR操做符。
正则表达式OR操做符的另外一种写法:[],好比:
SELECT field1,field2,... FROM <table_name> WHERE fieldN REGEXP '[字符1字符2...] ...';
[字符1字符2...]:定义一组字符,它的意思是 匹配字符1或匹配字符2等等。
也能够匹配字符串
SELECT field1,field2,... FROM <table_name> WHERE fieldN REGEXP '[字符串1, 字符串2...] ...';
[字符串1, 字符串2...]:定义一组字符串,匹配字符串1或匹配字符串1中的字符或匹配字符串2或匹配字符串2中的字符等等。
[] 形式的使用主要是用于有公共的部分,好比我要查询姓周,周后面带有 杰 或 雨 的同窗(注意:不是包含)就能够这样使用。
SELECT stu_name FROM student WHERE stu_name REGEXP BINARY '周[雨杰]';
匹配:周杰、周雨、周杰XXX、周雨XXX等。
按上面的例子,下面的这种写法:
SELECT stu_name FROM student WHERE stu_name REGEXP BINARY '周杰|雨';
若是这样写,匹配的是:周杰或雨。
上面的例子除非把字符|括在一个集合中,如:(杰|雨),不然它将应用于整个串。 懂了为何有OR为何要有:[]的形式了吧。
字符集合还能够被否认,即,它们将匹配指定字符外的任何东西。只须要在集合的开始放置一个^便可。好比:[^123]表示匹配除1或2或3外的任何东西。
集合可用来定义要匹配的一个或多个字符。例如,下面的集合将匹配数字0到9:
[0123456789]
为简化这种类型的集合,可以使用-来定义个范围。下面的式子等同于上述数字列表:
[0-9]
范围不限于完整的集合,[1-3]和[4-9]都是合法的范围。
下面是一些基础的字符集总结:
[abc]:表示多是字符a或是字符b或是字符c中的任意一位 [^abc]:表示不是字符a或是字符b或是字符c中的任意一位 [a-z]:全部的小写字母 [^a-z]: 不匹配全部的小写字母 [a-zA-Z]:字母中的任意一位 [^a-zA-Z]或[^(a-zA-Z)]:不匹配字母 [A-Z]:全部的大写字母 [^A-Z]:不匹配全部的大写字母 [0-9]:表示任意一位数字(只有一位,则范围为0到9) [^0-9]:表示不是任意一位数字
正则表达式语言由具备特定含义的特殊字符构成。好比前面学的.(点)、[]、|、-等,还有一些其余字符。可是这些字符是有特殊含义的,若是要匹配这些特殊字符要怎么作?
为了匹配特殊字符,必须使用\\为前导。即:\\- 表示查询特殊字符-; \\. 表示查询特殊字符.(点),\\\ 表示查询特殊字符。
这种处理称为转义(escaping),正则表达式内具备特殊意义的全部字符都必须以这种方式转义。
\\也用来引用元字符(具备特殊含义的字符):
元字符 | 说明 |
---|---|
\\f | 换页 |
\\n | 换行 |
\\r | 回车 |
\\t | 制表 |
\\v | 纵向制表 |
多半正则表达式实现使用单个反斜杠转义特殊字符,以便能使用这些字符自己。但MySQL要求两个反斜杠(MySQL本身解释一个,正则表达式解释另外一个)
存在找出本身常用的数字、全部的字母字符或全部数字字符等的匹配。为了方便工做,可用使用预约义的字符集,称为字符类(character class)
类 | 说明 |
---|---|
[:alnum:] | 任意字母和数字(同[a-zA-Z0-9]) |
[:alpha:] | 任意字符(同[a-zA-Z]) |
[:blank:] | 空格和制表(同[\\t]) |
[:cntrl:] | ASCII控制字符(ASCII 0到31和127) |
[:digit:] | 任意数字(同[0-9) |
[:graph:] | 与[:print:]相同,但不包括空格 |
[:lower:] | 任意小写字母(同[a-z]) |
[:print:] | 任意可打印字符 |
[:punct:] | 即不在[:alnum:]又不在[:cntrl:]中的任意字符 |
[:space:] | 包括空格在内的任意空白字符(同[\\f\\n\\r\\t\\v]) |
[:upper:] | 任意大写字母(同[A-Z]) |
[:xdigit:] | 任意十六进制数字(同[a-fA-F0-9]) |
不用死记,忘了就看。
到目前为止的全部正则表达式都是试图匹配单次出现。有时须要对匹配的数目进行更强的控制,那么就须要下面的重复元字符来完成:
元字符 | 说明 |
---|---|
* | 0个或多个匹配 |
+ | 1个或多个匹配(等一{1,}) |
? | 0个或1个匹配(等于{0,1}) |
{n} | 指定数目的匹配 |
{n,} | 很多于指定数目的匹配 |
{n,m} | 匹配数目的范围(m不超过255) |
好比:
匹配17级学生的全部学号,17级都是以2017开头的,而后后面有8位任意数字
... REGEXP '2017[0-9]{8}'; # 或 ... REGEXP '2017[[:digit:]]{8}';
[[:digit:]]{8}的解释:[:digit:]匹配任意数字,于是它为数字的一个集合。{8}确切要求它前面的字符(任意数字)出现8次,因此应该写成这样[[:digit:]]{8}:匹配连在一块儿的任意4位数字。
固然也能够这样写:
... REGEXP '2017[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]';
目前为止的全部例子都是匹配一个串中的任意位置的文本。为了匹配特定的位置,须要定位符:
元字符 | 说明
---|---
^ | 文本的开始(^有两种意义)
$ | 文本的结尾
[[:<:]] | 词的开始
[[:>:]] | 词的结尾
例如,若是想要找出以一个数(包括小数点开始的数)开始的全部产品,要怎么办?简单搜索[0-9\\.](或[[:digit:]\\.])吗?这样是不行的,由于它将在文本内的任意位置查找匹配。解决的方式就是使用^定位符,以下:
... REGEXP '^[0-9\\.]';
^有两种用法:
前面说过,LIKE匹配整个串而REGEXO匹配子串。利用定位符,经过用^开始每一个表达式,用%结束每一个表达式,可用是REGEXP的做用跟LIKE同样。
额外:可用在不使用数据库表的状况下用SELECT来测试正则表达式。REGEXP检查老是返回0(不匹配)或1(匹配)。可用用待文字串的REGEXP来测试表达式。好比
SELECT 'hello' REGEXP '[0-9]';
结果很明显返回0。
小结:介绍了正则表达式的基础知识,学习了如何在MySQL的SELECT语句中经过REGEXP关键字使用它们。