MySQL 基础 (一)
MySQL 基础(一)
每天学习新知识,每天进步一点点。
1. 什么是数据库?
数据库(Database)是按照数据结构来组织、存储和管理数据的仓库。
每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数据。
我们也可以将数据存储在文件中,但是在文件中读写数据速度相对较慢。
所以,现在我们使用关系型数据库管理系统(RDBMS)来存储和管理大数据量。
所谓的关系型数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。
2. MySQL概述
2.1 MySQL 是什么?
MySQL是数据库管理系统中的一种,是市面上最流行的数据库管理软件之一。
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型和大型网站的开发都选择 MySQL 作为网站数据库。
2.2 MySQL 的特点
-
数据以表格的形式出现
-
每行为各种记录名称
-
每列为记录名称所对应的数据域
-
许多的行和列组成一张表单
-
若干的表单组成database
2.3 RDBMS 术语
-
数据库: 数据库是一些关联表的集合。
-
数据表: 表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。
-
列: 一列(数据元素) 包含了相同类型的数据, 例如邮政编码的数据。
-
行:一行(元组,或记录)是一组相关的数据,例如一条用户订阅的数据。
-
冗余:存储两倍数据,冗余降低了性能,但提高了数据的安全性。
-
主键:主键是唯一的。一个数据表中只能包含一个主键。你可以使用主键来查询数据。
-
外键:外键用于关联两个表。
-
复合键:复合键(组合键)将多个列作为一个索引键,一般用于复合索引。
-
索引:使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构。类似于书籍的目录。
-
参照完整性: 参照的完整性要求关系中不允许引用不存在的实体。与实体完整性是关系模型必须满足的完整性约束条件,目的是保证数据的一致性。
3. SQL
3.1 SQL 是什么?
SQL(Structured Query Language,结构化查询语言)是用于管理关系数据库的语言。
我们通过学习SQL语句,编写SQL语句,然后DBMS负责执行SQL语句,最终来完成数据库中数据的增删改查操作。
3.2 SQL 语言分类
-
DQL(Data Query Language,数据查询语言):用于
查询和检索数据。(SELECT 查询) -
DDL(Data Definition Language,数据定义语言):用于
定义数据库对象,如数据库、表、视图、索引等。(CREATE 创建、ALTER 修改、DROP 删除) -
DML(Data Manipulation Language,数据操纵语言):用于
操作数据库对象,如插入、删除、更新、查询等。(INSERT 新增、DELETE 删除、UPDATE 更新) -
DCL(Data Control Language,数据控制语言):用于
控制数据库对象,如事务、权限等。(GRANT 授权、REVOKE 移除权限) -
TCL(Transaction Control Language,事务控制语言):用于管理事务,如开始、提交、回滚等。(COMMIT 提交、ROLLBACK 回滚)
3.3 SQL 通用语法
- SQL语句可以单行或者多行书写,但是必须以分号(
默认分号,可以通过命令更改结尾符)结尾。 - SQL语句不区分大小写,关键字建议全部采用大写字母。
- SQL语句可以使用空格/缩进来增强语句的可读性。
- 注释:
- 单行注释:-- 注释内容 或 # 注释内容(
MySQL特有) - 多行注释:/* 注释内容 */
- 单行注释:-- 注释内容 或 # 注释内容(
4. MySQL 安装
4.1 安装MySQL
MySQL的安装包可以在官网下载,根据自己的系统版本选择下载。
-
下载指定版本的MySQL安装包后,直接按照说明安装即可。(注意这里是MySQL8.0以上的版本,所以启动服务名为
mysql80)


-
安装成功后,就可以通过命令行界面进入mysql命令行了。(密码在安装过程中自行设置)


-
此外,我们还需要配置环境变量,使得任何地方都可访问到数据库。在
path中加入MySQL的安装目录中的bin目录即可。

-
输出
show databases;命令,可以查看当前数据库列表。

4.2 安装MySQL图形化管理工具
MySQL的图形化管理工具有很多,如Navicat、SQLyog等。
这里以Navicat为例,下载安装Navicat后,连接到MySQL服务器即可。下载适合自己系统的版本即可,不再赘叙。(试用14天或者付费,也可自行搜索free,不再多说)
- 安装成功后,运行Nacvicat,选择连接到MySQL服务器

- 输入用户名和密码,进行测试连接,测试成功后点击确认即可正确连接,进入MySQL图形化管理工具。

- 新建查询,输入
SHOW DATABASES;,点击运行即可查看数据库列表。

