前言
在当今信息化时代,数据已经成为企业核心竞争力的重要组成部分,而数据库作为数据存储与管理的核心载体,其重要性不言而喻。MySQL 作为一款开源、高效、稳定的关系型数据库管理系统,凭借其卓越的性能、灵活的扩展性和免费开源的特性,成为了全球最受欢迎的数据库之一,广泛应用于 Web 开发、数据分析、企业级应用等众多领域。
对于初学者而言,掌握 MySQL 的核心操作技能是进入数据库开发与管理领域的第一步。本文将以纯图解的方式,系统全面地讲解 MySQL 数据库从基础操作到高级应用的全流程,包括数据库与表的创建管理、数据增删改查(CRUD)、多表查询、用户权限管理等核心内容,通过丰富的示例代码和详细的步骤拆解,帮助读者快速上手 MySQL,为后续深入学习数据库优化、事务管理、索引优化等高级内容奠定坚实基础。
无论你是计算机相关专业的学生、刚入行的开发工程师,还是想要提升数据库操作能力的技术爱好者,都能从本文中获得实用的知识与技巧。接下来,就让我们一起开启 MySQL 数据库操作的学习之旅吧!
一、MySQL 数据库基础入门
1.1 MySQL 与 SQL 语言概述
在正式学习 MySQL 操作之前,我们需要先了解 MySQL 与 SQL 语言的基本概念。
MySQL 是一款开源的关系型数据库管理系统(RDBMS),由瑞典 MySQL AB 公司开发,后被 Oracle 收购。它支持多线程、高并发访问,能够高效处理海量数据,并且兼容多种操作系统(Windows、Linux、macOS 等),是 Web 开发领域的首选数据库之一。
而 SQL(Structured Query Language,结构化查询语言)是用于管理关系型数据库的标准语言,我们通过 SQL 语句来实现对数据库的创建、查询、更新、删除等操作。SQL 语言主要分为以下几大类:
- DDL(Data Definition Language,数据定义语言) :用于定义数据库、表、视图等结构,包括
CREATE(创建)、ALTER(修改)、DROP(删除)等语句。 - DML(Data Manipulation Language,数据操纵语言) :用于操作表中的数据,包括
INSERT(插入)、UPDATE(更新)、DELETE(删除)等语句。 - DQL(Data Query Language,数据查询语言) :用于查询数据库中的数据,核心语句为
SELECT,是日常开发中使用最频繁的语句。 - DCL(Data Control Language,数据控制语言) :用于控制数据库的访问权限,包括
GRANT(授权)、REVOKE(撤销权限)等语句。
在 MySQL 的操作环境中,我们每输入一条 SQL 语句,都需要以分号;结尾,然后按下回车键执行,系统会返回执行结果。
1.2 MySQL 系统数据库
当我们成功安装并启动 MySQL 服务后,系统会默认创建 4 个系统数据库,分别是sys、mysql、information_schema和performance_schema,它们各自承担着不同的功能:
- information_schema:主要存储数据库的元数据信息,包括数据库、表、字段、权限等的信息,不占用实际数据存储空间,是我们查看数据库结构的重要入口。
- performance_schema:从 MySQL 5.5 版本开始引入,主要用于收集数据库服务器的性能参数,帮助我们监控和优化数据库性能。
- mysql:核心系统数据库,主要存储系统用户的权限信息、角色、锁等重要数据,是 MySQL 权限管理的核心。
- sys :基于
information_schema和performance_schema封装而成,主要用于存储系统性能信息和监控数据,方便我们快速定位数据库性能问题。
这些系统数据库是 MySQL 正常运行的基础,切勿随意修改或删除,否则可能导致数据库服务异常。
二、MySQL 数据库操作详解
2.1 创建数据库
在 MySQL 中,我们使用CREATE DATABASE语句来创建一个新的数据库,基本语法如下:
CREATE DATABASE 数据库名;
示例 :创建一个名为db1的数据库
mysql> CREATE DATABASE db1;
Query OK, 1 row affected (0.01 sec)
执行成功后,系统会返回Query OK提示,表示数据库创建完成。
2.2 数据库命名规则
为了保证数据库的规范性和可维护性,MySQL 对数据库的命名有明确的规则:
- 可以由字母、数字、下划线
_、@、#、$组成; - 区分大小写(在 Linux 系统下),Windows 系统下不区分;
- 不能使用 MySQL 的关键字(如
create、select、database等)作为数据库名; - 不能以纯数字开头;
- 数据库名最长不能超过 64 个字符。
2.3 选择数据库
创建完成后,我们需要使用USE语句来选择要操作的数据库,语法如下:
USE 数据库名;
示例 :进入db1数据库
mysql> USE db1;
Database changed
执行成功后,系统会提示Database changed,表示当前已切换到db1数据库,后续的表操作、数据操作都将基于该数据库。
2.4 查看数据库
我们可以通过以下语句查看 MySQL 中的数据库信息:
-
查看所有数据库:
SHOW DATABASES; -
查看指定数据库的创建语句:
SHOW CREATE DATABASE 数据库名; -
查看当前正在操作的数据库:
SELECT DATABASE();
示例:
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| db1 |
+--------------------+
5 rows in set (0.00 sec)
mysql> SHOW CREATE DATABASE db1;
+----------+------------------------------------------------------------------+
| Database | Create Database |
+----------+------------------------------------------------------------------+
| db1 | CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT DATABASE();
+------------+
| DATABASE() |
+------------+
| db1 |
+------------+
1 row in set (0.00 sec)
2.5 删除数据库
当我们不再需要某个数据库时,可以使用DROP DATABASE语句将其删除,语法如下:
DROP DATABASE 数据库名;
示例 :删除db1数据库
mysql> DROP DATABASE db1;
Query OK, 0 rows affected (0.01 sec)
⚠️ 注意 :删除数据库操作是不可逆的,一旦执行,数据库中的所有表和数据都会被彻底删除,请务必谨慎操作!
三、MySQL 表操作核心技能
3.1 表的基本概念
在关系型数据库中,数据库相当于文件夹,而表相当于文件 ,表中的每一条记录就相当于文件的一行内容,每一列则称为一个字段,用于存储特定类型的数据。
例如,我们创建一个员工信息表t1,其结构如下:
表格
| id | name | age | sex |
|---|---|---|---|
| 1 | 张三 | 18 | male |
| 2 | 李四 | 20 | female |
| 3 | 王五 | 22 | male |
在这个表中,id、name、age、sex就是字段,分别代表员工编号、姓名、年龄、性别;每一行数据就是一条完整的员工记录。
3.2 查看表
在选择数据库后,我们可以通过以下语句查看数据库中的表:
-
查看当前数据库中的所有表:
SHOW TABLES; -
查看表的结构(字段信息、数据类型、约束等):
DESC 表名; -- 简写形式 DESCRIBE 表名; -- 完整形式 -
查看表的详细创建语句:
SHOW CREATE TABLE 表名;
示例:
mysql> USE db1;
Database changed
mysql> CREATE TABLE t1 (
-> id INT,
-> name VARCHAR(50),
-> age INT,
-> sex ENUM('male', 'female')
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> SHOW TABLES;
+---------------+
| Tables_in_db1 |
+---------------+
| t1 |
+---------------+
1 row in set (0.00 sec)
mysql> DESC t1;
+-------+-------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(50) | YES | | NULL | |
| age | int | YES | | NULL | |
| sex | enum('male','female') | YES | | NULL | |
+-------+-------------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> SHOW CREATE TABLE t1\G;
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int DEFAULT NULL,
`name` varchar(50) DEFAULT NULL,
`age` int DEFAULT NULL,
`sex` enum('male','female') DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
(使用\G可以让结果以更易读的垂直格式展示)
3.3 创建表
创建表是数据库操作的核心环节,我们使用CREATE TABLE语句来定义表的结构,包括字段名、数据类型、约束条件等,基本语法如下:
CREATE TABLE 表名(
字段名1 数据类型[长度] 约束条件,
字段名2 数据类型[长度] 约束条件,
...
字段名n 数据类型[长度] 约束条件
);
语法说明:
- 同一张表中,字段名不能重复;
- 字段名和表名的命名规则与数据库名一致;
- 约束条件是可选的,用于限制字段的取值范围;
- 最后一个字段后不能加逗号。
3.3.1 MySQL 常用数据类型
MySQL 支持丰富的数据类型,主要分为三大类:数值类型 、日期 / 时间类型 、字符串类型,下面是常用数据类型的详细介绍:
1. 数值类型
表格
| 类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |
|---|---|---|---|---|
| TINYINT | 1 字节 | -128 ~ 127 | 0 ~ 255 | 小数值 |
| SMALLINT | 2 字节 | -32768 ~ 32767 | 0 ~ 65535 | 小数值 |
| MEDIUMINT | 3 字节 | -8388608 ~ 8388607 | 0 ~ 16777215 | 中等数值 |
| INT | 4 字节 | -2147483648 ~ 2147483647 | 0 ~ 4294967295 | 大数值 |
| BIGINT | 8 字节 | -9223372036854775808 ~ 9223372036854775807 | 0 ~ 18446744073709551615 | 极大数值 |
| FLOAT | 4 字节 | 约 - 3.4E+38 ~ 3.4E+38 | 0 ~ 3.4E+38 | 单精度浮点数 |
| DOUBLE | 8 字节 | 约 - 1.7E+308 ~ 1.7E+308 | 0 ~ 1.7E+308 | 双精度浮点数 |
| DECIMAL(M,D) | M+2 字节 | 依赖于 M 和 D 的取值 | 依赖于 M 和 D 的取值 | 高精度小数(如金额) |
2. 日期 / 时间类型
表格
| 类型 | 大小 | 范围 | 格式 | 用途 |
|---|---|---|---|---|
| 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 ~ 2038-01-19 03:14:07 | YYYY-MM-DD HH:MM:SS | 时间戳(自动更新) |
3. 字符串类型
表格
| 类型 | 大小 | 用途 |
|---|---|---|
| CHAR(M) | 0~255 字节 | 定长字符串(M 为字符数) |
| VARCHAR(M) | 0~65535 字节 | 变长字符串(M 为字符数) |
| TINYTEXT | 0~255 字节 | 短文本数据 |
| TEXT | 0~65535 字节 | 长文本数据 |
| MEDIUMTEXT | 0~16777215 字节 | 中等长度文本数据 |
| LONGTEXT | 0~4294967295 字节 | 极大文本数据 |
| BLOB | 0~65535 字节 | 二进制大对象(存储图片、文件等) |
3.3.2 表的约束条件
约束条件用于限制字段的取值范围,保证数据的完整性和一致性,MySQL 中常用的约束条件如下:
表格
| 约束条件 | 说明 |
|---|---|
| PRIMARY KEY | 主键,唯一标识表中的记录,非空且唯一 |
| FOREIGN KEY | 外键,用于关联两张表,实现数据的引用完整性 |
| NOT NULL | 字段值不能为空 |
| UNIQUE | 字段值必须唯一 |
| AUTO_INCREMENT | 字段值自动增长(仅适用于整数类型的主键) |
| DEFAULT | 为字段设置默认值 |
| UNSIGNED | 数值类型无符号(取值范围从 0 开始) |
| ZEROFILL | 数值类型用 0 填充不足的位数 |
| ENUM() | 枚举类型,字段值只能从指定的列表中选择 |
| SET() | 集合类型,字段值可以选择多个指定的选项 |
示例:创建一个包含完整约束条件的员工信息表
mysql> CREATE TABLE renyuan (
-> id INT PRIMARY KEY AUTO_INCREMENT, -- 主键,自动增长
-> name VARCHAR(50) NOT NULL, -- 姓名,不能为空
-> sex ENUM('male', 'female') DEFAULT 'male', -- 性别,默认值为male
-> age INT UNSIGNED, -- 年龄,无符号
-> post VARCHAR(50), -- 职位
-> salary DECIMAL(10,2), -- 薪资,保留两位小数
-> office_id INT -- 部门编号
-> );
Query OK, 0 rows affected (0.03 sec)
3.4 修改表
在实际开发中,我们经常需要对已创建的表进行修改,比如添加字段、删除字段、修改字段类型等,MySQL 提供了ALTER TABLE语句来实现表结构的修改。
3.4.1 修改表名
ALTER TABLE 旧表名 RENAME TO 新表名;
示例 :将表t1重命名为t2
mysql> ALTER TABLE t1 RENAME TO t2;
Query OK, 0 rows affected (0.01 sec)
3.4.2 添加字段
ALTER TABLE 表名 ADD 字段名 数据类型 约束条件;
示例 :为renyuan表添加一个email字段
mysql> ALTER TABLE renyuan ADD email VARCHAR(100) UNIQUE;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
3.4.3 删除字段
ALTER TABLE 表名 DROP 字段名;
示例 :删除renyuan表中的email字段
mysql> ALTER TABLE renyuan DROP email;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
3.4.4 修改字段
-
修改字段的数据类型和约束条件:
ALTER TABLE 表名 MODIFY 字段名 新数据类型 新约束条件; -
修改字段名和数据类型:
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 新数据类型 新约束条件;
示例:
-- 修改age字段的数据类型为SMALLINT
mysql> ALTER TABLE renyuan MODIFY age SMALLINT UNSIGNED;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
-- 将post字段重命名为position,数据类型改为VARCHAR(100)
mysql> ALTER TABLE renyuan CHANGE post position VARCHAR(100);
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
3.5 复制表
我们可以通过CREATE TABLE ... LIKE语句复制表结构,再通过INSERT INTO ... SELECT语句复制表数据,语法如下:
-- 复制表结构
CREATE TABLE 新表名 LIKE 原表名;
-- 复制表数据
INSERT INTO 新表名 SELECT * FROM 原表名;
示例 :复制renyuan表为renyuan_copy
mysql> CREATE TABLE renyuan_copy LIKE renyuan;
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO renyuan_copy SELECT * FROM renyuan;
Query OK, 7 rows affected (0.01 sec)
Records: 7 Duplicates: 0 Warnings: 0
3.6 删除表
当我们不再需要某张表时,可以使用DROP TABLE语句将其删除,语法如下:
DROP TABLE 表名;
示例 :删除renyuan_copy表
mysql> DROP TABLE renyuan_copy;
Query OK, 0 rows affected (0.01 sec)
⚠️ 注意:删除表操作同样是不可逆的,会删除表结构和所有数据,请谨慎操作!
四、MySQL 数据增删改查(CRUD)
4.1 插入数据(INSERT)
我们使用INSERT INTO语句向表中插入新数据,语法如下:
-- 插入单条数据
INSERT INTO 表名(字段1, 字段2, ...) VALUES(值1, 值2, ...);
-- 插入多条数据
INSERT INTO 表名(字段1, 字段2, ...) VALUES(值1, 值2, ...), (值3, 值4, ...), ...;
示例 :向renyuan表中插入员工数据
mysql> INSERT INTO renyuan(name, sex, age, post, salary, office_id)
-> VALUES
-> ('张三', 'male', 18, '技术', 3000.00, 401),
-> ('李四', 'female', 20, '运营', 4000.00, 402),
-> ('王五', 'male', 22, '销售', 5000.00, 403),
-> ('赵六', 'female', 25, '技术', 6000.00, 401),
-> ('钱七', 'male', 30, '运营', 7000.00, 402),
-> ('孙八', 'female', 28, '销售', 8000.00, 403),
-> ('周九', 'male', 35, '技术', 9000.00, 401);
Query OK, 7 rows affected (0.01 sec)
Records: 7 Duplicates: 0 Warnings: 0
如果插入的是所有字段的数据,可以省略字段列表,直接写为:
INSERT INTO 表名 VALUES(值1, 值2, ...);
4.2 更新数据(UPDATE)
我们使用UPDATE语句修改表中已存在的数据,语法如下:
UPDATE 表名 SET 字段1=值1, 字段2=值2, ... [WHERE 条件];
示例 :将renyuan表中姓名为 "张三" 的员工薪资调整为 3500.00
mysql> UPDATE renyuan SET salary=3500.00 WHERE name='张三';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
⚠️ 注意 :如果省略WHERE条件,会更新表中所有数据,这是非常危险的操作,请务必添加条件限制!
4.3 删除数据(DELETE)
我们使用DELETE FROM语句删除表中的数据,语法如下:
DELETE FROM 表名 [WHERE 条件];
示例 :删除renyuan表中姓名为 "周九" 的员工记录
mysql> DELETE FROM renyuan WHERE name='周九';
Query OK, 1 row affected (0.01 sec)
⚠️ 注意 :如果省略WHERE条件,会删除表中所有数据,请谨慎操作!
4.4 查询数据(SELECT)
查询数据是数据库操作中最核心、最频繁的操作,我们使用SELECT语句从表中检索数据,语法如下:
SELECT 字段1, 字段2, ... FROM 表名 [WHERE 条件] [GROUP BY 分组字段] [HAVING 分组后条件] [ORDER BY 排序字段] [LIMIT 限制条数];
4.4.1 基础查询
-
查询所有字段:
SELECT * FROM 表名; -
查询指定字段:
SELECT 字段1, 字段2 FROM 表名;
示例:
-- 查询所有员工信息
mysql> SELECT * FROM renyuan;
+----+--------+--------+-----+--------+---------+-----------+
| id | name | sex | age | post | salary | office_id |
+----+--------+--------+-----+--------+---------+-----------+
| 1 | 张三 | male | 18 | 技术 | 3500.00 | 401 |
| 2 | 李四 | female | 20 | 运营 | 4000.00 | 402 |
| 3 | 王五 | male | 22 | 销售 | 5000.00 | 403 |
| 4 | 赵六 | female | 25 | 技术 | 6000.00 | 401 |
| 5 | 钱七 | male | 30 | 运营 | 7000.00 | 402 |
| 6 | 孙八 | female | 28 | 销售 | 8000.00 | 403 |
+----+--------+--------+-----+--------+---------+-----------+
6 rows in set (0.00 sec)
-- 查询员工的姓名和薪资
mysql> SELECT name, salary FROM renyuan;
+--------+---------+
| name | salary |
+--------+---------+
| 张三 | 3500.00 |
| 李四 | 4000.00 |
| 王五 | 5000.00 |
| 赵六 | 6000.00 |
| 钱七 | 7000.00 |
| 孙八 | 8000.00 |
+--------+---------+
6 rows in set (0.00 sec)
4.4.2 WHERE 条件查询
WHERE子句用于筛选符合条件的记录,支持以下运算符:
- 比较运算符 :
>、<、=、>=、<=、!=、<> - 范围运算符 :
BETWEEN ... AND ... - 集合运算符 :
IN(值1, 值2, ...) - 模糊查询 :
LIKE(%匹配任意字符,_匹配单个字符) - 逻辑运算符 :
AND、OR、NOT
示例:
-
查询薪资大于 5000 的员工姓名和薪资:
mysql> SELECT name, salary FROM renyuan WHERE salary > 5000; +--------+---------+ | name | salary | +--------+---------+ | 赵六 | 6000.00 | | 钱七 | 7000.00 | | 孙八 | 8000.00 | +--------+---------+ 3 rows in set (0.00 sec) -
查询部门编号为 403 的员工姓名:
mysql> SELECT name FROM renyuan WHERE office_id = 403; +--------+ | name | +--------+ | 王五 | | 孙八 | +--------+ 2 rows in set (0.00 sec) -
查询薪资在 4000 到 6000 之间的员工姓名和薪资:
mysql> SELECT name, salary FROM renyuan WHERE salary BETWEEN 4000 AND 6000; +--------+---------+ | name | salary | +--------+---------+ | 李四 | 4000.00 | | 王五 | 5000.00 | | 赵六 | 6000.00 | +--------+---------+ 3 rows in set (0.00 sec) -
查询薪资为 5000 或 7000 的员工姓名:
mysql> SELECT name FROM renyuan WHERE salary IN (5000, 7000); +--------+ | name | +--------+ | 王五 | | 钱七 | +--------+ 2 rows in set (0.00 sec) -
查询姓 "张" 的员工信息:
mysql> SELECT * FROM renyuan WHERE name LIKE '张%'; +----+--------+------+-----+--------+---------+-----------+ | id | name | sex | age | post | salary | office_id | +----+--------+------+-----+--------+---------+-----------+ | 1 | 张三 | male | 18 | 技术 | 3500.00 | 401 | +----+--------+------+-----+--------+---------+-----------+ 1 row in set (0.00 sec) -
查询薪资大于 7000 且部门编号为 403 的员工信息:
mysql> SELECT * FROM renyuan WHERE salary > 7000 AND office_id = 403; +----+--------+--------+-----+--------+---------+-----------+ | id | name | sex | age | post | salary | office_id | +----+--------+--------+-----+--------+---------+-----------+ | 6 | 孙八 | female | 28 | 销售 | 8000.00 | 403 | +----+--------+--------+-----+--------+---------+-----------+ 1 row in set (0.00 sec)
4.4.3 分组查询(GROUP BY)
GROUP BY语句用于将数据按照指定字段进行分组,结合聚合函数可以实现统计分析,常用聚合函数包括:
COUNT():统计记录数AVG():计算平均值MAX():计算最大值MIN():计算最小值SUM():计算总和
示例:
-
按性别分组,统计男、女员工的人数:
mysql> SELECT sex, COUNT(*) FROM renyuan GROUP BY sex; +--------+----------+ | sex | COUNT(*) | +--------+----------+ | male | 3 | | female | 3 | +--------+----------+ 2 rows in set (0.00 sec) -
按部门分组,计算每个部门的平均薪资:
mysql> SELECT office_id, AVG(salary) FROM renyuan GROUP BY office_id; +-----------+-------------+ | office_id | AVG(salary) | +-----------+-------------+ | 401 | 4750.000000 | | 402 | 5500.000000 | | 403 | 6500.000000 | +-----------+-------------+ 3 rows in set (0.00 sec) -
按职位分组,计算每个职位的最高薪资:
mysql> SELECT post, MAX(salary) FROM renyuan GROUP BY post; +--------+-------------+ | post | MAX(salary) | +--------+-------------+ | 技术 | 6000.00 | | 运营 | 7000.00 | | 销售 | 8000.00 | +--------+-------------+ 3 rows in set (0.00 sec)
4.4.4 分组后过滤(HAVING)
HAVING语句用于在分组后对结果进行过滤,与WHERE的区别在于:WHERE是在分组前过滤记录,HAVING是在分组后过滤分组结果。
示例:查询平均薪资大于 5000 的部门:
mysql> SELECT office_id, AVG(salary) FROM renyuan GROUP BY office_id HAVING AVG(salary) > 5000;
+-----------+-------------+
| office_id | AVG(salary) |
+-----------+-------------+
| 402 | 5500.000000 |
| 403 | 6500.000000 |
+-----------+-------------+
2 rows in set (0.00 sec)
4.4.5 排序查询(ORDER BY)
ORDER BY语句用于对查询结果进行排序,ASC表示升序(默认),DESC表示降序。
示例:按薪资降序排序,查询所有员工信息:
mysql> SELECT * FROM renyuan ORDER BY salary DESC;
+----+--------+--------+-----+--------+---------+-----------+
| id | name | sex | age | post | salary | office_id |
+----+--------+--------+-----+--------+---------+-----------+
| 6 | 孙八 | female | 28 | 销售 | 8000.00 | 403 |
| 5 | 钱七 | male | 30 | 运营 | 7000.00 | 402 |
| 4 | 赵六 | female | 25 | 技术 | 6000.00 | 401 |
| 3 | 王五 | male | 22 | 销售 | 5000.00 | 403 |
| 2 | 李四 | female | 20 | 运营 | 4000.00 | 402 |
| 1 | 张三 | male | 18 | 技术 | 3500.00 | 401 |
+----+--------+--------+-----+--------+---------+-----------+
6 rows in set (0.00 sec)
4.4.6 限制结果条数(LIMIT)
LIMIT语句用于限制查询结果的返回条数,常用于分页查询,语法如下:
LIMIT 偏移量, 条数;
-- 或
LIMIT 条数;
示例:查询薪资最高的前 3 名员工:
mysql> SELECT * FROM renyuan ORDER BY salary DESC LIMIT 3;
+----+--------+--------+-----+--------+---------+-----------+
| id | name | sex | age | post | salary | office_id |
+----+--------+--------+-----+--------+---------+-----------+
| 6 | 孙八 | female | 28 | 销售 | 8000.00 | 403 |
| 5 | 钱七 | male | 30 | 运营 | 7000.00 | 402 |
| 4 | 赵六 | female | 25 | 技术 | 6000.00 | 401 |
+----+--------+--------+-----+--------+---------+-----------+
3 rows in set (0.00 sec)
4.4.7 正则表达式查询(REGEXP)
MySQL 支持使用正则表达式进行模糊查询,通过REGEXP关键字实现,语法如下:
SELECT 字段 FROM 表名 WHERE 字段 REGEXP '正则表达式';
示例:查询姓名以 "张" 或 "赵" 开头的员工:
mysql> SELECT name FROM renyuan WHERE name REGEXP '^[张赵]';
+--------+
| name |
+--------+
| 张三 |
| 赵六 |
+--------+
2 rows in set (0.00 sec)
五、MySQL 多表查询高级应用
在实际业务场景中,数据往往分散在多张表中,我们需要通过多表查询 来关联获取完整的业务数据。多表查询主要分为子查询 和连接查询两大类,下面我们详细介绍。
5.1 准备数据
为了演示多表查询,我们先创建两张表:部门表bumen和员工表renyuan,并插入测试数据:
-- 创建部门表
mysql> CREATE TABLE bumen (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> name VARCHAR(20) NOT NULL
-> );
Query OK, 0 rows affected (0.02 sec)
-- 插入部门数据
mysql> INSERT INTO bumen(name) VALUES('技术'), ('人力'), ('运营'), ('销售');
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0
-- 创建员工表(关联部门表)
mysql> CREATE TABLE renyuan (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> name VARCHAR(50) NOT NULL,
-> sex ENUM('male', 'female') DEFAULT 'male',
-> age INT UNSIGNED,
-> post VARCHAR(50),
-> salary DECIMAL(10,2),
-> dep_id INT,
-> FOREIGN KEY (dep_id) REFERENCES bumen(id) -- 外键关联部门表
-> );
Query OK, 0 rows affected (0.03 sec)
-- 插入员工数据
mysql> INSERT INTO renyuan(name, sex, age, post, salary, dep_id)
-> VALUES
-> ('张三', 'male', 18, '技术', 3500.00, 1),
-> ('李四', 'female', 20, '运营', 4000.00, 3),
-> ('王五', 'male', 22, '销售', 5000.00, 4),
-> ('赵六', 'female', 25, '技术', 6000.00, 1),
-> ('钱七', 'male', 30, '人力', 7000.00, 2),
-> ('孙八', 'female', 28, '销售', 8000.00, 4),
-> ('周九', 'male', 35, '技术', 9000.00, 1);
Query OK, 7 rows affected (0.01 sec)
Records: 7 Duplicates: 0 Warnings: 0
5.2 子查询
子查询是指在一个查询语句中嵌套另一个查询语句,外层查询称为主查询 ,内层查询称为子查询,子查询的结果会作为主查询的条件或数据源。
5.2.1 标量子查询(子查询返回单个值)
示例:查询年龄大于平均年龄的员工姓名:
mysql> SELECT name FROM renyuan WHERE age > (SELECT AVG(age) FROM renyuan);
+--------+
| name |
+--------+
| 钱七 |
| 孙八 |
| 周九 |
+--------+
3 rows in set (0.00 sec)
5.2.2 列子查询(子查询返回一列数据)
示例:查询技术部和销售部的员工姓名:
mysql> SELECT name FROM renyuan WHERE dep_id IN (SELECT id FROM bumen WHERE name IN ('技术', '销售'));
+--------+
| name |
+--------+
| 张三 |
| 王五 |
| 赵六 |
| 孙八 |
| 周九 |
+--------+
5 rows in set (0.00 sec)
5.2.3 行子查询(子查询返回一行数据)
示例:查询与 "张三" 同部门且同性别员工的姓名:
mysql> SELECT name FROM renyuan WHERE (dep_id, sex) = (SELECT dep_id, sex FROM renyuan WHERE name='张三');
+--------+
| name |
+--------+
| 张三 |
| 周九 |
+--------+
2 rows in set (0.00 sec)
5.2.4 表子查询(子查询返回一张表)
示例:查询年龄大于 25 岁的员工所属部门名称:
mysql> SELECT b.name FROM bumen b WHERE b.id IN (SELECT dep_id FROM renyuan WHERE age > 25);
+--------+
| name |
+--------+
| 人力 |
| 销售 |
| 技术 |
+--------+
3 rows in set (0.00 sec)
5.3 连接查询
连接查询是将多张表通过关联字段连接起来,获取跨表的完整数据,MySQL 中常用的连接查询包括内连接 、左连接 、右连接。
5.3.1 内连接(INNER JOIN)
内连接只返回两张表中匹配成功的记录,语法如下:
SELECT 字段 FROM 表1 INNER JOIN 表2 ON 表1.关联字段 = 表2.关联字段;
示例:查询所有员工的姓名和所属部门名称:
mysql> SELECT r.name, b.name AS dep_name FROM renyuan r INNER JOIN bumen b ON r.dep_id = b.id;
+--------+-----------+
| name | dep_name |
+--------+-----------+
| 张三 | 技术 |
| 李四 | 运营 |
| 王五 | 销售 |
| 赵六 | 技术 |
| 钱七 | 人力 |
| 孙八 | 销售 |
| 周九 | 技术 |
+--------+-----------+
7 rows in set (0.00 sec)
5.3.2 左连接(LEFT JOIN)
左连接会返回左表的所有记录 ,以及右表中匹配成功的记录,如果右表没有匹配项,则显示NULL,语法如下:
SELECT 字段 FROM 表1 LEFT JOIN 表2 ON 表1.关联字段 = 表2.关联字段;
示例:查询所有部门的名称,以及对应的员工姓名(包括没有员工的部门):
mysql> SELECT b.name AS dep_name, r.name FROM bumen b LEFT JOIN renyuan r ON b.id = r.dep_id;
+-----------+--------+
| dep_name | name |
+-----------+--------+
| 技术 | 张三 |
| 技术 | 赵六 |
| 技术 | 周九 |
| 人力 | 钱七 |
| 运营 | 李四 |
| 销售 | 王五 |
| 销售 | 孙八 |
+-----------+--------+
7 rows in set (0.00 sec)
(当前所有部门都有员工,所以没有显示NULL)
5.3.3 右连接(RIGHT JOIN)
右连接会返回右表的所有记录 ,以及左表中匹配成功的记录,如果左表没有匹配项,则显示NULL,语法如下:
SELECT 字段 FROM 表1 RIGHT JOIN 表2 ON 表1.关联字段 = 表2.关联字段;
示例:查询所有员工的姓名,以及对应的部门名称(包括没有部门的员工,当前测试数据中没有此类员工):
mysql> SELECT r.name, b.name AS dep_name FROM renyuan r RIGHT JOIN bumen b ON r.dep_id = b.id;
+--------+-----------+
| name | dep_name |
+--------+-----------+
| 张三 | 技术 |
| 赵六 | 技术 |
| 周九 | 技术 |
| 钱七 | 人力 |
| 李四 | 运营 |
| 王五 | 销售 |
| 孙八 | 销售 |
+--------+-----------+
7 rows in set (0.00 sec)
六、MySQL 用户与权限管理
数据库的安全性是企业级应用的核心关注点,MySQL 通过用户与权限管理来控制不同用户对数据库的访问范围和操作权限,避免数据泄露或误操作。
6.1 创建用户
我们使用CREATE USER语句创建新用户,语法如下:
CREATE USER '用户名'@'登录地址' IDENTIFIED BY '密码';
- 登录地址 :可以是
localhost(本地登录)、%(任意地址登录)、具体 IP 地址(如192.168.1.100)。 - 密码:需要符合 MySQL 的密码策略,建议包含大小写字母、数字和特殊字符。
示例 :创建一个本地登录的用户test,密码为123456:
mysql> CREATE USER 'test'@'localhost' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.01 sec)
6.2 授权用户
创建用户后,需要使用GRANT语句为用户分配权限,语法如下:
GRANT 权限1, 权限2, ... ON 数据库.表 TO '用户名'@'登录地址';
常用权限包括:
SELECT:查询权限INSERT:插入权限UPDATE:更新权限DELETE:删除权限ALTER:修改表结构权限CREATE:创建数据库 / 表权限DROP:删除数据库 / 表权限ALL PRIVILEGES:所有权限
示例 :为用户test分配db1数据库中所有表的查询和插入权限:
mysql> GRANT SELECT, INSERT ON db1.* TO 'test'@'localhost';
Query OK, 0 rows affected (0.01 sec)
如果要分配所有权限,可以写为:
mysql> GRANT ALL PRIVILEGES ON *.* TO 'test'@'localhost';
Query OK, 0 rows affected (0.01 sec)
授权完成后,需要执行FLUSH PRIVILEGES;语句使权限生效:
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
6.3 查看用户权限
我们可以使用SHOW GRANTS语句查看用户的权限:
SHOW GRANTS FOR '用户名'@'登录地址';
示例 :查看用户test的权限:
mysql> SHOW GRANTS FOR 'test'@'localhost';
+--------------------------------------------------+
| Grants for test@localhost |
+--------------------------------------------------+
| GRANT USAGE ON *.* TO `test`@`localhost` |
| GRANT SELECT, INSERT ON `db1`.* TO `test`@`localhost` |
+--------------------------------------------------+
2 rows in set (0.00 sec)
6.4 撤销用户权限
我们使用REVOKE语句撤销用户的权限,语法如下:
REVOKE 权限1, 权限2, ... ON 数据库.表 FROM '用户名'@'登录地址';
示例 :撤销用户test对db1数据库的插入权限:
mysql> REVOKE INSERT ON db1.* FROM 'test'@'localhost';
Query OK, 0 rows affected (0.01 sec)
6.5 删除用户
我们使用DROP USER语句删除用户,语法如下:
DROP USER '用户名'@'登录地址';
示例 :删除用户test:
mysql> DROP USER 'test'@'localhost';
Query OK, 0 rows affected (0.01 sec)
七、总结与进阶建议
7.1 本文核心内容回顾
本文以纯图解的方式,系统讲解了 MySQL 数据库操作的核心知识点,主要包括:
- MySQL 基础:MySQL 与 SQL 语言的概念、系统数据库的作用。
- 数据库操作:创建、选择、查看、删除数据库的语法与注意事项。
- 表操作:创建表(数据类型、约束条件)、查看表、修改表、复制表、删除表的完整流程。
- 数据增删改查 :
INSERT、UPDATE、DELETE、SELECT语句的详细用法,包括基础查询、条件查询、分组查询、排序查询、分页查询等。 - 多表查询:子查询(标量子查询、列子查询、行子查询、表子查询)和连接查询(内连接、左连接、右连接)的应用场景与示例。
- 用户与权限管理:创建用户、授权、查看权限、撤销权限、删除用户的操作方法。
通过学习本文,读者可以掌握 MySQL 数据库的基础操作技能,能够独立完成数据库与表的创建、数据的增删改查、多表关联查询以及用户权限管理等日常开发任务。
7.2 进阶学习建议
在掌握基础操作后,建议读者继续深入学习以下高级内容,提升数据库开发与优化能力:
- 事务管理:学习 MySQL 的事务特性(ACID)、事务隔离级别、事务的提交与回滚,保证数据操作的原子性和一致性。
- 索引优化:学习索引的类型(主键索引、唯一索引、普通索引、复合索引)、索引的创建与删除、索引优化策略,提升查询效率。
- 存储引擎:了解 MySQL 常用的存储引擎(InnoDB、MyISAM、Memory 等)的特点与适用场景,根据业务需求选择合适的存储引擎。
- 数据库备份与恢复 :学习
mysqldump、binlog等备份与恢复工具,保证数据的安全性和可用性。 - 性能优化:学习慢查询日志分析、SQL 语句优化、服务器参数调优等方法,提升数据库的整体性能。
7.3 学习资源推荐
- 官方文档 :MySQL 8.0 Reference Manual(最权威的学习资料)
- 书籍:《MySQL 必知必会》(入门首选)、《高性能 MySQL》(进阶必读)
- 在线课程:慕课网、B 站等平台的 MySQL 实战课程,通过项目实践巩固所学知识。
结语
MySQL 数据库操作是后端开发、数据分析等领域的核心技能,掌握基础操作是进入技术行业的第一步。本文通过丰富的示例代码和详细的步骤拆解,力求让读者能够快速上手 MySQL,希望能为你的技术学习之路提供帮助。