# 查询操作
# select 语句简介
这里补充说明一下“主键”的作用。如果将某一列设置为主键,那么这一列的值具有两个特点:**① 不允许为空(null),②具有唯一性。**一般情况下,每个表都需要有一个作为主键的列,这样可以保证每一行数据都有一个唯一标识。
举个简单的例子,如果一条记录包含了身份证号、姓名、性别、年龄等,那么怎样对两个人进行区分呢?很明显,只有通过身份证号才可以,因为姓名、性别、年龄这些都可能是相同的。所以主键就相当于每一行数据的“身份证号”,可以对不同行数据进行区分。
此外,在实际开发中,包含小数的列建议使用 decimal 类型,而不使用 float 或 double 类型。主要是因为 decimal 类型不存在精度损失,而 float 或 double 类型可能存在精度损失。
# select 语句
在 MySQL 中,可以使用 select 语句来对一个表进行查询操作。其中,select 是 SQL 中的关键字。select 语句是 SQL 所有语句中用得最多的一种语句,如果你能把 select 语句认真掌握好,那么说明离掌握 SQL 已经不远了。
select 列名 from 表名;
select 语句由“select 子句”和“from 子句”这两个部分组成。可能小伙伴们会觉得很奇怪:为什么这里除了有“select 语句”这种叫法之外,还有“select 子句”这样的叫法呢?
实际上,select 语句是“查询语句”的统称,它是由“子句”组合而成的。“子句”是语句的一部分,不能单独使用。select 语句包含的子句(查询子句)主要有 7 种,如表 3-1 所示。
表 3-1 查询子句
子句 | 说明 |
---|---|
select | 查询哪些列 |
from | 从哪个表查询 |
where | 查询条件 |
group by | 分组 |
having | 分组条件 |
order by | 排序 |
limit | 限制行数 |
从表 3-1 可以看出,where、group by、order by 等其实都属于查询子句,它们都是配合 select 子句使用的。小伙伴们一定要深刻地理解这一点,这样在后续的学习过程中才会有一个清晰的学习思路。
举例:查询一列
select name from fruit;
运行结果如图 3-3 所示。
举例:查询多列
select name, type, price from fruit;
运行结果如图 3-4 所示。
其中列名通过 ,
分割,书写的顺序也就是查询出来的数据排列顺序
# 特殊列名
如果列名中包含空格,此时应该怎么办呢?比如名称这一列的列名是“fruit name”(两个单词中间有一个空格),则小伙伴们可能会写出下面的 SQL 语句。
select fruit name from fruit;
实际上,上面这条语句是无效的。对于包含空格的列名,需要使用反引号()将其引起来。反引号(
)在键盘左上方数字 1 的左边,切换到英文状态下可以输入。
我们尝试在 Navicat for MySQL 中将 fruit 表中的“name”这个列名改为“fruit name”,然后执行下面的 SQL 语句,此时运行结果如图 3-9 所示。
select `fruit name` from fruit;
图 3-9
注意
需要特别注意的是,对于特殊列名(如包含空格),只能使用反引号将其引起来,而不能使用单引号或双引号。
# 使用别名:as
在使用 SQL 语句查询数据时,可以使用 as 关键字给一个列名起一个别名。起别名的作用是:增强代码和查询结果的可读性。
语法:
select 列名 as 别名
from 表名;
2
说明:
在实际开发中,一般建议在以下几种情况中使用别名。对于内置函数和多表查询,后续内容会详细介绍。
- 列名比较长或可读性差。
- 使用内置函数。
- 用于多表查询。
- 需要把两个或更多的列放在一起。
举例:英文别名
select name as fruit_name
from fruit;
2
运行结果如图 3-11 所示。
图 3-11
注意
- 别名只在当前的查询结果中显示,真实表中的列名并不会改变。
- 在使用 as 关键字起别名时,如果别名中包含了保留字或者特殊字符,如空格、加号(+)、减号(-)等,那么该别名必须用英文引号引起来。
# 条件子句:where
在 MySQL 中,可以使用 where 子句来指定查询的条件。where 子句是配合 select 子句来使用的。
语法:
select 列名
from 表名
where 条件;
2
3
说明:
where 子句一般需要结合运算符来使用,主要包括以下 3 类运算符。
- 比较运算符。
- 逻辑运算符。
- 其他运算符。
# 比较运算符
在 where 子句中,可以使用比较运算符来指定查询的条件。常用的比较运算符如表 3-2 所示。
表 3-2 比较运算符
运算符 | 说明 |
---|---|
> | 大于 |
< | 小于 |
= | 等于 |
>= | 大于或等于 |
<= | 小于或等于 |
!> | 不大于(相当于 <=) |
!< | 不小于(相当于 >=) |
!= 或 <> | 不等于 |
<=> | 安全等于 |
对于 MySQL 中的运算符,我们需要清楚以下 3 点。
- 对于“等于”,MySQL 使用的是“=”而不是“==”,这一点和其他编程语言不同。
- 对于“不等于”,MySQL 有两种表示方式:“!=”和“<>”。
- 只有 MySQL 中才有“<=>”运算符,SQL Server、Oracle、PostgreSQL 等是没有的。
举例:等于(数值)
select name, price
from fruit
where price = 27.3;
2
3
运行结果如图 3-17 所示。
# 逻辑运算符
在 where 子句中,如果需要同时指定多个查询条件,就需要使用逻辑运算符。MySQL 的逻辑运算符有两种写法:一种是“关键字”,如表 3-3 所示;另一种是“符号”,如表 3-4 所示。
表 3-3 关键字
运算符 | 说明 |
---|---|
and | 与 |
or | 或 |
not | 非 |
表 3-4 符号
运算符 | 说明 |
---|---|
&& | 与 |
|| | 或 |
! | 非 |
在实际开发中,一般情况下都使用“关键字”这种写法。
举例:与运算
select name, price
from fruit
where price > 10 and price < 20;
2
3
运行结果如图 3-22 所示。
图 3-22
# 其他运算符
除了比较运算符和逻辑运算符之外,MySQL 的其他运算符如表 3-5 所示。这些运算符也是非常重要的,小伙伴们也要认真掌握。
表 3-5 其他运算符
运算符 | 说明 |
---|---|
is null 或 isnull | 是否为 null 值 |
is not null | 是否不为 null 值 |
in | 是否为列表中的值 |
not in | 是否不为列表中的值 |
between A and B | 是否处于 A 和 B 之间(取值范围为 [A, B],包含 A 也包含 B) |
not between A and B | 是否不处于 A 和 B 之间 |
select *
from fruit_miss
where price is null;
2
3
select name, price
from fruit
where name in ('葡萄', '柿子', '橘子');
2
3
select name, price
from fruit
where price between 10 and 20;
2
3
# 运算符优先级
优先级也就是执行顺序的意思。例如,数学中的加减乘除运算就有一定的优先级,即有“()”就得先算“()”,然后算“乘除”,最后才算“加减”。
在 MySQL
中,逻辑运算符也是有优先级的,规则很简单:**优先级高的先运算,优先级低的后运算;优先级相同的,从左到右进行运算。**对于运算符优先级,我们需要清楚以下两个规则。
- 在算术运算中,“乘除”的优先级比“加减”的优先级要高。
- 在逻辑运算中,优先级由高到低为非(not)、与(and)、或(or)。
select name, season, price
from fruit
where (season = '夏' and price < 10) or price > 20;
2
3
因此在实际开发中还是建议加上一些必要的“()”,这样可以让代码的可读性更高。
# 排序子句:order by
# 语法
语法
select 列名
from 表名
order by 列名 asc 或 desc;
2
3
asc
表示升序排列,也就是从小到大排列;desc
表示降序排列,也就是从大到小排列。其中,asc
是“ascend”(上升)的缩写,而 desc
是“descend”(下降)的缩写。
# 对多列排序
select name, price, date
from fruit
order by price desc, date desc;
2
3
# 结合 where 子句
select name, price
from fruit
where price < 10
order by price desc;
2
3
4
注意
order by 子句可以结合 where 子句来使用,且 order by 子句必须放在 where 子句的后面。因为要先执行 where 子句来筛选数据,然后再执行 order by 子句来排序。
# 中文排序
在默认情况下,MySQL
使用的是 utf-8
字符集,此时对中文字符串进行排序,并不会按照中文拼音的顺序来进行。如果想要按照中文拼音顺序来进行排序,则需要借助 convert()
函数来实现。
convert( 列名 using gbk)
表示强制该列使用 gbk
字符集。
直接排序:
select name, price
from fruit
order by name;
2
3
提示
从结果可以看出,name 这一列并没有按照中文拼音顺序进行排序
使用 convert()
函数
select name, price
from fruit
order by convert(name using gbk);
2
3
注意
对于 select 子句来说,中文别名两侧的引号可加可不加。但是对于 order by 子句来说,中文别名两侧是一定不能加上引号的。如果加上引号,排序就无法成功。所以建议统一不加引号,这样可以避免出错。
# 限制行数:limit
# limit 子句
在默认情况下,select 语句会把符合条件的“所有行数据(所有记录)”都查询出来。如果查询到的记录有 100 条,而我们只需要获取前 10 条,此时应该怎么办呢?
获取前5
条数据:
select name, price
from fruit
limit 5;
2
3
# 指定数值范围
想要获取售价最高的前 5 条记录,使用 limit
关键字就可以轻松实现。但是如果要获取售价最高的第 2~5 条记录,又应该怎么实现呢?
语法
-- start 表示开始位置,默认值是 0。n 表示获取 n 条记录。
limit start, n
-- limit 1, 4
2
3
# 去重处理:distinct
在 MySQL
中,可以使用 distinct
关键字来实现数据的去重。所谓的数据去重,指的是去除多个重复行,只保留其中一行。
语法
select distinct 字段列表
from 表名;
2
提示
distinct
关键字用于 select
子句中,它总是紧跟在 select
关键字之后,并且位于第一个列名之前。此外,distinct
关键字作用于整个字段列表的所有列,而不是单独的某一列。
null值
注意
需要清楚的是,null 值被视为一类数据。如果列中存在多个 null 值,则只会保留一个 null 值。
用于多列
原数据:
select distinct type, season
from fruit;
2
结果
错误方式:
需要注意的是,distinct 关键字只能位于字段列表第一个列名之前,然后它会对整个字段列表的所有列进行去重处理。下面两种方式都是错误的。
-- 错误方式 1
select type, distinct season
from fruit;
-- 错误方式 2
select distinct type, distinct season
from fruit;
2
3
4
5
6
7
# 情景
一张 student 表:
id | name | sex | grade | birthday | major |
---|---|---|---|---|---|
1 | 张欣欣 | 女 | 86 | 2000-03-02 | 计算机科学 |
2 | 刘伟达 | 男 | 92 | 2001-06-13 | 网络工程 |
3 | 杨璐璐 | 女 | 72 | 2000-05-01 | 软件工程 |
4 | 王明刚 | 男 | 80 | 2002-10-17 | 电子商务 |
5 | 张伟 | 男 | 65 | 2001-11-09 | 人工智能 |
(1)查询成绩在 80 和 100 之间的学生的基本信息。
点击查看
select * from student where grade between 80 and 100
(2)查询所有学生的基本信息,并按照成绩从高到低进行排序。
点击查看
select * from student order by grade desc
(3)查询成绩前 3 名的学生的基本信息。
点击查看
select * from student order by grade desc limit 3
(4)查询所有学生的 name、grade、major 这 3 列的信息。
点击查看
select name,grade,major from student
(5)查询所有学生的 name、grade 这两列的信息,并且给 name 列起一个别名“姓名”,给 grade 列起一个别名“成绩”
点击查看
select name as `姓名`,grade as `姓名` from student