5. MySQL 基本操作
5.1 命令行连接数据库
我们可以使用命令行或图形化工具连接到MySQL服务器,连接成功后,就可以执行SQL语句来操作数据库。使用图形化工具连接很方便,安装过程中已经演示,此处不再演示连接过程。
这里主要说明命令行连接操作。
连接数据库的命令如下:
mysql -h 主机名 -u 用户名 -p 密码
参数说明:
-h : 指定客户端所要登录的 MySQL 主机名, 登录本机(localhost 或 127.0.0.1)该参数可以省略;
-u : 登录的用户名;
-p : 告诉服务器将会使用一个密码来登录, 如果所要登录的用户名密码为空, 可以忽略此选项。
-P : 指定 MySQL 连接的端口(一般远程才会使用)
如果我们要登录本机的 MySQL 数据库,只需要输入以下命令即可:(此处使用的是root用户,如果想用其他用户登录,请修改用户名和密码)
mysql -u root -p
按回车确认, 如果安装正确且 MySQL 正在运行, 会得到以下响应:
Enter password:
若密码存在, 输入密码登录, 不存在则直接按回车登录。登录成功后你将会看到 Welcome to the MySQL monitor... 的提示语。
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is xxx
此时就已经正确连接到 MySQL 服务器了,可以输入 exit 或 quit 退出连接。
5.2 DDL(数据定义语言)
DDL(Data Definition Language,数据定义语言)用于定义数据库对象,主要操作的对象就是数据库,表,字段等。
5.2.1 查询
SHOW DATABASES [like '%数据库名%'];查看当前连接的MySQL服务器上的所有数据库名,([]内的%表示模糊查询,可省略)。
输入SHOW DATABASES;, 得到以下结果:
Database
information_schema
book
carrental
invitationmanage
jdbc
mysql
performance_schema
sys
输入SHOW DATABASES like '%rent%';, 得到以下结果:
Database (%rent%)
carrental
注意:第一行Database表示字段名,从第二行开始才是具体的数据库名。当MySQL在创建一个数据库时,就会在MySQL的安装目录下的data目录中生成和该数据库同名的目录。
USE 数据库名;选择当前连接的数据库。输入USE book;, 选择当前连接的数据库为book。
注意:USE命令是用来选择当前连接的数据库的,只有在选择了数据库后,才能执行后续对应数据库中的SQL语句。
SHOW TABLES [FROM 数据库名];查看数据库中的所有表名。
输入SHOW TABLES;, 得到以下结果:
Tables_in_book
account
bookinfo
hotel
order
user
输入SHOW TABLES FROM book;, 得到以下结果:
Tables_in_book
account
bookinfo
hotel
order
user
注意:第一行Tables_in_book表示字段名,从第二行开始才是具体的表名。[]内的FROM 数据库名表示指定数据库名,可省略,如果不指定,则默认选择当前连接的数据库,即USE指定的数据库。如果没有使用USE命令选择数据库,则会报错,Query : show tables Error Code : 1046 No database selected
SHOW CREATE DATABASE 数据库名;查看数据库的创建语句。
输入SHOW CREATE DATABASE book;, 得到以下结果:
Database Create Database
book CREATE DATABASE `book` /*!40100 DEFAULT CHARACTER SET utf8 */
SHOW CREATE TABLE 表名;查看表的创建语句。
输入SHOW CREATE TABLE bookinfo;, 得到以下结果:
Table Create Table
bookinfo CREATE TABLE `bookinfo` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(40) NOT NULL,
`author` varchar(40) NOT NULL,
`desc` varchar(200) DEFAULT NULL,
`price` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8
SHOW COLUMNS FROM 表名;查看表中的字段信息。
输入SHOW COLUMNS FROM bookinfo;, 得到以下结果:
Field Type Null Key Default Extra
id int(11) NO PRI \N auto_increment
name varchar(40) NO \N
author varchar(40) NO \N
desc varchar(200) YES \N
price double YES \N
DESC 表名;查看表中的字段信息。
输入DESC bookinfo;, 得到以下结果:
Field Type Null Key Default Extra
id int(11) NO PRI \N auto_increment
name varchar(40) NO \N
author varchar(40) NO \N
desc varchar(200) YES \N
price double YES \N
注意:DESC命令和SHOW COLUMNS命令的作用相同,都是查看表中的字段信息。
SHOW INDEX FROM 表名;查看表中的索引信息。
输入SHOW INDEX FROM bookinfo;, 得到以下结果:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
bookinfo 0 PRIMARY 1 id A 9 \N \N BTREE
注意:SHOW INDEX命令可以查看表中的索引信息,包括主键索引、唯一索引、普通索引等。
SHOW STATUS;查看服务器状态,这里只关注主要的几个即可。
| 参数 | 描述 |
|---|---|
| Aborted_clients | 由于客户端没有正确关闭连接导致的已放弃的连接数。 |
| Aborted_connects | 尝试已经失败的MySQL服务器的连接次数。 |
| Connections | 尝试连接MySQL服务器的次数。 |
| Created_tmp_tables | 当执行语句时,已经被创建的临时表的数量。 |
| Key_read_requests | 请求从缓存读入一个键值的次数。 |
| Key_reads | 从物理磁盘读取一个键值的次数。 |
| Not_flushed_delayed_rows | 在INSERT DELAY队列中等待写入的行的数量。 |
| Open_tables | 打开表的数量。 |
| Open_files | 打开文件的数量。 |
| Open_streams | 打开流的数量(主要用于日志记录)。 |
| Opened_tables | 已经打开的表的数量。 |
| Questions | 发往服务器的查询的数量。 |
| Slow_queries | 要超时超过long_query_time的查询数量。 |
| Threads_connected | 当前打开的连接数。 |
| Threads_running | 不在休眠状态的线程数量。 |
| Uptime | 服务器工作了多少秒。 |
SHOW VARIABLES;查看服务器的系统变量。因为变量过多,所以不再展示,自行输入查看即可。
输入SHOW VARIABLES LIKE '%char%';查看MySQL服务器的编码方式,得到以下结果:
Variable_name Value
character_set_client utf8
character_set_connection utf8
character_set_database utf8
character_set_filesystem binary
character_set_results utf8
character_set_server utf8
character_set_system utf8
character_sets_dir D:\\soft\\mysql80\\mysql80\\share\\charsets\\
注意:SHOW VARIABLES命令可以查看服务器的系统变量,包括全局变量SHOW GLOBAL VARIABLES和会话变量SHOW SESSION VARIABLES。
SHOW PROCESSLIST;查看服务器的连接信息。
输入SHOW PROCESSLIST;,得到以下结果:
Id User Host db Command Time State Info
16 root localhost:21696 \N Sleep 2696 \N
20 root localhost:24554 book Query 0 starting show processlist
21 root localhost:24555 \N Sleep 1021 \N
23 root localhost:25068 book Sleep 634 \N
24 root localhost:25069 book Sleep 240 \N
注意:SHOW PROCESSLIST命令可以查看服务器的连接信息,包括Id、User、Host、db、Command、Time、State、Info。
SHOW TABLE STATUS FROM 数据库名;查看数据库中表的状态。
输入SHOW TABLE STATUS FROM book;,得到以下结果:

SHOW GRANTS FOR 用户名@主机名;查看用户的权限。显示的是授权语句。
输入SHOW GRANTS FOR root@localhost;,得到以下结果:
Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION
SELECT DATABASE();查看当前连接的数据库名。
输入SELECT DATABASE();,得到以下结果:
database()
book
SHOW ENGINES;查看支持的引擎。
输入SHOW ENGINES;,得到以下结果:

