创建示例表
mysql> select * from player;
+----+-----------------------------+-------+
| id | name | level |
+----+-----------------------------+-------+
| 1 | 火狗 | 10 |
| 2 | 裂焰之狂犬 | 10 |
| 3 | 黄鸟—金翅域骨凰 | 15 |
| 4 | 亚洲人 | 14 |
| 5 | 小舞 | 35 |
| 6 | 极东之地的住民 | 47 |
| 7 | 老太太—沉默的智者 | 46 |
| 8 | 皮鞋 | 46 |
| 9 | 暗狱常胜靴 | 46 |
| 10 | 熊崽忽 | 46 |
| 11 | 有着奇怪职业 | 45 |
| 12 | 一样黑的猥琐狗熊 | 45 |
| 13 | sagou | 7 |
| 14 | senoku | 15 |
| 15 | shirley | 1 |
| 16 | useless | 1 |
| 17 | guess | 25 |
| 18 | Dog | 24 |
| 19 | leslieF | 3 |
| 20 | oooooo | 23 |
| 21 | ooo | 13 |
| 22 | oooo | 43 |
| 23 | 浩然狂舞曲 | 43 |
+----+-----------------------------+-------+
23 rows in set (0.00 sec)
一、order by排序语句
- 使用ORDER BY语句来实现排序
- 排序可针对一个或多个字段
- ASC:升序,默认排序方式
- DESC:降序
ORDER BY的语法结构:
selcet 字段1,字段2…… from 表名 order by 字段1,字段2…… ASC
selcet 字段1,字段2…… from 表名 order by 字段1,字段2…… DESC
示例
按关键字排序
使用SELECT语句可以将需要的数据从MySQL数据库中查询出来,如果对查询的结果进行排序,该如何去实现呢?
可以使用ORDER BY语句来完成排序,并最终将排序后的结果返回给用户。这个语句的排序不光可以针对某一个字段,
也可以针对多个字段。以下就是MySQL中ORDERBY语句的语法结构。
1.单字段排序
mysql> select id,name,level from player where level>=45 order by id desc; //降序排列id
+----+-----------------------------+-------+
| id | name | level |
+----+-----------------------------+-------+
| 12 | 一样黑的猥琐狗熊 | 45 |
| 11 | 有着奇怪职业 | 45 |
| 10 | 熊崽忽 | 46 |
| 9 | 暗狱常胜靴 | 46 |
| 8 | 皮鞋 | 46 |
| 7 | 老太太—沉默的智者 | 46 |
| 6 | 极东之地的住民 | 47 |
+----+-----------------------------+-------+
7 rows in set (0.00 sec)
2.多字段排序
ORDER BY后面跟多个字段时,字段之间使用英文逗号隔开,
优先级是按先后顺序而定。下面以A和B分别表示两个字段。(即多字段排序,以先写的字段先进行排序,将相同的值为一组,在以第二字段来排序,只有第一字段存在数值相同时第二字段的排序才有意义)
- ORDER BYA,B desc指A用升序,B用降序
- ORDER BY A asc,B desc指A用升序,B用降序;
- ORDER BYA desc,B desc指A用降序,B用降序;
mysql> select id,name,level from player where level>=45 order by level,id asc; //查看level大于等于45并一level,id列升序排列的id,name,level列的信息,(先排列level,后排列id)
+----+-----------------------------+-------+
| id | name | level |
+----+-----------------------------+-------+
| 11 | 有着奇怪职业 | 45 |
| 12 | 一样黑的猥琐狗熊 | 45 |
| 7 | 老太太—沉默的智者 | 46 | //可以看到在level=46的行中,id是以升序排列的
| 8 | 皮鞋 | 46 |
| 9 | 暗狱常胜靴 | 46 |
| 10 | 熊崽忽 | 46 |
| 6 | 极东之地的住民 | 47 |
+----+-----------------------------+-------+
7 rows in set (0.00 sec)
mysql> select id,name,level from player where level>=45 order by level,id desc; //level升序排列,id降序排列
+----+-----------------------------+-------+
| id | name | level |
+----+-----------------------------+-------+
| 12 | 一样黑的猥琐狗熊 | 45 |
| 11 | 有着奇怪职业 | 45 |
| 10 | 熊崽忽 | 46 | //可以看到在level=46的行中,id是以降序排列的
| 9 | 暗狱常胜靴 | 46 |
| 8 | 皮鞋 | 46 |
| 7 | 老太太—沉默的智者 | 46 |
| 6 | 极东之地的住民 | 47 |
+----+-----------------------------+-------+
7 rows in set (0.00 sec)
二、group by 分组语句
对结果进行分组:通过 SQL 查询出来的结果,还可以对其进行分组,使用 GROUP BY 语句来实现。
- GROUP BY 从字面上看,是以 BY 后面的内容对查询出的数据进行分组,就是将一个“数据集”划分成若干个“小区域”,然后针对这些个“小区域”进行数据处理。
- GROUP BY通常都是结合聚合函数一起使用的,常用的聚合函数包括:
计数(COUNT)、求和(SUM)、求平均数(AVG)、最大值(MAX)、最小值(MIN), - GROUP BY 分组的时候可以按一个或多个字段对结果进行分组处理。
语法结构
SELECT 列名,函数(列名) FROM 表名 WHERE 列名 控制语句 GROUP BY 列名;
示例
mysql> select count(name),level from player where level>=45 group by level; //以level字段进行分组,将相同的归为一组,之后查询统计的name字段和level字段
+-------------+-------+
| count(name) | level |
+-------------+-------+
| 2 | 45 |
| 4 | 46 |
| 1 | 47 |
+-------------+-------+
3 rows in set (0.01 sec)
mysql> select count(name),level from player where level>=45 group by level order by count(name) desc; //结合order by语句进行排序
+-------------+-------+
| count(name) | level |
+-------------+-------+
| 4 | 46 |
| 2 | 45 |
| 1 | 47 |
+-------------+-------+
3 rows in set (0.00 sec)
三、limit限制语句
- limit语句来限制结果条目:在使用 MySQL SELECT 语句进行查询时,结果集返回的是所有匹配的记录。有时候仅需要返回第一行或者前几行,这时候就需要用到 LIMIT 子句。
- LIMIT 的第一个参数是位置偏移量(可选参数),是设置 MySQL 从哪一行开始显示。
- 如果不设定第一个参数,将会从表中的第一条记录开始显示。需要注意的是,第一条记录的位置偏移量是 0,第二条是 1,以此类推。第二个参数是设置返回记录行的最大数目。
语法结构
SELECT 字段1,字段2, … FROM 表名 LIMIT [位偏移量,] 限制数目
示例
mysql> select id,name,level from player limit 3; //显示从第一行往后的3行
+----+--------------------------+-------+
| id | name | level |
+----+--------------------------+-------+
| 1 | 火狗 | 10 |
| 2 | 裂焰之狂犬 | 10 |
| 3 | 黄鸟—金翅域骨凰 | 15 |
+----+--------------------------+-------+
3 rows in set (0.00 sec)
mysql> select id,name,level from player limit 2,3; //显示从第3行开始往后的3行
+----+--------------------------+-------+
| id | name | level |
+----+--------------------------+-------+
| 3 | 黄鸟—金翅域骨凰 | 15 |
| 4 | 亚洲人 | 14 |
| 5 | 小舞 | 35 |
+----+--------------------------+-------+
3 rows in set (0.00 sec)
mysql> select id,name,level from player order by level desc limit 5; 结合order by 先降序排列,再限制条目
+----+-----------------------------+-------+
| id | name | level |
+----+-----------------------------+-------+
| 6 | 极东之地的住民 | 47 |
| 8 | 皮鞋 | 46 |
| 7 | 老太太—沉默的智者 | 46 |
| 10 | 熊崽忽 | 46 |
| 9 | 暗狱常胜靴 | 46 |
+----+-----------------------------+-------+
5 rows in set (0.00 sec)
as设置别名语句
- 在MySQL查询时,当表的名字比较长或者表内某些字段比较长时,为了方便书写或者多次使用相同的表,
- 可以给字段列或表设置别名。
使用的时候直接使用别名,简洁明了,增强可读性。 - 设置别名使用AS语句,
列的别名语法结构:
SELECT 列名 FROM 表名 AS 别名; (as是可以省略的)
示例
1.直接设置别名
mysql> select count(*) from player; //先使用count统计所有
+----------+
| count(*) |
+----------+
| 23 |
+----------+
1 row in set (0.00 sec)
mysql> select count(*) as number from player; //对count设置别名,显示的 count(*)变为了number
+--------+
| number |
+--------+
| 23 |
+--------+
1 row in set (0.00 sec)
mysql> select count(*) nub from player; //为表设置别名,as是可以省略的
+-----+
| nub |
+-----+
| 23 |
+-----+
1 row in set (0.00 sec)
2.如果表的长度比较长,可以使用AS给表设置别名,在查询的过程中直接使用别名
mysql> select p.id,p.name from player as p limit 5;
+----+--------------------------+
| id | name |
+----+--------------------------+
| 1 | 火狗 |
| 2 | 裂焰之狂犬 |
| 3 | 黄鸟—金翅域骨凰 |
| 4 | 亚洲人 |
| 5 | 小舞 |
+----+--------------------------+
5 rows in set (0.00 sec)
3.AS还可以作为连接语句的操作符
例如,执行以下操作即可实现用一条 SQL语句完成在创建表tmp的时候将player表内的数据写入 tmp 表。
使用as复制的表结构能保证数据类型是相同的,但是约束语句没有被复制下来,如主键、索引等
mysql> create table tmp as select * from player;
Query OK, 23 rows affected (0.02 sec)
Records: 23 Duplicates: 0 Warnings: 0
mysql> create table tmp as select * from player; //这里as作为连接操作符,相当于中转,将player表中的数据导入tmp表中(as在这里完成了两个步骤,复制表结构,插入数据)
Query OK, 23 rows affected (0.02 sec)
Records: 23 Duplicates: 0 Warnings: 0
mysql> select * from tmp;
+----+-----------------------------+-------+
| id | name | level |
+----+-----------------------------+-------+
| 1 | 火狗 | 10 |
| 2 | 裂焰之狂犬 | 10 |
| 3 | 黄鸟—金翅域骨凰 | 15 |
| 4 | 亚洲人 | 14 |
| 5 | 小舞 | 35 |
| 6 | 极东之地的住民 | 47 |
| 7 | 老太太—沉默的智者 | 46 |
| 8 | 皮鞋 | 46 |
……省略部分
注意:
1. 在为表设置别名时,要保证别名不能与数据库中的其他表的名称冲突。
2. 列的别名是在结果中有显示的,而表的别名在结果中没有显示,只在执行查询时使用,是临时的。
like语句结合通配符(模糊查询)
- 通配符主要用于替换字符串中的部分字符,通过部分字符的匹配将相关结果查询出来。
- 通常通配符都是跟 LIKE 一起使用的,并协同 WHERE 子句共同来完成查询任务。
常见的通配符
常用的通配符 | 含义 |
---|---|
% | 百分号表示零个、一个或多个字符 |
_ | 下划线表示单个字符 |
示例
mysql> select * from player where name like 's%'; //显示所有s开头的数据
+----+---------+-------+
| id | name | level |
+----+---------+-------+
| 13 | sagou | 7 |
| 14 | senoku | 15 |
| 15 | shirley | 1 |
+----+---------+-------+
3 rows in set (0.00 sec)
mysql> select * from player where name like '%g';
+----+------+-------+
| id | name | level |
+----+------+-------+
| 18 | Dog | 24 |
+----+------+-------+
1 row in set (0.00 sec)
mysql> select * from player where name like '__g'; //两个下划线代替两个字符
+----+------+-------+
| id | name | level |
+----+------+-------+
| 18 | Dog | 24 |
+----+------+-------+
1 row in set (0.00 sec)
mysql> select id,name,level from player where name like '_es%';
+----+---------+-------+
| id | name | level |
+----+---------+-------+
| 19 | leslieF | 3 |
+----+---------+-------+
1 row in set (0.00 sec)
in子查询(嵌套查询)语句
- 子查询也被称作内查询或者嵌套查询,是指在一个查询语句里面还嵌套着另一个查询语句子查询语句是先于主查询语句被执行的,
- 其结果作为外层的条件返回给主查询进行下一步的查询过滤。
- 子查询不仅可以在 SELECT 语句中使用,在 INERT、UPDATE、DELETE中也同样适用。在嵌套的时候,子查询内部还可以再次嵌套新的子查询,也就是说可以多层嵌套。
- IN用来判断某个值是否
子查询语法格式
<表达式> [NOT] IN <子查询>
-
当表达式与子查询返回的结果集中的某个值相等时,返回TRUE,否则返回 FALSE。
-
若启用了 NOT 关键字,则返回值相反。
-
需要注意的是,子查询只能返回一列数据,如果需求比较复杂,一列解决不了问题,可以使用多层嵌套的方式来应对。
-
多数情况下,子查询都是与SELECT语句一起使用的。增删改查都可以用子查询
示例1
mysql> select name,level from player where id in (select id from player where level>=45); //先查询level>=45的id数据,在查询当id满足上个条件时的name和level字段的数据。
+-----------------------------+-------+
| name | level |
+-----------------------------+-------+
| 极东之地的住民 | 47 |
| 老太太—沉默的智者 | 46 |
| 皮鞋 | 46 |
| 暗狱常胜靴 | 46 |
| 熊崽忽 | 46 |
| 有着奇怪职业 | 45 |
| 一样黑的猥琐狗熊 | 45 |
+-----------------------------+-------+
7 rows in set (0.01 sec)
注意,子查询是被放到括号内的,这个括号是无法省略的,缺失则会报错,无法形成子查询。
示例2
子查询内要查询的字段通常都是一个,查询后形成结果集供主查询使用。
子查询还可以用在 INSERT 语句中。子查询的结果集可以通过 INSERT 语句插入到其他的表中。
内外层必须数据类型同意,(比如内存是char,外层是int,则不能匹配了)
mysql> select * from tmp;
+----+-----------------------------+-------+
| id | name | level |
+----+-----------------------------+-------+
| 1 | 火狗 | 10 |
| 2 | 裂焰之狂犬 | 10 |
| 3 | 黄鸟—金翅域骨凰 | 15 |
| 4 | 亚洲人 | 14 |
| 5 | 小舞 | 35 |
| 6 | 极东之地的住民 | 47 |
| 7 | 老太太—沉默的智者 | 46 |
| 8 | 皮鞋 | 46 |
……省略部分
mysql> truncate table tmp; //清空tmp表
Query OK, 0 rows affected (0.01 sec)
mysql> select * from tmp; //查看tmp表,数据为空
Empty set (0.00 sec)
mysql> insert into tmp select * from player where id in (select id from player); //内外层必须数据类型同意,(比如内存是char,外层是int,则不能匹配了)将player表的值赋给tmp,注意这里的tmp和play的结构要相同才行
Query OK, 23 rows affected (0.00 sec)
Records: 23 Duplicates: 0 Warnings: 0
针对一些特殊情况,可以利用子查询,例如limit语句结合order by排序时,只能先排序,后限制行数,否则会报错,可以利用子查询解决这个问题
mysql> select * from info;
+----+-----------+-------+
| id | name | score |
+----+-----------+-------+
| 1 | lisi | 88 |
| 2 | zhangshan | 88 |
| 3 | wangwu | 60 |
| 4 | xiaoxiao | 69 |
| 5 | xia | 60 |
| 6 | xa | 45 |
+----+-----------+-------+
6 rows in set (0.00 sec)
############错误示范,会报错语法出错误##############
mysql> select * from info limit 3 order by id desc;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order by id desc' at line 1
###########################################
mysql> select a.* from (select * from info limit 3) a order by score desc;
+----+-----------+-------+
| id | name | score |
+----+-----------+-------+
| 2 | zhangshan | 88 |
| 1 | lisi | 88 |
| 3 | wangwu | 60 |
+----+-----------+-------+
3 rows in set (0.00 sec)
mysql> select a.* from (select * from info limit 3) a order by score;
+----+-----------+-------+
| id | name | score |
+----+-----------+-------+
| 3 | wangwu | 60 |
| 2 | zhangshan | 88 |
| 1 | lisi | 88 |
+----+-----------+-------+
3 rows in set (0.00 sec)
UPDATE结合子查询
- UPDATE内的子查询,在set更新内容时,可以是单独的一列,也可以是多列。
示例
mysql> select id,name,level from tmp where id=6;
+------+-----------------------+-------+
| id | name | level |
+------+-----------------------+-------+
| 6 | 极东之地的住民 | 47 |
+------+-----------------------+-------+
1 row in set (0.00 sec)
mysql> update tmp set level = level - 7 where id in (select a.id from (select id from tmp where level >= 47) a); //是level>=47的level值减去7,别名a在这里不能省略,select a.id from (select id from tmp where level >= 47) a,把这个结果集查询单独拉出来看,id是属于结果集的,因此要利用别名指明字段
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select id,name,level from tmp where id=6; //查看,确实减去了7
+------+-----------------------+-------+
| id | name | level |
+------+-----------------------+-------+
| 6 | 极东之地的住民 | 40 |
+------+-----------------------+-------+
1 row in set (0.00 sec)
mysql> update tmp set level=47 where id=6;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select id,name,level from tmp where id=6;
+------+-----------------------+-------+
| id | name | level |
+------+-----------------------+-------+
| 6 | 极东之地的住民 | 47 |
+------+-----------------------+-------+
1 row in set (0.00 sec)
mysql> delete from tmp where id in (select a.id from (select id from tmp where level=47)a); //注意这里的别名a是不能省略的,否则无法识别id字段是来自哪里的
Query OK, 1 row affected (0.01 sec)
注意:类似 select 方式的子查询,MySQL 不支持,需要多引入一层子查询
mysql> update tmp set level = level - 7 where id in (select id from tmp where level >= 47);
ERROR 1093 (HY000): You can't specify target table 'tmp' for update in FROM clause
in结合not用法
在IN前面还可以添加NOT,其作用与IN相反,表示否定(即不在子查询的结果集里面)。
mysql> select name,level from tmp where id not in (select id from tmp where level < 30); //查询level不小于30的数据
+-----------------------------+-------+
| name | level |
+-----------------------------+-------+
| 小舞 | 35 |
| 老太太—沉默的智者 | 46 |
| 皮鞋 | 46 |
| 暗狱常胜靴 | 46 |
| 熊崽忽 | 46 |
| 有着奇怪职业 | 45 |
| 一样黑的猥琐狗熊 | 45 |
| oooo | 43 |
| 浩然狂舞曲 | 43 |
+-----------------------------+-------+
9 rows in set (0.00 sec)
子查询上也可以使用比较运算符(=、<、>、>=、<=)
mysql> select id,name,level from tmp where id = (select id from tmp where name='shirley');
+------+---------+-------+
| id | name | level |
+------+---------+-------+
| 15 | shirley | 1 |
+------+---------+-------+
1 row in set (0.00 sec)
子查询结合EXIST 关键字
在子查询时,EXIST 关键字主要用于判断子查询的结果集是否为空。如果不为空, 则返回 TRUE;反之,则返回FALSE。
mysql> select count(*) as number from tmp where EXISTS (select id from tmp where name='shirley'); //name='shirley'的值是存在的,则统计name的值
+--------+
| number |
+--------+
| 22 |
+--------+
1 row in set (0.00 sec)
mysql> select count(*) as number from info where exists (select * from info where name='wangwu');
+--------+
| number |
+--------+
| 6 |
+--------+
1 row in set (0.00 sec)
利用别名子查询结果集
利用select查询出来的类似表的数据被称为“结果集”
查看结果集中的字段需要利用别名才能查询
mysql> select id,name from info; //查询info表,输出结果集
+----+-----------+
| id | name |
+----+-----------+
| 1 | lisi |
| 2 | zhangshan |
| 3 | wangwu |
| 4 | xiaoxiao |
| 5 | xia |
| 6 | xa |
+----+-----------+
6 rows in set (0.01 sec)
mysql> select id from (select id,name from info); //不设置别名是无法查询结果集中的字段的
ERROR 1248 (42000): Every derived table must have its own alias
mysql> select a.id from (select id,name from info) a; //设置结果集为别名a后,就可以查询结果集中的字段了
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
+----+
6 rows in set (0.00 sec)
视图
含义:
视图可以视为“虚拟表”或“存储的查询”,创建视图所依据的表称为“基表”,视图会根据基表动态改变(就好比“猴子捞月”,猴子在水中看见月亮,却不能捞出来,月亮消失,水中月也会消失,月亮出现,水中月也会出现)
语法:
create view 虚拟表名 select 字段 from 基表
视图的优点
- 提供了另外一种级别的表安全性:隐藏了一些关键的字段
- 简化的用户的SQL命令
- 隔离基表结构的改变
mysql> select * from info; //查看基表数据
+----+-----------+-------+
| id | name | score |
+----+-----------+-------+
| 1 | lisi | 88 |
| 2 | zhangshan | 88 |
| 3 | wangwu | 89 |
| 4 | xiaoxiao | 69 |
| 5 | xia | 60 |
| 6 | xa | 45 |
+----+-----------+-------+
6 rows in set (0.00 sec)
mysql> create view v_score as select * from info where score >= 80; //创建视图查询基表info中score>=80的信息
Query OK, 0 rows affected (0.00 sec)
mysql> select * from v_score; //查看视图,视图显示出过滤后的信息
+----+-----------+-------+
| id | name | score |
+----+-----------+-------+
| 1 | lisi | 88 |
| 2 | zhangshan | 88 |
| 3 | wangwu | 89 |
+----+-----------+-------+
3 rows in set (0.00 sec)
mysql> update info set score=60 where name='wangwu'; //现在将基表中的“wangwu”的score分值改为60,小于80分
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from v_score; //再次查看视图,视图中wangwu已经不在了,动态更新,被筛掉了
+----+-----------+-------+
| id | name | score |
+----+-----------+-------+
| 1 | lisi | 88 |
| 2 | zhangshan | 88 |
+----+-----------+-------+
2 rows in set (0.00 sec)
NULL 值描述
- 在SQL语句使用过程中,经常会碰到NULL这几个字符。通常使用NULL来表示缺失的值,也就是在表中该字段是没有值的。
- 如果在创建表时,限制某些字段不为空,则可以使用NOT NULL关键字,不使用则默认可以为空。
- 在向表内插入记录或者更新记录时,如果该字段没有NOT NULL并且没有值,这时候新记录的该字段将被保存为 NULL。
- 需要注意的是,NULL 值与数字 0 或者空白(spaces)的字段是不同的,值为NULL的字段是没有值的。
- 在SQL语句中,使用IS NULL可以判断表内的某个字段是不是NULL值,相反的用IS NOT NULL 可以判断不是NULL值。
################首先创建一个表用于测试#######################################
mysql> CREATE TABLE `test` (
-> `id` int(10) NOT NULL AUTO_INCREMENT,
-> `NAME` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
-> `level` int(10) NOT NULL,
-> `coin` int(32),
-> PRIMARY KEY (id)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test(name,level) values('aa',10); //插入数据
Query OK, 1 row affected (0.01 sec)
mysql> insert into test(name,level,coin) values('ab',20,100);
Query OK, 1 row affected (0.01 sec)
mysql> select * from test; //coin字段未插入数据默认为null
+----+------+-------+------+
| id | NAME | level | coin |
+----+------+-------+------+
| 1 | aa | 10 | NULL |
| 2 | ab | 20 | 100 |
+----+------+-------+------+
2 rows in set (0.00 sec)
mysql> select * from test where coin is null; //查询出coin字段为null的数据
+----+------+-------+------+
| id | NAME | level | coin |
+----+------+-------+------+
| 1 | aa | 10 | NULL |
+----+------+-------+------+
1 row in set (0.00 sec)
mysql> select * from test where coin is not null; //查询出coin字段不为null的数据
+----+------+-------+------+
| id | NAME | level | coin |
+----+------+-------+------+
| 2 | ab | 20 | 100 |
+----+------+-------+------+
1 row in set (0.00 sec)
比较null值和空值
提到 NULL 值就不得不说下空值,空值就是在表的字段中存储空字符(‘’)
二者的区别如下:
- 空值的长度为 0,不占用空间的;而NULL值的长度是 NULL,是占用空间的。
- IS NULL 或者 IS NOT NULL,是用来判断字段是不是为 NULL 或者不是 NULL,不能查出是不是空值的。
- 空值的判断使用=’’或者<>’’来处理。
- 在通过 count()计算有多少记录数时,如果遇到 NULL 值会自动忽略掉,遇到空值会加入到记录中进行计算。
mysql> select coin from test;
+------+
| coin |
+------+
| NULL |
| 100 |
| 123 |
+------+
3 rows in set (0.00 sec)
mysql> select count(coin) from test; //null值是不计入统计的
+-------------+
| count(coin) |
+-------------+
| 2 |
+-------------+
1 row in set (0.00 sec)
mysql> alter table test add cxxx char(8) default''; //插入一个默认为空的字段
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> insert into test(name,level,coin,cxxx) values('cd',30,111,'lll');
Query OK, 1 row affected (0.01 sec)
mysql> select * from test; //cxxx字段有3个空值,1个有效值
+----+------+-------+------+------+
| id | NAME | level | coin | cxxx |
+----+------+-------+------+------+
| 1 | aa | 10 | NULL | |
| 2 | ab | 20 | 100 | |
| 3 | bc | 30 | 123 | |
| 4 | cd | 30 | 111 | lll |
+----+------+-------+------+------+
4 rows in set (0.00 sec)
mysql> select count(cxxx) from test; //空值是参与count统计的
+-------------+
| count(cxxx) |
+-------------+
| 4 |
+-------------+
1 row in set (0.00 sec)
mysql> select * from test where cxxx=''; //查询cxxx字段为空值的数据
+----+------+-------+------+------+
| id | NAME | level | coin | cxxx |
+----+------+-------+------+------+
| 1 | aa | 10 | NULL | |
| 2 | ab | 20 | 100 | |
| 3 | bc | 30 | 123 | |
+----+------+-------+------+------+
3 rows in set (0.00 sec)
mysql> select * from test where cxxx<> ''; //查询cxxx字段不为空值的数据
+----+------+-------+------+------+
| id | NAME | level | coin | cxxx |
+----+------+-------+------+------+
| 4 | cd | 30 | 111 | lll |
+----+------+-------+------+------+
1 row in set (0.00 sec)
正则表达式
- MySQL 正则表达式通常是在检索数据库记录的时候,根据指定的匹配模式匹配记录中符合要求的特殊字符串。
- MySQL 的正则表达式使用 REGEXP 这个关键字来指定正则表达式的匹配模式,REGEXP 操作符所支持的匹配模式
常见的正则表达式
匹配模式 | 描述 | 描述 |
---|---|---|
^ | 匹配文本的开始字符 | ‘^bd’ 匹配以 bd 开头的字符串 |
$ | 匹配文本的结束字符 | ‘qn$’ 匹配以 qn 结尾的字符串 |
. | 匹配任何单个字符 | ‘s.t’ 匹配任何s 和t 之间有一个字符的字符串 |
* | 匹配零个或多个在它前面的字符 | ‘fo*t’ 匹配 t 前面有任意个 o |
+ | 匹配前面的字符 1 次或多次 | ‘hom+’ 匹配以 ho 开头,后面至少一个 |
‘字符串’ | 匹配包含指定的字符串 | ‘clo’ 匹配含有 clo 的字符串 |
p1|p2 | 匹配 p1 或 p2 | ‘bg|fg’ 匹配 bg 或者 fg |
[…] | 匹配字符集合中的任意一个字符 | ‘[abc]’ 匹配 a 或者 b 或者 c |
[^…] | 匹配不在括号中的任何字符 | ‘[^ab]’ 匹配不包含 a 或者 b 的字符串 |
{n} | 匹配前面的字符串 n 次 | ‘g{2}’ 匹配含有 2 个 g 的字符串 |
{n,m} | 匹配前面的字符串至少 n 次,至多m 次 | ‘f{1,3}’ 匹配 f 最少 1 次,最多 3 次 |
示例
mysql> select id,name,level from player where name REGEXP '^us'; //匹配us开头的数据
+----+---------+-------+
| id | name | level |
+----+---------+-------+
| 16 | useless | 1 |
+----+---------+-------+
1 row in set (0.00 sec)
mysql> select id,name,level from player where name REGEXP 'ss$';
+----+---------+-------+
| id | name | level |
+----+---------+-------+
| 16 | useless | 1 |
| 17 | guess | 25 |
+----+---------+-------+
2 rows in set (0.00 sec)
mysql> select id,name,level from player where name REGEXP 'ok'; //查询包含ok字符的数据
+----+--------+-------+
| id | name | level |
+----+--------+-------+
| 14 | senoku | 15 |
+----+--------+-------+
1 row in set (0.00 sec)
mysql> select id,name,level from player where name REGEXP 'shir.ey'; //以.代替一个字符
+----+---------+-------+
| id | name | level |
+----+---------+-------+
| 15 | shirley | 1 |
+----+---------+-------+
1 row in set (0.01 sec)
mysql> select id,name,level from player where name REGEXP '[^a-z]';
+----+-----------------------------+-------+
| id | name | level |
+----+-----------------------------+-------+
| 1 | 火狗 | 10 |
| 2 | 裂焰之狂犬 | 10 |
| 3 | 黄鸟—金翅域骨凰 | 15 |
| 4 | 亚洲人 | 14 |
| 5 | 小舞 | 35 |
| 6 | 极东之地的住民 | 47 |
| 7 | 老太太—沉默的智者 | 46 |
| 8 | 皮鞋 | 46 |
| 9 | 暗狱常胜靴 | 46 |
| 10 | 熊崽忽 | 46 |
| 11 | 有着奇怪职业 | 45 |
| 12 | 一样黑的猥琐狗熊 | 45 |
| 23 | 浩然狂舞曲 | 43 |
+----+-----------------------------+-------+
13 rows in set (0.00 sec)
mysql> select id,name,level from player where name REGEXP '^[a-z]';
+----+---------+-------+
| id | name | level |
+----+---------+-------+
| 13 | sagou | 7 |
| 14 | senoku | 15 |
| 15 | shirley | 1 |
| 16 | useless | 1 |
| 17 | guess | 25 |
| 18 | Dog | 24 |
| 19 | leslieF | 3 |
| 20 | oooooo | 23 |
| 21 | ooo | 13 |
| 22 | oooo | 43 |
+----+---------+-------+
10 rows in set (0.00 sec)
四、运算符
MySQL 的运算符用于对记录中的字段值进行运算。MySQL 的运算符共有四种,分别是:算术运算符、比较运算符、逻辑运算符和位运算符。
1.常见运算符
运算符 | 描述 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 取余数 |
示例
mysql> create table lls as (select 1+2 as addition, 2-1 as subtraction, 2*3 as multiplication, 4/2 as division, 8%2 as remainder); //利用as,可以将运算值生成表
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from lls;
+----------+-------------+----------------+----------+-----------+
| addition | subtraction | multiplication | division | remainder |
+----------+-------------+----------------+----------+-----------+
| 3 | 1 | 6 | 2.0000 | 0 |
+----------+-------------+----------------+----------+-----------+
1 row in set (0.00 sec)
mysql> select 1+1 as addition, 4-1 as subtraction, 2*7 as multiplication, 4/0 as division, 4%2 as remainder;
+----------+-------------+----------------+----------+-----------+
| addition | subtraction | multiplication | division | remainder |
+----------+-------------+----------------+----------+-----------+
| 2 | 3 | 14 | NULL | 0 |
+----------+-------------+----------------+----------+-----------+
1 row in set, 1 warning (0.00 sec)
注意:
- 在除法运算和求余数运算中,除数不能为 0,若除数是 0,返回的结果则为 NULL。
- 如果有多个运算符,按照先乘除后加减的优先级进行运算,相同优先级的运算 符没有先后顺序。
- 在 MySQL 的字段值内还有一种情况:某些字符串类型的字段存储的数字型字符串,这些字段在进行算术运算时将会被自动转换为数字的值。
- 如果字符串的开始部分是数字,在转 换时将被转换为这个数字。如果是既包含字符又包含数字得的混合字符串,无法转换为数字时,将被转换为 0。这些细节在进行算术运算时需多加注意。
2.比较运算符
- 比较运算符是查询数据记录时经常使用的一类运算符。通过使用比较运算符可以判断出 表中有哪些记录是符合条件的,如果比较的结果为真则返回 1,如果为假则返回 0,
- 比较的结果如果不确定则返回 NULL。其中字符串在进行比较的时候默认是不区分大小写的,如果要区分大小写可以通过 binary 关键字来实现。常用的比较运算符
运算符 | 描述 |
---|---|
= | 等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
!=或<> | 不等于 |
IS NULL | 判断一个值是否为 NULL |
IS NOT NULL | 判断一个值是否不为 NULL |
BETWEEN AND | 两者之间 |
IN | 在集合中 |
LIKE | 通配符匹配 |
GREATEST | 两个或多个参数时返回最大值 |
LEAST | 两个或多个参数时返回最小值 |
REGEXP | 正则表达式 |
(1)等于运算符
等号(=)是用来判断数字、字符串和表达式是否相等的,如果相等则返回1,如果不相等则返回0。
如果比较的两者有一个值是 NULL,则比较的结果就是 NULL。其中字符的比较是根据 ASCII 码来判断的,
如果 ASCII 码相等,则表示两个字符相同;如果ASCII码不相等,则表示两个字符不相同。
a对应的ASCII码为97
A对应的ASCII码是65
0对应的ASCII码是48
mysql> select 2=4,2='2','e'='e',(2+2)=(3+1),'r'=NULL;
+-----+-------+---------+-------------+----------+
| 2=4 | 2='2' | 'e'='e' | (2+2)=(3+1) | 'r'=NULL |
+-----+-------+---------+-------------+----------+
| 0 | 1 | 1 | 1 | NULL |
+-----+-------+---------+-------------+----------+
1 row in set (0.00 sec)
总结:
- 如果两者都是整数,则按照整数值进行比较。
- 如果一个整数一个字符串,则会自动将字符串转换为数字,再进行比较。
- 如果两者都是字符串,则按照字符串进行比较。
- 如果两者中至少有一个值是 NULL,则比较的结果是 NULL。
(2)不等于运算符
- 不等于号有两种写法,分别是<>或者!=,用于针对数字、字符串和表达式不相等的比较。
- 如果不相等则返回 1,如果相等则返回 0,这点正好跟等于的返回值相反。需要注意的是不等于运算符不能用于判断 NULL。
mysql> select 'ltp'<>'ltp', 1<>2, 3!=3, 2.5!=2, NULL<>NULL ;
+--------------+------+------+--------+------------+
| 'ltp'<>'ltp' | 1<>2 | 3!=3 | 2.5!=2 | NULL<>NULL |
+--------------+------+------+--------+------------+
| 0 | 1 | 0 | 1 | NULL |
+--------------+------+------+--------+------------+
1 row in set (0.01 sec)
(3)大于、大于等于、小于、小于等于运算符
- 大于(>)运算符用来判断左侧的操作数是否大于右侧的操作数,若大于返回 1,否则返回 0,同样不能用于判断 NULL。
- 小于(<)运算符用来判断左侧的操作数是否小于右侧的操作数,若小于返回 1,否则返回 0,同样不能用于判断 NULL。
- 大于等于(>=)判断左侧的操作数是否大于等于右侧的操作数,若大于等于返回 1,否则返回 0,不能用于判断 NULL。
- 小于等于(<=)判断左侧的操作数是否小于等于右侧的操作数,若小于等于返回 1,否则返回 0,不能用于判断 NULL。
mysql> select 5>4,'a'>'b',2>=3,(2+3)>=(1+2),4.4<3,1<2,'x'<='y',5<=5.5,'u'>=NULL;
+-----+---------+------+--------------+-------+-----+----------+--------+-----------+
| 5>4 | 'a'>'b' | 2>=3 | (2+3)>=(1+2) | 4.4<3 | 1<2 | 'x'<='y' | 5<=5.5 | 'u'>=NULL |
+-----+---------+------+--------------+-------+-----+----------+--------+-----------+
| 1 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | NULL |
+-----+---------+------+--------------+-------+-----+----------+--------+-----------+
1 row in set (0.00 sec)
###############字符串之间的比较是由做往右依次比较的,是“或”的关系,满足一个就成立#####
mysql> select 'abc'>'bbd'; ##比较a>b,所以不成立
+-------------+
| 'abc'>'bbd' |
+-------------+
| 0 |
+-------------+
1 row in set (0.00 sec)
mysql> select 'cbc'>'bbd'; ##比较c>b,所以成立
+-------------+
| 'cbc'>'bbd' |
+-------------+
| 1 |
+-------------+
1 row in set (0.00 sec)
如果两者都是整数,则按照整数值进行比较。
如果一个整数一个字符串,则会自动将字符串转换为数字,再进行比较。
如果两者都是字符串,则按照字符串进行比较。
如果两者中至少有一个值是 NULL,则比较的结果是NULL。
(4)IS NULL、IS NOT NULL
- IS NULL 判断一个值是否为 NULL,如果为 NULL 返回 1,否则返回 0。
- IS NOT NULL 判断一个值是否不为 NULL,如果不为 NULL 返回 1,否则返回 0。例如,关于数字、字符和 NULL 值的运用,
mysql> select 2 IS NULL,'f' IS NOT NULL,NULL IS NULL;
+-----------+-----------------+--------------+
| 2 IS NULL | 'f' IS NOT NULL | NULL IS NULL |
+-----------+-----------------+--------------+
| 0 | 1 | 1 |
+-----------+-----------------+--------------+
1 row in set (0.00 sec)
- IS NULL:判断为空
- IS NOT NULL :判断不为空
- 两者只是有无 NOT 这个关键字的区别,同时返回值不同。
(5)BETWEEN AND
BETWEEN AND 比较运算通常用于判断一个值是否落在某两个值之间。例如,判断某数字是否在另外两个数字之间,也可以判断某英文字母是否在另外两个字母之间(包含头和尾的)
mysql> select 4 BETWEEN 2 AND 6,5 BETWEEN 6 AND 8,'c' BETWEEN 'a' AND 'f';
+-------------------+-------------------+-------------------------+
| 4 BETWEEN 2 AND 6 | 5 BETWEEN 6 AND 8 | 'c' BETWEEN 'a' AND 'f' |
+-------------------+-------------------+-------------------------+
| 1 | 0 | 1 |
+-------------------+-------------------+-------------------------+
1 row in set (0.00 sec)
(6)LEAST、GREATEST
- LEAST:当有两个或者多个参数时,返回其中的最小值。如果其中一个值为 NULL,则返回结果就为 NULL。
- GREATEST:当有两个或者多个参数时,返回其中的最大值。如果其中一个值为 NULL, 则返回结果就为 NULL。
- least语句中如果放的是不同类型数值(数字和字母)将不能识别,返回状态码0;在greate语句中则会忽略字母继续比较。
mysql> SELECT least(1,2,3),least('a','b','c'),greatest(1,2,3),greatest('a','b','c');
+--------------+--------------------+-----------------+-----------------------+
| least(1,2,3) | least('a','b','c') | greatest(1,2,3) | greatest('a','b','c') |
+--------------+--------------------+-----------------+-----------------------+
| 1 | a | 3 | c |
+--------------+--------------------+-----------------+-----------------------+
1 row in set (0.00 sec)
mysql> select least (10,5.1,10.3)最小 ,greatest (10,5.1,10.3)最大; //浮点型和整数型也可以比较
+--------+--------+
| 最小 | 最大 |
+--------+--------+
| 5.1 | 10.3 |
+--------+--------+
1 row in set (0.00 sec)
mysql> select least (10,5.1,10.3,'b')最小 ,greatest (10,5.1,10.3,'b')最大;
+--------+--------+
| 最小 | 最大 |
+--------+--------+
| 0 | 10.3 |
+--------+--------+
1 row in set, 2 warnings (0.00 sec)
总结:
- LEAST 比较的参数为数字时,返回的是其中最小的值;当比较的参数为字符串时,返回字母表中顺序最靠前的字符。
- GREATEST 比较的参数为数字时, 返回的是其中最大的值;当比较的参数为字符串时,返回字母表中顺序最靠后的字符。
(7)IN、NOT IN
- IN 判断一个值是否在对应的列表中,如果是返回 1,否则返回 0。
- NOT IN 判断一个值是否不在对应的列表中,如果不是返回 1,否则返回 0。
例如,判断某数字是否在一组数字中,也可判断某字符是否在一组字符中,具体操作如 下所示。
mysql> SELECT 2 in (1,2,3,4,5),'c' not in ('a','b','c');
+------------------+--------------------------+
| 2 in (1,2,3,4,5) | 'c' not in ('a','b','c') |
+------------------+--------------------------+
| 1 | 0 |
+------------------+--------------------------+
1 row in set (0.00 sec)
(8)LIKE、NOT LIKE
- LIKE 用来匹配字符串,如果匹配成功则返回 1,反之返回 0。
- LIKE 支持两种通配符:’%’ 用于匹配任意数目的字符,而’_’只能匹配一个字符。
- NOT LIKE 正好跟 LIKE 相反,如果没有匹配成功则返回 1,反之返回 0。
例如,若要判断某字符串能否匹配成功,分单字符匹配和多字符匹配,也可以判断不匹配.
mysql> SELECT 'ltp' LIKE 'ly_','lpp' LIKE '%p','etc' NOT LIKE '%th';
+------------------+-----------------+----------------------+
| 'ltp' LIKE 'ly_' | 'lpp' LIKE '%p' | 'etc' NOT LIKE '%th' |
+------------------+-----------------+----------------------+
| 0 | 1 | 1 |
+------------------+-----------------+----------------------+
1 row in set (0.00 sec)
3.逻辑运算符
逻辑运算符又被称为布尔运算符,通常用来判断表达式的真假,如果为真返回 1,否则返回 0,
真和假也可以用 TRUE 和 FALSE 表示。MySQL 中支持使用的逻辑运算符有四种,
运算符 | 描述 |
---|---|
NOT 或 ! | 逻辑非 |
AND 或 && | 逻辑与 |
OR 或 || | 逻辑或 |
XOR | 逻辑异或 |
补充:在或关系中,有一个表达式成立,整个表达式就成立;在且关系中必须两个都要成立;在异或关系中,都为0或者都为1(非零)则被判定位成立,否则不成立。(在下面的判断中非0就相当于成立,0相当于不成立)
且 | 0&&0=0 | 1&&0=0 | 0&&1=0 | 1&&1=1 | 1&&null=null | 0&&nuull=0 |
---|---|---|---|---|---|---|
或 | 0 or 0=0 | 1 or 0=1 | 0 or 1=1 | 1 or 1=1 | 1 or null=1 | 0 or nuull=null |
异或 | 0 xor 0=0 | 1 xor 0=1 | 0 xor 1=1 | 1 xor 1=0 | 1 xor null=null | 0 xor nuull=null |
(1)逻辑非
逻辑运算符中最简单的运算符就是逻辑非,逻辑非使用 NOT 或!表示。逻辑非将跟在它后面的逻辑测试取反,把真变为假,把假变为真。如果 NOT 后面的操作数为 0 时,所得值为 1;如果操作数为非 0 时,所得值为 0;如果操作数为 NULL 时,所得值为 NULL。
mysql>SELECT not 2,!3,not 0,!(4-4);
+-------+----+--------+--------+
| not 2 | !3 | not 0 | !(4-4) |
+-------+----+--------+--------+
| 0 | 0 | 1 | 1 |
+-------+----+--------+--------+
1 row in set (0.00 sec)
(2)逻辑与
- 逻辑与通常用于判断两个值或多个值的有效性,如果所有值都是真返回 1,否则返回 0,遇0则为0
- 逻辑与使用 AND 或者&&表示。
mysql> SELECT 2 AND 3,4 && 0,0 && NULL,1 AND NULL;
+---------+--------+-----------+------------+
| 2 AND 3 | 4 && 0 | 0 && NULL | 1 AND NULL |
+---------+--------+-----------+------------+
| 1 | 0 | 0 | NULL |
+---------+--------+-----------+------------+
1 row in set (0.00 sec)
在且关系中,0&&null(0且null)结果为0,1&&null(1且null)结果为null
(3)逻辑或
- 逻辑或表示包含的操作数,任意一个为非零值并且不是 NULL 值时,返回 1,否则返回0。
- 逻辑或通常使用 OR 或者||来表示。(不要用||,有问题)
mysql>SELECT 2 OR 3,4 || 0,0 OR NULL,1 || NULL; ### ||这种方式不准确(会以或的关系全部输出出来),or比较靠谱
+--------+--------+-----------+-----------+
| 2 OR 3 | 4 || 0 | 0 OR NULL | 1 || NULL |
+--------+--------+-----------+-----------+
| 1 | 40 | NULL | 1 |
+--------+--------+-----------+-----------+
1 row in set (0.00 sec)
在或关系中,0 or null 结果为null,1 or null 结果为1;
(4)逻辑异或
- 两个非 NULL 值的操作数,如果两者都是 0 或者都是非 0,则返回 0;如果一个为 0, 另一个为非 0,则返回结果为1;
- 当任意一个值为 NULL 时,返回值为 NULL。
mysql>SELECT 2 XOR 3,0 XOR 0,0 XOR 5,1 XOR NULL,NULL XOR NULL;
+---------+---------+---------+------------+---------------+
| 2 XOR 3 | 0 XOR 0 | 0 XOR 5 | 1 XOR NULL | NULL XOR NULL |
+---------+---------+---------+------------+---------------+
| 0 | 0 | 1 | NULL | NULL |
+---------+---------+---------+------------+---------------+
1 row in set (0.00 sec)
4.位运算符
位运算符实际上是对二进制数进行计算的运算符。MySQL 内位运算会先将操作数变成二进制格式,然后进行位运算,最后在将计算结果从二进制变回到十进制格式,方便用户查看。MySQL 支持 6 种位运算符
运算符 | 描述 |
---|---|
& | 按位与 |
| | 按位或 |
~ | 按位取反 |
^ | 按位异或 |
<< | 按位左移 |
>> | 按位右移 |
mysql> SELECT 10 & 15, 10 | 15, 10 ^ 15, 5 &~1;
+---------+---------+---------+-------+
| 10 & 15 | 10 | 15 | 10 ^ 15 | 5 &~1 |
+---------+---------+---------+-------+
| 10 | 15 | 5 | 4 |
+---------+---------+---------+-------+
1 row in set (0.00 sec)
以第一个逻辑与 10&15 为例
10= 1 0 1 0
15= 1 1 1 1
____________
逻辑与: 1 0 1 0 =10
10= 1 0 1 0
15= 1 1 1 1
____________
逻辑或: 1 1 1 1 =15
10= 1 0 1 0
15= 1 1 1 1
____________
逻辑异或: 0 1 0 1 =5
mysql> SELECT 1<<2, 2<<2,10>>2,15>>2;
+------+------+-------+-------+
| 1<<2 | 2<<2 | 10>>2 | 15>>2 |
+------+------+-------+-------+
| 4 | 8 | 2 | 3 |
+------+------+-------+-------+
1 row in set (0.00 sec)
mysql> select 10<<2;
+-------+
| 10<<2 |
+-------+
| 40 |
+-------+
1 row in set (0.00 sec)
mysql> select 10>>2;
+-------+
| 10>>2 |
+-------+
| 2 |
+-------+
1 row in set (0.01 sec)
1<<2 :1向左偏移两位,即:001变为100=4
10>>2:10向右偏移两位,即:1010变为0010=2 ;偏移后超出的位数将被移除并丢弃,不足的位用0补齐
10<<2
10= 1 0 1 0 = 0 0 1 0 1 0
左偏移2位: 1 0 1 0 0 0 = 40
—————————————————————————————————————————————————————————
10>>2
10= 1 0 1 0 = 0 0 1 0 1 0
右偏移2位: 0 0 0 0 1 0 = 2
5.运算符优先级
以上不管哪种运算符,在使用过程中都有优先级问题。运算符的优先级决定了不同的运 算符在计算过程中的先后顺序。级别高的运算符会先进行计算,如果运算符的级别相同, MySQL 会按照顺序从左到右依次进行计算。如果不确定所使用的运算符的优先级,可以使用()改变优先级。“!”的优先级最高,而“:=”的优先级最低。
优先级 | 运算符 |
---|---|
1 | ! |
2 | ~ |
3 | ^ |
4 | * , /(DIV), %(MOD) |
5 | +,- |
6 | >>,<< |
7 | & |
8 | | |
9 | =,<=>,>=,>,<=,<,<>,!=,IS,LIKE,REGEXP,IN |
10 | BETWEEN,CASE,WHEN,THEN,ELSE |
11 | NOT |
12 | &&,AND |
13 | ||,OR,XOR |
14 | := |
五、连接查询
MySQL 的连接查询,通常都是将来自两个或多个表的行结合起来,基于这些表之间的共同字段,进行数据的拼接。
首先,要确定一个主表作为结果集,然后将其他表的行有选择性的连接到选定的主表结果集上。使用较多的连接查询包括:内连接、左连接和右连接。
MySQL 除了内连接,还可以使用外连接。区别于 MySQL 外连接是将表分为基础表和参考表,再依据基础表返回满足条件或不满足条件的记录。外连接按照连接时表的顺序来分,
有左连接和右连接之分。
这里使用两个表 a_player 和 b_player 来进行演示。首先需要创建这两个表,然后插入一些初始数据。
CREATE TABLE `a_player` (
`a_id` int(11) DEFAULT NULL,
`a_name` varchar(32) DEFAULT NULL,
`a_level` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `b_player` (
`b_id` int(11) DEFAULT NULL,
`b_name` varchar(32) DEFAULT NULL,
`b_level` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into a_player(a_id, a_name, a_level) values(1, 'aaaa', 10);
insert into a_player(a_id, a_name, a_level) values(2, 'bbbb', 20);
insert into a_player(a_id, a_name, a_level) values(3, 'cccc', 30);
insert into a_player(a_id, a_name, a_level) values(4, 'dddd', 40);
insert into b_player(b_id, b_name, b_level) values(2, 'bbbb', 20);
insert into b_player(b_id, b_name, b_level) values(3, 'cccc', 30);
insert into b_player(b_id, b_name, b_level) values(5, 'eeee', 50);
insert into b_player(b_id, b_name, b_level) values(6, 'ffff', 60);
mysql> select * from a_player;
+------+--------+---------+
| a_id | a_name | a_level |
+------+--------+---------+
| 1 | aaaa | 10 |
| 2 | bbbb | 20 |
| 3 | cccc | 30 |
| 4 | dddd | 40 |
+------+--------+---------+
4 rows in set (0.00 sec)
mysql> select * from b_player;
+------+--------+---------+
| b_id | b_name | b_level |
+------+--------+---------+
| 2 | bbbb | 20 |
| 3 | cccc | 30 |
| 5 | eeee | 50 |
| 6 | ffff | 60 |
+------+--------+---------+
4 rows in set (0.00 sec)
内连接
MySQL 中的内连接就是两张或多张表中同时符合某种条件的数据记录的组合。通常在FROM 子句中使用关键字 INNER JOIN 来连接多张表,并使用 ON 子句设置连接条件。
- 两张或多张表中同时符合某种条件的数据记录组合
- FROM子句中使用INNERJOIN关键字连接多张表,并使用ON设置连接条件
- 是系统默认的表连接方式,可以省略INNER关键字
- 多表支持连续使用INNER JOIN,建议不超过三个表
语法格式
SELECT 字段 FROM 表1 INNER JOIN 表2 ON 表1.字段 = 表2.字段;
示例:在刚才创建的 a_player 和 b_player 表中使用内连接查询出通过判断 a_id 和 b_id 相等,包含在两个表内的部分
mysql> select a_id id,a_name,a_level from a_player inner join b_player on a_id=b_id;
+------+--------+---------+
| id | a_name | a_level |
+------+--------+---------+
| 2 | bbbb | 20 |
| 3 | cccc | 30 |
+------+--------+---------+
2 rows in set (0.00 sec)
- 上述操作是将 a_player 表的每一行与 b_player 表的每一行进行比较,以检查它们是否都满足条件。当满足条件时,INNER JOIN 将返回由 a_player 表中的列组成的行。如果没有匹配项,查询将返回一个空的结果集。INNER JOIN 结果集中的行必须出现在两个表 a_player 和 b_player 中,是这两个表的交叉部分,即a_id=b_id的部分
- 如果表中至少有一个匹配项,INNER JOIN 关键字将返回一行。如果没有匹配项,则不会有输出结果。
外连接
- 在JOIN左边的为左表,在 JOIN右边的为右表
- 在进行左连接查询时,左表会全部显示,右表显示匹配部分,右连接同理
1.左连接
- 左连接也可以被称为左外连接。
- 在 FROM 子句中使用 LEFT JOIN 或者 LEFT OUTER JOIN 关键字来表示。
- 左连接以左侧表为基础表,接收左表的所有行,并用这些行与右侧参考表中的记录进行匹配,也就是说匹配左表中的所有行以及右表中符合条件的行。
示例,从a_player 和 b_player 表中,查询出 a_player 表中所有内容,并且查询出通过 a_id 和 b_id 相等判断出的 b_player 中的部分,具体操作如下。
mysql> select * from a_player a left join b_player b on a.a_id=b.b_id;
+------+--------+---------+------+--------+---------+
| a_id | a_name | a_level | b_id | b_name | b_level |
+------+--------+---------+------+--------+---------+
| 2 | bbbb | 20 | 2 | bbbb | 20 |
| 3 | cccc | 30 | 3 | cccc | 30 |
| 1 | aaaa | 10 | NULL | NULL | NULL |
| 4 | dddd | 40 | NULL | NULL | NULL |
+------+--------+---------+------+--------+---------+
4 rows in set (0.00 sec)
总结:
- 从以上左连接查询结果可以看出,除了匹配的行,a_id 和 b_id 是 2 和 3 那两行,还包括了左表中有但右表中没有的行,如果有表没有对应值,则使用 NULL 代替。也就是说在左连接查询中,使用 NULL 值表示右表中没有找到与左表中匹配的记录。
- 从原理图可以看出,左连接中左表的记录将会全部表示出来,而右表只会显示符合搜索 条件的记录,也就是图中交叉的部分。右表记录不足的地方均为 NULL。
2.右连接
- 右连接也被称为右外连接.
- 在 FROM 子句中使用 RIGHT JOIN 或者 RIGHT OUTER JOIN 关键字来表示。
- 右连接跟左连接正好相反,它是以右表为基础表,用于接收右表中的所有行,并用这些记录与左表中的行进行匹配。也就是说匹配右表中的每一行及左表中符合条件的记录。
例如,从 a_player 和 b_player 表中,查询出在 b_player 表内的所有记录,并且通过判断 a_id 和 b_id 相等,在 a_player 表内的部分,具体的实现操作如下所示。
mysql> select * from a_player a right join b_player b on a.a_id=b.b_id;
+------+--------+---------+------+--------+---------+
| a_id | a_name | a_level | b_id | b_name | b_level |
+------+--------+---------+------+--------+---------+
| 2 | bbbb | 20 | 2 | bbbb | 20 |
| 3 | cccc | 30 | 3 | cccc | 30 |
| NULL | NULL | NULL | 5 | eeee | 50 |
| NULL | NULL | NULL | 6 | ffff | 60 |
+------+--------+---------+------+--------+---------+
4 rows in set (0.00 sec)
实用示例
mysql> create table 学员信息表 (
-> 学号 int(10) not null auto_increment primary key,
-> 姓名 varchar(16) not null,
-> 兴趣类型 int(3) not null);
Query OK, 0 rows affected (0.00 sec)
mysql> desc 学员信息表;
+--------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+----------------+
| 学号 | int(10) | NO | PRI | NULL | auto_increment |
| 姓名 | varchar(16) | NO | | NULL | |
| 兴趣类型 | int(3) | NO | | NULL | |
+--------------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> create table 兴趣表 (
-> 兴趣编号 int(10) primary key not null,
-> 兴趣类型 varchar(10) not null);
Query OK, 0 rows affected (0.00 sec)
mysql> desc 兴趣表;
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| 兴趣编号 | int(10) | NO | PRI | NULL | |
| 兴趣类型 | varchar(10) | NO | | NULL | |
+--------------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> select * from 学员信息表;
+--------+--------+--------------+
| 学号 | 姓名 | 兴趣类型 |
+--------+--------+--------------+
| 1 | 张三 | 10 |
| 2 | 李四 | 10 |
| 3 | 王五 | 20 |
| 4 | 赵柳 | 30 |
| 5 | 杨琪 | 20 |
+--------+--------+--------------+
5 rows in set (0.00 sec)
mysql> select * from 兴趣表;
+--------------+--------------+
| 兴趣编号 | 兴趣类型 |
+--------------+--------------+
| 10 | 篮球 |
| 20 | 乒乓球 |
| 30 | 跑步 |
| 40 | 游泳 |
+--------------+--------------+
4 rows in set (0.00 sec)
########内连接#################
mysql> select a.姓名,b.兴趣类型 from 学员信息表 a inner join 兴趣表 b on a.兴趣类型=b.兴趣编号;
+--------+--------------+
| 姓名 | 兴趣类型 |
+--------+--------------+
| 张三 | 篮球 |
| 李四 | 篮球 |
| 王五 | 乒乓球 |
| 赵柳 | 跑步 |
| 杨琪 | 乒乓球 |
+--------+--------------+
5 rows in set (0.00 sec)
######右连接#######################
mysql> select a.学号,a.姓名,b.兴趣类型 from 学员信息表 a right join 兴趣表 b on a.兴趣类型=b.兴趣编号;
+--------+--------+--------------+
| 学号 | 姓名 | 兴趣类型 |
+--------+--------+--------------+
| 1 | 张三 | 篮球 |
| 2 | 李四 | 篮球 |
| 3 | 王五 | 乒乓球 |
| 4 | 赵柳 | 跑步 |
| 5 | 杨琪 | 乒乓球 |
| NULL | NULL | 游泳 |
+--------+--------+--------------+
6 rows in set (0.00 sec)
注意:int类型的字段是默认不能为空(’’)但可以为(null)