| 引擎 | 支持 | 注释 | 事务支持 | XA支持 | 保存点支持 | 主要特点 |
|---|---|---|---|---|---|---|
| InnoDB | 默认 | 支持事务 | 是 | 是 | 是 | InnoDB是MySQL的默认存储引擎,支持高并发、高可靠性,适合大多数生产环境。 - 事务支持:支持ACID特性的事务,保证数据的一致性和可靠性。 - 外键约束:支持外键约束,保证数据完整性。 - 行级锁定:采用行级锁定,适合高并发的写操作。 - MVCC:支持多版本并发控制,提高并发性能(更多,请参考: MySQL中的MVCC)。 - 崩溃恢复:具有自动崩溃恢复功能,通过重做日志和回滚日志保证数据完整性。 |
| MyISAM | 是 | MyISAM存储 | 否 | 否 | 否 | MyISAM是一种非事务性存储引擎,适用于读多写少的应用场景。 - 表级锁定:采用表级锁定,适合读取多于写入的场景。 - 全文索引:支持全文索引,适合全文检索。 - 压缩表:支持表压缩,节省存储空间。 - 高插入速度:插入数据速度较快。 |
| MEMORY | 是 | 基于哈希的存储 | 否 | 否 | 否 | MEMORY存储引擎将数据存储在内存中,适用于需要快速访问的小数据集。 - 高性能:所有数据存储在内存中,访问速度极快。 - 非持久化:数据在服务器重启时会丢失。 - 表级锁定:采用表级锁定。 |
| BLACKHOLE | 是 | /dev/null存储 | 否 | 否 | 否 | BLACKHOLE引擎不保存数据,适合用于复制。 - 不返回结果:读写均没有实际数据返回。 |
| CSV | 是 | CSV存储 | 否 | 否 | 否 | CSV存储引擎将数据存储在 CSV 文件中,适用于与外部系统的数据交换。 - 数据交换:数据以 CSV 格式存储,方便与其他应用进行数据交换。 -简单结构:每个表对应一个 CSV 文件。 - 无索引:不支持索引。 |
| ARCHIVE | 是 | 归档存储 | 否 | 否 | 否 | ARCHIVE 存储引擎适用于存储大量的历史数据,数据只支持插入和查询操作。 - 压缩存储:数据进行压缩存储,节省空间。 - 只支持插入和查询:不支持更新和删除操作。 - 高写入性能:适合大数据量的插入操作。 |
| PERFORMANCE | 是 | 性能优化存储 | 否 | 否 | 否 | PERFORMANCE引擎主要用于性能优化,适合读频繁的场景。 |
| FEDERATED | 否 | 联邦存储 | - | - | - | FEDERATED引擎允许访问远程数据库,但不存储数据。 |
注意:
在MySQL5.5版本以前MySQL默认的使用MyISAM作为默认的引擎,之后使用额是InnoDB作为默认的引擎。
XA支持
- 定义:XA是一种分布式事务协议,旨在确保在多资源环境中事务的一致性。
- 特点:
它允许在多个事务处理系统之间进行原子操作。在XA协议下,所有参与者必须要么全部成功(提交事务),要么全部失败(回滚事务)。
适用于分布式系统环境,可以帮助开发者管理跨多个数据库的事务。
保存点支持
- 定义:保存点是事务中的一个标记,用于在长事务中标识特定的状态。这使得用户可以在整个事务中进行部分回滚。
- 特点:
支持在事务执行过程中创建多个保存点,如果条目处理失败,可以回滚到特定的保存点,而不是回滚整个事务。
提高了灵活性和控制力,特别是在执行复杂操作时,有助于提升应用的稳定性和性能。
总结: XA支持适合需要分布式事务处理的场景,而保存点支持则适合需要在复杂事务中实现部分回滚的需求。二者都是确保数据一致性和完整性的重要功能。
5.2.2 创建
CREATE DATABASE创建数据库
CREATE DATABASE [IF NOT EXISTS] 数据库名 [DEFAULT CHARACTER SET 字符集][COLLATE 排序规则];
输入CREATE DATABASE MyDB;, 创建名为mydb的数据库。
CREATE DATABASE MyDB
> OK
> 时间: 0.001s
在输入SHOW DATABASES;时,可以看到mydb已经存在,并且是不区分大小写的
Database
information_schema
book
carrental
jdbc
mydb
对于已经存在的数据库,不能再创建。此时我们再输入CREATE DATABASE MyDB;,由于数据库已经存在,因此会提示错误:
CREATE DATABASE MyDB
> 1007 - Can't create database 'mydb'; database exists
如果我不知道数据库是否存在,可以使用IF NOT EXISTS选项,这样如果数据库不存在,则会自动创建数据库,输入CREATE DATABASE IF NOT EXISTS MyDB2;, 得到以下结果:
CREATE DATABASE IF NOT EXISTS MyDB2
> OK
> 时间: 0.001s
此时再输入SHOW DATABASES;,可以看到MyDB2已经创建好了。
Database
information_schema
book
carrental
mydb
mydb2
还可以设置字符集和排序规则
| 字符集 | 定义 & 用途 | 支持字符范围 | 典型应用场景 | 存储需求 | 排序规则 |
|---|---|---|---|---|---|
| latin1 | ISO-8859-1字符集,主要用于西欧语言。 | 支持256个字符,主要是拉丁字母。 | 主要用于英语、西欧语言的应用。 | 每字符1字节 | latin1_swedish_ci(不区分大小写) |
| utf8 | UTF-8编码标准,广泛支持多种语言。 | 支持最多3个字节,涵盖所有Unicode字符。有些字符需4个字节(如Emoji)。 | 多语言网站和应用,尤其是亚洲语言和特殊字符使用场合。 | 每字符1到3字节 | utf8_general_ci(一般不区分大小写) |
| utf8mb4 | 扩展的UTF-8,支持所有Unicode字符。 | 支持4个字节,包含所有Unicode字符。 | 涉及Emoji和各种特殊字符需要的应用(如社交媒体) | 每字符1到4字节 | utf8mb4_unicode_ci(支持多语言,不区分大小写) |
| ascii | ASCII字符集,仅支持基本拉丁字符。 | 支持128个字符,主要是英文字母和数字。 | 只需要处理英语的应用、配置文件等。 | 每字符1字节 | ascii_general_ci(不区分大小写) |
| utf16 | UTF-16编码标准,适用于Unicode字符。 | 支持2个或4个字节,全面支持Unicode。 | Java、Windows系统中常用。 | 每字符2或4字节 | utf16_unicode_ci(支持多语言,不区分大小写) |
输入CREATE DATABASE MyDB3 DEFAULT CHARACTER SET utf8mb4;即可。
注意:字符集根据实际情况选择,utf8mb4可以支持更多的Unicode字符,但也会占用更多的存储空间。创建数据库时未指定字符集,则默认字节集为uft8。
CREATE TABLE创建表
CREATE TABLE 表名 (
列名1 字段类型 [约束],
列名2 字段类型 [约束],
...
[表约束]
);
- 表名:要创建的表的名称,符合命名规则且在同一数据库中必须唯一。
- 列名:每一列的名称,必须符合命名规则(如字母、数字和下划线)。
- 字段类型:每一列的数据类型,如int、varchar、datetime等。
- 约束:对列进行限制,如NOT NULL、UNIQUE、DEFAULT、CHECK、PRIMARY KEY等。
- 表约束:对表进行限制,如PRIMARY KEY、FOREIGN KEY、UNIQUE等。
在创建表前,一定要先通过USE 数据库名;选择要操作的数据库。这里选择USE mydb2;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY, -- 用户ID,主键,自增长
username VARCHAR(50) NOT NULL UNIQUE, -- 用户名,不能为空,唯一
password VARCHAR(100) NOT NULL, -- 密码,不能为空
email VARCHAR(100) NOT NULL UNIQUE, -- 邮箱,不能为空,唯一
-- 自行删除上一行,保留修正后
email VARCHAR(100) NOT NULL UNIQUE -- 邮箱,不能为空,唯一
);
注意创建表最后一句,email VARCHAR(100) NOT NULL UNIQUE, -- 邮箱,不能为空,唯一,这里是表的最后一句,所以不应该有逗号存在,要删除掉,不然会报语法错误。
这时可以使用SHOW TABLES;查看数据库中的表:
Tables_in_mydb2
users
创建表同创建数据库,如果已存在再去创建,则会发生错误,ERROR 1050 (42S01): Table 'users' already exists,因此同样可以使用IF NOT EXISTS选项。
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE
);
注意:创建表时,如果指定了AUTO_INCREMENT属性,则该列必须为主键。除了数据库和表之外,还可以创建索引等,属于高级话题,这里不做展开。
5.2.3 修改
ALTER TABLE修改表结构
ALTER TABLE 表名 [ADD | DROP | MODIFY | CHANGE] 列名 字段类型 [约束];
- ADD:添加列。
- DROP:删除列。
- MODIFY:修改列定义,数据类型或约束。
- CHANGE:修改列名和定义。
为users表新增一个age列,类型为int,约束为非空
ALTER TABLE users ADD age INT NOT NULL;
使用DESC users;查看表结构:
id int(11) NO PRI auto_increment
username varchar(50) NO UNI
password varchar(100) NO
email varchar(100) NO UNI
age int(11) NO
将age列删除掉
ALTER TABLE users DROP age;
使用DESC users;查看表结构:
id int(11) NO PRI auto_increment
username varchar(50) NO UNI
password varchar(100) NO
email varchar(100) NO UNI
修改email列的定义,更改类型为CHAR(50)
ALTER TABLE users MODIFY email CHAR ( 50 ) NOT NULL;
使用DESC users;查看表结构:
...
email char(50) NO UNI
修改email列的名称为user_email,不改变其他
ALTER TABLE users CHANGE email user_email CHAR ( 50 ) NOT NULL;
使用DESC users;查看表结构:
...
user_email char(50) NO UNI
RENAME TABLE重命名表
ALTER TABLE 旧表名 RENAME TO 新表名; (TO 可省略)
ALTER TABLE users RENAME TO userinfo
SHOW TABLES;查看数据库中的表:
Tables_in_mydb2
userinfo
5.2.4 删除
DROP TABLE删除表
DROP TABLE [IF EXISTS] 表名;
- IF EXISTS:可选,如果表不存在,则忽略错误。
删除名为 users 的表:
DROP TABLE users;
如果不确定表是否存在,可以使用:
DROP TABLE IF EXISTS users;
TRUNCATE TABLE清空表
TRUNCATE TABLE 表名;
TRUNCATE TABLE命令用于快速删除表中所有记录,但保留表结构。
清空 users 表中的所有数据:
TRUNCATE TABLE users;
DROP DATABASE删除数据库
DROP DATABASE [IF EXISTS] 数据库名;
- IF EXISTS:可选,如果数据库不存在,则忽略错误。
删除名为 mydb 的数据库:
DROP DATABASE mydb;
如果不确定数据库是否存在,可以使用:
DROP DATABASE IF EXISTS mydb;
注意:
- 使用
DROP TABLE后,表及其所有数据将永久删除,无法恢复。 TRUNCATE TABLE是一种DDL操作,不能通过 ROLLBACK 回滚。如果清空表后想恢复数据,无法恢复。此操作比 DELETE 命令执行得更快,因为不记录每一行的删除操作,直接重置表的状态。- 使用
DROP DATABASE后,数据库及其所有数据和表将永久删除,无法恢复。
5.3 数据类型
MySQL 支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。
- 数值数据类型:TINYINT 、SMALINT 、MEDIUMINT 、INT 、BIGINT 、FLOAT 、DOUBLE 、DECIMAL
- 日期/时间类型:YEAR 、TIME 、DATE 、DATETIME 、TIMESTAMP
- 字符串类型:CHAR 、VARCHAR 、BINARY 、VARBINARY 、BLOB 、TEXT 、ENUM 、SET
5.3.1 数值数据类型
包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL 和 NUMERIC),以及近似数值数据类型(FLOAT、REAL 和 DOUBLE PRECISION)。
关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。
BIT数据类型保存位字段值,并且支持 MyISAM、MEMORY、InnoDB 和 BDB表。
作为 SQL 标准的扩展,MySQL 也支持整数类型 TINYINT、MEDIUMINT 和 BIGINT。
| 类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |
|---|---|---|---|---|
| TINYINT | 1 Byte | -128 至 127 | 0 至 255 | 小整数值 |
| SMALLINT | 2 Bytes | -32,768 至 32,767 | 0 至 65,535 | 大整数值 |
| MEDIUMINT | 3 Bytes | -8,388,608 至 8,388,607 | 0 至 16,777,215 | 大整数值 |
| INT / INTEGER | 4 Bytes | -2,147,483,648 至 2,147,483,647 | 0 至 4,294,967,295 | 大整数值 |
| BIGINT | 8 Bytes | -9,223,372,036,854,775,808 至 9,223,372,036,854,775,807 | 0 至 18,446,744,073,709,551,615 | 极大整数值 |
| FLOAT | 4 Bytes | -3.402823466E+38 至 -1.175494351E-38、0、1.175494351E-38 至 3.402823466E+38 | 0、1.175494351E-38 至 3.402823466E+38 | 单精度浮点数 |
| DOUBLE | 8 Bytes | -1.7976931348623157E+308 至 -2.2250738585072014E-308、0、2.2250738585072014E-308 至 1.7976931348623157E+308 | 0、2.2250738585072014E-308 至 1.7976931348623157E+308 | 双精度浮点数 |
| DECIMAL(M, D) | 根据 M 和 D 的值 | 依赖于 M 和 D 的值 | 依赖于 M 和 D 的值 | 小数值 |
5.3.2. 日期和时间类型
表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。
每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。
| 类型 | 大小 (Bytes) | 范围 | 格式 | 用途 |
|---|---|---|---|---|
| DATE | 3 | 1000-01-01 至 9999-12-31 | YYYY-MM-DD | 日期值 |
| TIME | 3 | '-838:59:59' 至 '838:59:59' | HH:MM:SS | 时间值或持续时间 |
| YEAR | 1 | 1901 至 2155 | YYYY | 年份值 |
| DATETIME | 8 | '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59' | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
| TIMESTAMP | 4 | '1970-01-01 00:00:01' UTC 到 '2038-01-19 03:14:07' UTC | YYYY-MM-DD HH:MM:SS | 混合日期和时间值,时间戳 |
5.3.3 字符串类型
字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。描述了这些类型如何工作以及如何在查询中使用这些类型。
| 类型 | 大小 (Bytes) | 用途 |
|---|---|---|
| CHAR | 0-255 | 定长字符串 |
| VARCHAR | 0-65,535 | 变长字符串 |
| TINYBLOB | 0-255 | 不超过 255 字节的二进制字符串 |
| TINYTEXT | 0-255 | 短文本字符串 |
| BLOB | 0-65,535 | 二进制形式的长文本数据 |
| TEXT | 0-65,535 | 长文本数据 |
| MEDIUMBLOB | 0-16,777,215 | 二进制形式的中等长度文本数据 |
| MEDIUMTEXT | 0-16,777,215 | 中等长度文本数据 |
| LONGBLOB | 0-4,294,967,295 | 二进制形式的极大文本数据 |
| LONGTEXT | 0-4,294,967,295 | 极大文本数据 |
注意:
- char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符。
- CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。
- BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。、
- BLOB 是一个二进制大对象,可以容纳可变数量的数据。有 4 种 BLOB 类型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。
- 有 4 种 TEXT 类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。
5.3.4 案例

个人解答:
CREATE TABLE users (
id INT auto_increment PRIMARY KEY COMMENT '编号',
employeeNo CHAR ( 10 ) NOT NULL UNIQUE COMMENT '工号',
employeeName VARCHAR ( 10 ) NOT NULL COMMENT '姓名',
sex CHAR ( 1 ) COMMENT '性别' CHECK (
sex IN ( '男', '女' )),
age TINYINT UNSIGNED COMMENT '年龄非负',
cardNo CHAR ( 18 ) COMMENT '身份证号',
hireDate DATE COMMENT '入职时间'
);
注意:
sex CHAR ( 1 ) COMMENT '性别' CHECK (sex IN ( '男', '女' ))这里使用了CHECK约束限制输入必须为男或女其中一个,使用CHECK时,必须确保为在列最后。
5.4 DML (数据操作语言)
DML 是数据操纵语言,用于操作数据库中的数据。包括
INSERT、UPDATE、DELETE,即新增、更新、删除。
5.4.1 INSERT
INSERT 语句用于向表中插入新数据行。语法如下:
INSERT INTO 表名 (字段名1,字段名2) VALUES (值1,值2);
其中,字段名即为列名,值即为插入的数据。
INSERT INTO users ( employeeNo, employeeName, sex ) VALUES ('xxxa456852','李四','男');
我们可以填写表中的字段,来进行指定字段的数据插入,如果我们想要插入全部字段的数据,则可以省略字段名,直接使用values关键字。
INSERT INTO users VALUES (2,'dass123456', '张三', '男', 25, '123456789012345678', '2010-01-01');
接下来在数据库中查询一下刚才插入的数据,可以看到刚才插入的数据已经成功插入。
SELECT * FROM users;
1 xxxa456852 李四 男
2 dass123456 张三 男 25 123456789012345678 2010-01-01
上面演示了单条数据插入,那如果,我们想要一次插入多个数据,需要重复编写INSERT INTO语句,会显得很麻烦,这时我们可以使用INSERT INTO语句的批量插入功能。
INSERT INTO 表名 (字段名1,字段名2) VALUES (值1,值2),(值1,值2),(值1,值2);
其实就是在单条插入的基础上,多条数据插入,中间用逗号隔开。同样,插入全部字段时,可以省略字段名。
-- 指定字段名进行批量插入
INSERT INTO users ( employeeNo, employeeName, sex ) VALUES
('xxxa110221','洞主','男'),
('xxxa120331','凯哥','女'),
('xxxa135021','阿松','男');
# 全部字段进行批量插入
INSERT INTO users VALUES
(9,'dass321552', '辛蒂', '女', 23, '123412345612345678', '2021-09-04'),
(10,'dass326145', '王海', '男', 27, '123412312312345678', '2019-07-06'),
(11,'dass314215', '凯蒂', '女', 21, '123465447812345678', '2023-04-09');
再查询数据库,可以看到数据也正确插入了。
6 xxxa110221 洞主 男
7 xxxa120331 凯哥 女
8 xxxa135021 阿松 男
9 dass321552 辛蒂 女 23 123412345612345678 2021-09-04
10 dass326145 王海 男 27 123412312312345678 2019-07-06
11 dass314215 凯蒂 女 21 123465447812345678 2023-04-09
注意:
- 插入数据时,指定的字段顺序需要与值的顺序是一一对应的。
- 字符串和日期型数据应该包含在单/双引号中。
- 插入的数据大小,应该在字段的规定范围内
- 批量插入时,如果插入的数据中有重复的主键值,则会报错。
- 如果主键为自增字段,则插入数据时,主键字段可以填写
NULL,系统会自动生成主键值。
5.4.2 UPDATE
UPDATE 语句用于更新表中的数据。语法如下:
UPDATE 表名 SET 字段名1=新值1,字段名2=新值2 [WHERE 条件];
UPDATE是删除关键字,FROM子句指定要删除数据来源的表名,WHERE子句用于指定更新条件,如果省略WHERE子句,则会更新表中所有数据,根据需求不同,慎用。
这里我们将上面所有员工的入职时间,全部改为2021-09-09
UPDATE users SET hireDate = '2021-09-09';
根据需求,要修改所有员工,所以我们没有添加WHERE子句
6 xxxa110221 洞主 男 2021-09-09
7 xxxa120331 凯哥 女 2021-09-09
8 xxxa135021 阿松 男 2021-09-09
9 dass321552 辛蒂 女 23 123412345612345678 2021-09-09
10 dass326145 王海 男 27 123412312312345678 2021-09-09
11 dass314215 凯蒂 女 21 123465447812345678 2021-09-09
那接下来,我们修改名为阿松的员工,入职时间改为2022-06-13
UPDATE users SET hireDate = '2022-06-13' WHERE employeeName = '阿松';
再次查询,可以看到,已经成功修改了阿松的入职时间,并且其他人的入职时间没有发生改变,因为我们采用WHERE子句指定了更新条件,即员工名为阿松。
6 xxxa110221 洞主 男 2021-09-09
7 xxxa120331 凯哥 女 2021-09-09
8 xxxa135021 阿松 男 2022-06-13
9 dass321552 辛蒂 女 23 123412345612345678 2021-09-09
10 dass326145 王海 男 27 123412312312345678 2021-09-09
11 dass314215 凯蒂 女 21 123465447812345678 2021-09-09
5.4.3 DELETE
DELETE 语句用于删除表中的数据。语法如下:
DELETE FROM 表名 [WHERE 条件];
同
UPDATE语句,DELETE是删除关键字,FROM子句指定要删除数据来源的表名,WHERE子句用于指定删除条件,如果省略WHERE子句,则会删除表中所有数据,根据需求不同,慎用。
这里我们演示一下删除名为阿松的员工。
DELETE FROM users WHERE employeeName = '阿松';
从查询结果中可以看出,阿松的员工数据已经被删除了。
6 xxxa110221 洞主 男 2021-09-09
7 xxxa120331 凯哥 女 2021-09-09
9 dass321552 辛蒂 女 23 123412345612345678 2021-09-09
10 dass326145 王海 男 27 123412312312345678 2021-09-09
11 dass314215 凯蒂 女 21 123465447812345678 2021-09-09
注意:
- DELETE 可以删除行数据,但是无法删除某一个字段的数据,需要使用UPDATE语句。
5.5 DCL (数据控制语言)
DCL 是数据控制语言,用于控制数据库的访问权限、安全性、完整性等。包括
GRANT、REVOKE等。
这里DCL主要介绍一下GRANT和REVOKE的用法。因为这两个命令是都是针对用户的,所以我们需要先了解用户相关命令。
5.5.1 用户相关命令
数据库的用户分为两类:
- 系统用户:由系统管理员创建,具有最高权限,可以访问所有数据库对象,可以创建其他用户。常见的就是
root用户。 - 数据库用户:由数据库管理员创建,具有数据库对象权限,可以访问指定的数据库对象。
- 查询用户
我们可以查询当前数据库中,存在的用户,首先选择
mysql数据库,然后查询user表。
USE mysql;
SELECT * from user;
可以看到,当前数据库中存在的用户。

- root:超级管理员用户,拥有最高权限,几乎可以对数据库进行任何操作,包括创建和删除数据库、表,管理用户权限等。在生产环境中,使用 root 用户需要特别谨慎,因为不当操作可能导致数据丢失或安全风险。
- mysql.session:这个用户主要用于内部系统操作,用于管理 MySQL 服务器的会话。它的权限非常有限,仅用于 MySQL 内部的会话管理,不能用于一般的数据库操作。
- mysql.sys:mysql.sys 用户用于访问 MySQL 系统表和视图,提供了一种安全的方式来查询系统元数据。它的权限也受到严格限制,主要用于支持 MySQL 系统的一些内部功能和管理工具。
- z521xxx 创建的数据库用户。
- localhost:表示该用户只能从运行 MySQL 服务器的本地机器进行连接。例如图片中的 root、mysql.session、mysql.sys 用户的 Host 为 localhost,意味着这些用户只能在服务器本机登录并操作数据库,这增加了安全性,因为它们无法从远程机器访问数据库,防止外部非法访问。
- %:这是一个通配符,表示该用户可以从任何主机连接到 MySQL 服务器。图片中 z521xxx 用户的 Host 是 %,意味着这个用户可以在任何网络环境下尝试连接到该 MySQL 服务器,只要提供正确的用户名和密码,不过这种设置也会带来一定安全风险,需要在防火墙等方面做好安全措施。
- 创建用户
创建的用户即为数据库中的用户,通常使用
root用户进行创建。语法如下:
CREATE USER 用户名@主机名 IDENTIFIED BY 密码;
接下来,我们创建一个名为user1的用户,密码为123456,并且只允许从本地登录。同时创建一个允许从任何主机登录的user2用户。
-- user1 只允许从本地登录
CREATE USER 'user1' @'localhost' IDENTIFIED BY '123456';
# user2 允许从任何主机登录
CREATE USER 'user2' @'%' IDENTIFIED BY '123456';
接下来再查询一下user表,可以看到,新的用户已经创建成功。
localhost user1 ...
% user2 ...
- 查询用户权限
直接使用SHOW GRANTS FOR 'user1' @'localhost';即可查询用户user1的当前所拥有权限,并通过SQL语句展示。
GRANT USAGE ON *.* TO 'user1'@'localhost'
- 修改用户
修改用户的密码,语法如下:
ALTER USER 用户@主机名 IDENTIFIED WITH 加密方式(通常是mysql_native_password) BY 新密码;
修改user1用户的密码为123456zz
ALTER USER 'user1' @'localhost' IDENTIFIED WITH mysql_native_password BY '123456zz';
- 删除用户
删除用户的语法如下:
DROP USER 用户名@主机名;
删除user2用户
DROP USER 'user2'@'%';
5.5.2 GRANT
GRANT 语句用于向用户或角色授权权限。语法如下:
GRANT 权限列表 ON 数据库名.表名 TO 用户名@主机名 [WITH GRANT OPTION];
GRANT关键字用于向用户或角色授权权限,ON子句指定要授予权限的数据库对象,TO子句指定授予权限的用户或角色。
WITH GRANT OPTION作用是允许被授权的用户将自己拥有的权限再授予其他用户。也就是说,当你给某个用户授权时带上了 WITH GRANT OPTION,这个用户不仅可以使用这些权限,还能把这些权限分配给其他用户。
举例来说,假设现在有两个用户:user1 和 user2,首先,以管理员身份(比如 root 用户)登录 MySQL ,给 user1 用户授予对 mydb2 数据库中所有表的 SELECT 权限,并允许 user1 用户将这个权限授予其他用户,执行语句如下:
GRANT SELECT ON mydb2.* TO 'user1' @'localhost' WITH GRANT OPTION;
然后,给 user2 用户授予对 mydb2 数据库中 users 表的 SELECT 权限,执行语句如下:
GRANT SELECT ON mydb2.users TO 'user2' @'localhost';
这样,user1 和 user2 两个用户都有了对 mydb2 数据库中 users 表的 SELECT 权限,并且 user1 用户可以将这个权限授予其他用户。
常用的权限列表有:
- SELECT:允许用户读取数据库中的数据。
- INSERT:允许用户向数据库中插入数据。
- UPDATE:允许用户更新数据库中的数据。
- DELETE:允许用户删除数据库中的数据。
- CREATE:允许用户创建数据库对象,如表、视图、索引等。
- DROP:允许用户删除数据库对象。
- ALTER:允许用户修改数据库对象,如表结构、视图定义等。
这里我们演示一下向用户user1授予mydb2数据库中users表的SELECT权限。
-- 授予mydb2数据库中users表的SELECT权限
GRANT SELECT ON mydb2.users TO 'user1' @'localhost';
-- 授予mydb2数据库中所有表的SELECT权限
# GRANT SELECT ON mydb2.* TO 'user1' @'localhost';
-- 授予所有数据库的SELECT权限
# GRANT SELECT ON *.* TO 'user1' @'localhost';
-- 授予mydb2数据库中users表的SELECT,INSERT,UPDATE权限
# GRANT SELECT,INSERT,UPDATE ON mydb2.users TO 'user1' @'localhost';
-- 授予mydb2数据库中users表的所有权限
# GRANT ALL ON mydb2.users TO 'user1' @'localhost';
授予了权限以后,查询一下user1的权限
SHOW GRANTS FOR 'user1' @'localhost';
可以看到,user1已经拥有了mydb2.users表的SELECT权限。
GRANT USAGE ON *.* TO 'user1'@'localhost'
GRANT SELECT ON `mydb2`.`users` TO 'user1'@'localhost'
5.5.3 REVOKE
REVOKE 语句用于回收用户或角色的权限。语法如下:
REVOKE 权限列表 ON 数据库名.表名 FROM 用户名@主机名;
REVOKE关键字用于回收用户或角色的权限,ON子句指定要回收权限的数据库对象,FROM子句指定回收权限的用户或角色。
这里我们演示一下回收用户user1对mydb2.users表的SELECT权限。
REVOKE SELECT on mydb2.users from 'user1'@'localhost';
查询一下user1的权限
SHOW GRANTS FOR 'user1' @'localhost';
可以看到,user1已经没有mydb2.users表的SELECT权限了。
GRANT USAGE ON *.* TO 'user1'@'localhost'
其余REVOKE就和GRANT同样,多个权限使用逗号间隔,所有数据库对象使用*.*表示,指定数据库所有表使用mydb2.*表示。
5.6 DQL (数据查询语言)
DQL 是数据查询语言,用于查询数据库中的数据。
DQL 主要就是使用SELECT语句来查询数据。这里大致分类为:
| 类型 | 描述 |
|---|---|
| 基本查询 | SELECT 用于选择要返回的字段,FROM 用于指定从哪个或哪些表中获取数据。 |
| 条件查询(WHERE) | WHERE 用于筛选满足特定条件的记录。 |
| 聚合函数 | 包括 count(计数)、max(最大值)、min(最小值)、avg(平均值)、sum(求和)等,用于对数据进行统计计算。 |
| 分组查询(GROUP BY) | GROUP BY 用于将数据按照指定字段进行分组。 |
| 排序查询(ORDER BY) | ORDER BY 用于对查询结果按照指定字段进行升序或降序排序。 |
| 分页查询(LIMIT) | LIMIT 用于限制返回结果的数量,实现分页功能。 |
接着了解一下SELECT语句的语法:
SELECT
字段列表
FROM
表名列表
[WHERE
条件列表]
[GROUP BY
分组字段列表]
[HAVING
分组后条件列表]
[ORDER BY
排序字段列表]
[LIMIT
分页参数]
| 字段 | 作用 |
|---|---|
| select | 后跟显示的列名(多列逗号分开) |
| from | 后跟表名(多个表逗号分开) |
| where | 后跟过滤条件的列 |
| group by | 后跟分组的列 |
| having | 后跟分组后的过滤聚合函数 |
| order by | 后跟排序的列(desc降序 默认:asc升序) |
| limit | 显示前几行 LIMIT M,N:跳过M行,显示一共N行 LIMIT Y OFFSET X: 跳过X行,显示一共Y行 |
| like %_ | 模糊查询 占位符:(%:任意长度字符 _:一个字符) |
| union | 多个结果集合并查询的功能 |
| union all | 多个结果集合并查询的功能,去重 |
| and | 并且 |
| not | 非 |
| or | 或者 |
| in | 与or相同 |
| between …and… | 在什么范围之内,包含边界值 |
| is not null | 查询非空值 |
| is null | 查询空值 |
| distinct | 查询结果不重复 |
5.6.1 基本查询
- 查询多个字段
-- 查询多个字段
SELECT 字段1, 字段2, 字段3 FROM 表名;
-- 查询所有字段
SELECT * FROM 表名;
(1) 查询users表中,员工号、员工姓名、性别
(2) 查询users表所有信息
-- (1)
SELECT employeeNo,employeeName,sex FROM users;
-- (2)
SELECT * FROM users;
查询得到的结果如下:
-- (1)
employeeNo employeeName sex
xxxa110221 洞主 男
xxxa120331 凯哥 女
dass321552 辛蒂 女
dass326145 王海 男
dass314215 凯蒂 女
--(2)
employeeNo employeeName sex age cardNo hireDate
6 xxxa110221 洞主 男 2021-09-09
7 xxxa120331 凯哥 女 2021-09-09
9 dass321552 辛蒂 女 23 123412345612345678 2021-09-09
10 dass326145 王海 男 27 123412312312345678 2021-09-09
11 dass314215 凯蒂 女 21 123465447812345678 2021-09-09
- 设置别名
SELECT 字段 [AS 别名] FROM 表名;
其中,AS关键字用于给字段设置别名,也可以省略不写,直接字段名后跟别名。
(1) 查询users表中,员工号、员工姓名、性别并设置别名
-- 使用AS关键字设置别名
SELECT employeeNo AS 员工编号,employeeName AS 员工姓名,sex AS 性别 FROM users;
-- 省略AS关键字设置别名
SELECT employeeNo 员工编号,employeeName 员工姓名,sex 性别 FROM users;
查询得到的结果如下:
-- 使用AS关键字设置别名
员工编号 员工姓名 性别
xxxa110221 洞主 男
xxxa120331 凯哥 女
dass321552 辛蒂 女
dass326145 王海 男
dass314215 凯蒂 女
-- 省略AS关键字设置别名
员工编号 员工姓名 性别
xxxa110221 洞主 男
xxxa120331 凯哥 女
dass321552 辛蒂 女
dass326145 王海 男
dass314215 凯蒂 女
- 去除重复记录
数据库中数据可能存在重复记录,使用DISTINCT关键字可以去除重复记录。
SELECT DISTINCT 字段 FROM 表名;
为了方便演示,我们假设users表中存在重复记录。将员工编号为dass326145的员工王海修改名字为凯哥,这样员工姓名就存在两个凯哥,便于展示。
UPDATE users SET employeeName = '凯哥' WHERE employeeNo = 'dass326145';
接下来我们先查询,员工表中的所有员工姓名:
SELECT employeeName FROM users;
可以看到,修改成功,存在重复姓名凯哥:
employeeName
洞主
凯哥
辛蒂
凯哥
凯蒂
接下来我们使用去重关键字DISTINCT,查询员工表中所有员工姓名,并去除重复记录:
SELECT DISTINCT employeeName FROM users;
可以看到,查询结果中没有重复记录:
employeeName
洞主
凯哥
辛蒂
凯蒂
接下来我们再使用去重关键字DISTINCT,查询员工表的员工姓名、员工工号,并去除重复记录:
SELECT DISTINCT employeeNo,employeeName FROM users;
查询结果如下:
employeeNo employeeName
xxxa110221 洞主
xxxa120331 凯哥
dass321552 辛蒂
dass326145 凯哥
dass314215 凯蒂
可以看到,我们使用了DISTINCT关键字,去除结果中重复记录,但是为什么,明明去重了,却还是有两个凯哥?
在使用 DISTINCT 关键字时,它是基于指定的所有列来判断是否重复的。在查询语句中,DISTINCT 会同时考虑 employeeNo(员工工号)和 employeeName(员工姓名)这两列的值。
虽然有两个员工姓名都是 “凯哥”,但从查询结果可以看到,他们的 employeeNo(员工工号)是不同的(xxxa120331 和 dass326145)。对于 DISTINCT 来说,只要这两列的组合值不完全一样,就不会被视为重复记录,所以会出现两个姓名相同但工号不同的员工记录都被保留下来的情况。也就是说,DISTINCT 去重是基于多列组合的唯一性,而不是仅针对某一列(如姓名列)进行去重。
5.6.2 条件查询
条件查询是指根据指定的条件来查询数据。
SELECT 字段 FROM 表名 WHERE 条件;
(1) 查询员工表中,所有男性员工信息
(2) 查询员工表中,员工身份证为null的员工信息
(3) 查询员工表中,员工编号为xxxa110221或xxxa120331的员工信息
(4) 查询员工表中,年龄在24到27岁之间的员工信息
(5) 查询员工表中,姓凯的员工信息
(6) 查询员工表中,员工号倒数第二位是1的员工信息
-- (1)
SELECT * FROM users WHERE sex = '男';
-- (2)
SELECT * FROM users WHERE cardNo is NULL;
-- (3)
# 使用or关键字 实现或
SELECT * FROM users WHERE employeeNo = 'xxxa110221' or employeeNo = 'xxxa120331';
# 使用in关键字 实现或
SELECT * FROM users WHERE employeeNo in ('xxxa110221', 'xxxa120331');
-- (4)
# 使用and 实现且
SELECT * FROM users WHERE age >=24 and age <= 27;
# 使用between and 实现范围区间
SELECT * FROM users WHERE age BETWEEN 24 and 27;
-- (5)
SELECT * FROM users WHERE employeeName like '凯%';
-- (6)
SELECT * FROM users WHERE employeeNo like '%1_';
查询结果如下:
-- (1)
6 xxxa110221 洞主 男 2021-09-09
10 dass326145 凯哥 男 27 123412312312345678 2021-09-09
-- (2)
employeeNo employeeName sex age cardNo hireDate
6 xxxa110221 洞主 男 2021-09-09
7 xxxa120331 凯哥 女 2021-09-09
-- (3)
employeeNo employeeName sex age cardNo hireDate
6 xxxa110221 洞主 男 2021-09-09
7 xxxa120331 凯哥 女 2021-09-09
6 xxxa110221 洞主 男 2021-09-09
7 xxxa120331 凯哥 女 2021-09-09
-- (4)
5 dass123456 张三 男 25 123456789012345678 2021-09-09
10 dass326145 凯哥 男 27 123412312312345678 2021-09-09
5 dass123456 张三 男 25 123456789012345678 2021-09-09
10 dass326145 凯哥 男 27 123412312312345678 2021-09-09
-- (5)
7 xxxa120331 凯哥 女 2021-09-09
10 dass326145 凯哥 男 27 123412312312345678 2021-09-09
11 dass314215 凯蒂 女 21 123465447812345678 2021-09-09
-- (6)
11 dass314215 凯蒂 女 21 123465447812345678 2021-09-09
5.6.3 聚合函数
在MySQL中,聚合函数用于对一组值执行计算,并返回单个值。
常见的聚合函数有:
- count():计算指定列的非空值的个数。
- max():计算指定列的最大值。
- min():计算指定列的最小值。
- avg():计算指定列的平均值。
- sum():计算指定列的总和。
(1) 查询员工表中,员工数量
(2) 查询员工表中,男性员工数量
(3) 查询员工表中,最大年龄、最小年龄、平均年龄
-- (1)
SELECT COUNT(*) FROM users;
-- (2)
SELECT COUNT(*) FROM users WHERE sex = '男';
-- (3)
SELECT MAX(age) 最大年龄,MIN(age) 最小年龄,AVG(age) 平均年龄 FROM users;
查询结果如下:
-- (1)
5
-- (2)
2
-- (3)
最大年龄 最小年龄 平均年龄
27 21 23.6667
5.6.4 分组查询
分组查询是指按照指定字段对数据进行分组,然后对分组进行聚合操作。主要使用的关键字为
GROUP BY以及筛选条件HAVING。
SELECT 字段 FROM 表名 [WHERE 条件] GROUP BY 分组字段 [HAVING 分组后条件];
注意WHERE和HAVING的区别:
- WHERE:在分组之前,对数据进行筛选,若不满足则不参与分组,并且不能判断聚合函数。
- HAVING:在分组之后,对满足的分组数据进行条件筛选,可以判断聚合函数。
假设有一个订单表,字段有订单号、客户姓名、客户手机号、订单金额、订单日期。
(1) 查询订单表中,每个客户的订单数量,订单总金额
(2) 查询订单表中,在'2024-10-09'日订单数量、订单总金额、订单平均金额的客户,并且订单数量要大于等于3
(3) 查询订单表中,订单总金额超过535的客户姓名,手机号
-- 创建表
CREATE TABLE orders(
orderNo char(11) PRIMARY KEY,
customerName varchar(20),
customerPhone varchar(11),
orderAmount decimal(10,2),
orderDate date
);
-- 插入数据
INSERT INTO orders VALUES
('SYY24100101','大海','13888886666','99.86','2024-10-01'),
('SYY24100102','爱卿','18666669999','18.21','2024-10-01'),
('SYY24100103','十一月','18888888888','189.38','2024-10-01'),
('SYY24100401','十一月','18888888888','59.14','2024-10-04'),
('SYY24100402','大海','13888886666','89.46','2024-10-04'),
('SYY24100701','十一月','18888888888','268.60','2024-10-07'),
('SYY24100702','爱卿','18666669999','354.78','2024-10-07'),
('SYY24100801','大海','13888886666','123.45','2024-10-08'),
('SYY24100901','爱卿','18666669999','67.89','2024-10-09'),
('SYY24100902','大海','13888886666','89.67','2024-10-09'),
('SYY24100903','爱卿','18666669999','32.45','2024-10-09'),
('SYY24100904','大海','13888886666','45.67','2024-10-09'),
('SYY24100905','爱卿','18666669999','62.35','2024-10-09'),
('SYY24100906','十一月','18888888888','43.16','2024-10-09'),
('SYY24100907','大海','13888886666','82.39','2024-10-09');
-- (1)
SELECT customerName 客户姓名,COUNT(*) 订单数量,SUM(orderAmount) 订单总金额 FROM orders GROUP BY customerName;
-- (2)
SELECT customerName 客户姓名,COUNT(*) 订单数量,SUM(orderAmount) 订单总金额,AVG(orderAmount) 订单平均金额 FROM orders WHERE orderDate = '2024-10-09' GROUP BY customerName HAVING COUNT(*) >= 3;
-- (3)
SELECT customerName 客户姓名,customerPhone 客户手机,SUM(orderAmount) 订单总金额 FROM orders GROUP BY customerName,customerPhone HAVING SUM(orderAmount) >=535;
查询结果如下:
-- (1)
客户姓名 订单数量 订单总金额
十一月 4 560.28
大海 6 530.50
爱卿 5 535.68
-- (2)
客户姓名 订单数量 订单总金额 订单平均金额
大海 3 217.73 72.576667
爱卿 3 162.69 54.230000
-- (3)
客户姓名 客户手机 订单总金额
十一月 18888888888 560.28
爱卿 18666669999 535.68
注意:
- 执行顺序: WHERE > 聚合函数 > HAVING
- 分组之后,查询的字段只能出现分组字段和聚合函数,其他会报错。如果不分组,则只能出现聚合函数。
5.6.5 排序查询
排序查询是指按照指定字段对数据进行排序。
SELET 字段 FROM 表名 [WHERE 条件] ORDER BY 排序字段1 [ASC|DESC],排序字段2 [ASC|DESC];
排序方式:
- ASC:升序,从小到大,默认排序方式。
- DESC:降序,从大到小。
(1) 将订单表中数据按照订单金额进行降序排序
(2) 将订单表中数据按照订单日期进行降序、订单金额进行升序排序
-- (1)
SELECT * FROM orders ORDER BY orderAmount desc;
-- (2)
SELECT * FROM orders ORDER BY orderDate desc,orderAmount asc;
查询结果如下:
-- (1)
orderNo customerName customerPhone orderAmount orderDate
SYY24100702 爱卿 18666669999 354.78 2024-10-07
SYY24100701 十一月 18888888888 268.60 2024-10-07
SYY24100103 十一月 18888888888 189.38 2024-10-01
SYY24100801 大海 13888886666 123.45 2024-10-08
SYY24100101 大海 13888886666 99.86 2024-10-01
SYY24100902 大海 13888886666 89.67 2024-10-09
SYY24100402 大海 13888886666 89.46 2024-10-04
SYY24100907 大海 13888886666 82.39 2024-10-09
SYY24100901 爱卿 18666669999 67.89 2024-10-09
SYY24100905 爱卿 18666669999 62.35 2024-10-09
SYY24100401 十一月 18888888888 59.14 2024-10-04
SYY24100904 大海 13888886666 45.67 2024-10-09
SYY24100906 十一月 18888888888 43.16 2024-10-09
SYY24100903 爱卿 18666669999 32.45 2024-10-09
SYY24100102 爱卿 18666669999 18.21 2024-10-01
-- (2)
orderNo customerName customerPhone orderAmount orderDate
SYY24100903 爱卿 18666669999 32.45 2024-10-09
SYY24100906 十一月 18888888888 43.16 2024-10-09
SYY24100904 大海 13888886666 45.67 2024-10-09
SYY24100905 爱卿 18666669999 62.35 2024-10-09
SYY24100901 爱卿 18666669999 67.89 2024-10-09
SYY24100907 大海 13888886666 82.39 2024-10-09
SYY24100902 大海 13888886666 89.67 2024-10-09
SYY24100801 大海 13888886666 123.45 2024-10-08
SYY24100701 十一月 18888888888 268.60 2024-10-07
SYY24100702 爱卿 18666669999 354.78 2024-10-07
SYY24100401 十一月 18888888888 59.14 2024-10-04
SYY24100402 大海 13888886666 89.46 2024-10-04
SYY24100102 爱卿 18666669999 18.21 2024-10-01
SYY24100101 大海 13888886666 99.86 2024-10-01
SYY24100103 十一月 18888888888 189.38 2024-10-01
可以看到,(1)按照订单金额进行降序排序,(2)按照订单日期进行降序、如果订单日期相同,则按照订单金额进行升序排序。
注意:多字段排序时,按照第一个字段排序,第一个字段相同后才按照第二个字段排序,以此类推。
5.6.6 分页查询
分页查询是指按照指定数量、偏移量查询数据。我们在搜索引擎中经常可以看到分页查询的功能。最下方的10条、下一页、上一页等按钮就是分页查询的一种实现方式。
SELECT 字段 FROM 表名 [WHERE 条件] LIMIT 偏移量,数量;
(1) 查询订单表中,按照订单金额升序排列,每页显示5条数据,显示第2页的数据
(2) 查询订单表中,按照订单金额降序排列,每页显示3条数据,显示第4页的数据
-- (1) 从第二页开始,每页显示5条数据,按照金额升序
SELECT * FROM orders ORDER BY orderAmount ASC LIMIT 2,5;
-- (2) 从第四页开始,每页显示3条数据,按照金额降序
SELECT * FROm orders ORDER BY orderAmount DESC LIMIT 4,3;
查询结果如下:
-- (1)
orderNo customerName customerPhone orderAmount orderDate
SYY24100906 十一月 18888888888 43.16 2024-10-09
SYY24100904 大海 13888886666 45.67 2024-10-09
SYY24100401 十一月 18888888888 59.14 2024-10-04
SYY24100905 爱卿 18666669999 62.35 2024-10-09
SYY24100901 爱卿 18666669999 67.89 2024-10-09
-- (2)
orderNo customerName customerPhone orderAmount orderDate
SYY24100101 大海 13888886666 99.86 2024-10-01
SYY24100902 大海 13888886666 89.67 2024-10-09
SYY24100402 大海 13888886666 89.46 2024-10-04


