MySQL数据库系统学习笔记(1)
MySQL数据库系统学习笔记
一、数据库基础概念
1. 核心组件
数据库(DB):存储数据的文件系统
DBMS:数据库管理系统软件(如MySQL)
SQL:结构化查询语言(操作数据库的标准)
2. 数据库分类
关系型:MySQL/Oracle/SQL Server(二维表结构)
非关系型:Redis/HBase(键值对/文档型)
二、MySQL安装与登录
1. 命令行登录
1 | mysql -uroot -proot |
三、SQL语言分类
D:定义
M:操作
Q:查询
C:控制
这部分很重要,重点记忆
DDL:数据定义语言,用来操作数据库对象(数据库,表,字段)
DML:数据操作语言,用来对数据库中表的数据进行增删改
DQL:数据查询语言,用来对数据库中表的数据进行查询操作
DCL:数据控制语言,用来创建数据库用户,控制访问权限
字符库意义对照表
- SHOW[显示]
- SELECT[查询]
- DATABASE[数据库]
- IF[如果]
- NOT[没有]
- EXISTS[存在]
- DEFAULT[默认]
- CHARSET[字符集]
- UTF8[支持中文(万国码)]
- DROP[删除]
- IF EXISTS[如果存在]
- TABLES[表]
- DESC[描述]
- CREATE[创建]
- ALTER[修改]
- ADD[添加]
- TRUNCATE[截断,清除]
DDL部分(数据对象操作,数据库操作,表操作,字段操作)
数据定义语言,用来操作数据库对象(数据库,表,字段)
1. DDL(数据定义)
查看所有数据库1
2
3-- 查看所有数据库
-- show[显示] databases[所有数据库]
SHOW DATABASES;
查看当前数据库1
2
3-- 查看当前数据库
-- select[查询] DATABASE[数据库]
SELECT DATABASE();
创建数据库1
2
3
4
5
6
7
8
9
10
11
12-- 创建数据库
-- 在同一个数据库服务器中,不能创建两个名字相同的数据库
-- create[创建] database[数据库] db[数据库名]
-- if[如果] not[没有] exists[存在]
CREATE DATABASE IF NOT EXISTS shop
-- 创建数据库指定字符集
-- default[默认] charset[字符集] utf8[支持中文]
DEFAULT CHARSET utf8;
create database if not exists db3 default charset utf8;
删除数据库1
2
3-- 删除数据库
drop[删除] if exists[如果存在]
DROP DATABASE IF EXISTS test;
切换数据库1
2select database();
use db;
2. 表操作DDL
查看所有表1
2
3-- 查看所有表
-- SHOW[显示] tables[所有表]
SHOW TABLES;
查看指定表的结构1
2
3
4-- 查看指定表的结构
-- 查看表的字段,字段的类型,是否可以为null,是否有默认值
-- desc[描述] studentinfo[表名]
desc studentinfo;
查看指定表的建表语句1
2
3-- 查看指定表的建表语句
-- show[显示] create[创建] tables[表] studentinfo[表名]
show create table studentinfo;
3. 数据类型详解
数值类型
- int整数
- float 小数(单精度)
- double 小数(双精度)
1 | INT -- 整数 |
字符串类型
1 | CHAR(11) -- 固定长度(适合身份证号) |
- char(需要指定长度)固定字符串
- varchar(需要指定长度)可变字符串
存在面试题,见下
时间类型
1 | DATE -- 日期(YYYY-MM-DD) |
4. 完整表示例和表操作
1 | CREATE TABLE employees ( |
修改表1
2
3
4-- 修改表
-- 添加一个新的字段 家庭住址 address
-- alter[修改] table[表] emp[表名] add[添加] address[添加的字段名]
alter table emp add address varchar(50);
删除字段1
2
3-- 删除字段
-- alter[修改] table[表] emp[表名] drop[删除] address[删除的字段名]
alter table emp drop address;
两种删除表1
2
3
4
5
6-- 删除表
drop table if exists emp;
-- 删除表, 并重新创建表
-- truncate[截断,清除]
truncate table emp;
此处存在面试题,见下
四、DML数据操作
DML数据操作语言,用于对数据库中的数据进行增删改操作。
- 添加数据INSERT
- 修改数据UPDATE
- 删除数据DELETE
1. 添加数据
1 | -- 给指定字段添加数据 |
2. 修改数据
更新类别1
2
3
4
5-- 条件更新
UPDATE employees SET salary = salary*1.1 WHERE department_id = 2;
-- 全表更新
UPDATE employees SET age = age + 1;
修改数据1
2
3
4
5-- 修改数据
-- 修改id为1的数据,将name修改为中文杰克
-- where 用于指定条件
update emp set name='JACK',age=22 where eid=1;
-- 修改语句的条件可以有,也可以没有,如果没有指定条件,则修改整张表的数据。
3. 删除数据
1 | -- 条件删除 |
详细案例1
2
3-- 删除数据
delete from emp where eid=1;
-- 删除语句的条件可以有,也可以没有,如果没有指定条件,则删除整张表的数据。
五、DQL数据查询
DQL数据查询语言,用来查询数据库中表的数据
语法结构顺序(强制性顺序,元素可以不存在,但是必须按照这个顺序)
1 | select 字段列表 |
- 基本查询(不带条件)
- 条件查询(where)
- 聚合函数(count、max、min、avg、sum)
- 分组查询(group by)
- 排序查询(order by)
- 分页查询(limit)
1. 基础查询
在基本查询的DQL语句中,不带任何的查询条件。1
2
3
4
5
6
7
8
9
10
11-- 查询指定列
SELECT name, salary FROM employees;
-- 别名查询
SELECT name AS '姓名',
salary*12 '年薪'
FROM employees;
-- 去重查询
SELECT DISTINCT department_id
FROM employees;
实战对照1
2
3
4
5
6
7
8
9
10
11-- 查询多个字段
-- 职员姓名,职员性别,职员工资,入职时间
-- select[查询] 字段列表 from[来自] emp[查询的表名]
select name,sex,sal,hiredate from emp;
-- 查询所有字段 * 代表查询所有字段
select * from emp;
-- 字段取别名 as 取别名 as可以省略
select sal '工资',hiredate '入职时间' from emp;
-- 查询员工的年龄有哪几种
-- distinct[去重复]
select distinct age from emp;
2. 条件查询
- 比较运算符 > < >= <= <>或 != between..and in
- 逻辑运算符 or 或者 and 并且 not ! 非 不是
1 | -- 比较查询 |
实战对照1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20-- 查询年龄大于18岁的
select * from emp where age>19;
-- 查询年龄小于20岁的
select * from emp where age<20;
-- 查询没有身份证号的员工信息
select * from emp where card is null;
-- 查询有身份证的员工信息
select * from emp where card is not null;
-- 查询年龄在19(包括)和20(包括)岁之间的职员信息
select * from emp where age>=19 && age<=20;
-- BETWEEN...and.. 在某个范围之间(最小值 and 最大值)
select * from emp where age between 19 and 20;
-- 查询性别为女,年龄小于20岁的职员信息
select * from emp where sex='女' and age<20;
-- 查询eid等于 2或者3或者6的员工信息
select * from emp where eid=2 or eid=3 or eid=6;
-- in 在in之后列表中的值 多选
select * from emp where eid in(2,3,6);
like模糊查询模糊查询通过通配符实现字符串匹配 %
表示任意长度的字符 1个或1个以上_
表示单个字符
实战对照
1 | -- 查询姓名为4个字的员工信息 |
3. 聚合函数
可以理解为数学函数逻辑
- COUNT 统计数量
- AVG 求平均
- MAX 最大值
- MIN 最小值
- SUM 求和
1 | -- 统计员工总数量 |
4. 分组查询
按照分组阶段将结果相同的内容作为一组,分组的目的是为了统计,所以一般情况会跟聚合函数一起使用。1
2
3
4
5
6
7
8
9
10
11
12-- 按照性别分组,统计男女职员各多少人
select sex,count(*) from emp group by sex;
-- 按照性别分组,统计男女员工的平均年龄
select sex,avg(age) from emp group by sex;
-- 按照性别分组,统计男女职员各多少人,小于2的不显示
-- having 筛选
select sex,count(*) from emp group by sex having count(*)>2;
-- 查询年龄大于20岁,按性别分组,统计每组的人数,大于2显示
select sex,count(*) from emp where age>20 group by sex having count(*)>2;
5. 排序查询
ORDER BY 语句对查询结果进行排序。
表达式后面可选asc(升序)
或者desc(降序)
来指定排序方向,如果没有指定方向,默认为asc(升序)
1 | -- 按照年龄对员工进行升序 |
6.分页查询limit
用来限制select查询返回的行会,常用于分页,或提取部分数据,提供查询效率。
基本上所有的分页设计都是为了降低服务器负担,提高效率1
2-- 0 开始索引, 查询3条
select * from emp limit 0,3;
注意:索引是按照提交数量定的,哪怕没提交成功报错了,但是执行了一次查询,索引仍然会增加
解释:若是0,3,意思是从索引0开始,每次查询三条,若是成功查询,索引会变为3,哪怕出现报错查询则变为1
查询练习实例
1 | -- 查询年龄在20,21,23的员工信息 |
六、数据库设计
何为范式
好的数据库设计对数据库的存储性能和后期开发,都会产生重要的影响。建立规范的数据库需要满足一些规则来优化数据库的设计和存储,这些规则称为范式。
数据库三大范式就是设计表结构所遵循的规范,目的就是为了减少冗余,建立结构合理的数据库,而提高数据存储和使用的性能。
三大范式之间是具有依赖关系的,比如第二范式需要在第一范式的基础上进行,第三范式需要在第二范式的基础上进行。
1. 三大范式
1NF:
字段原子性(不可再分)
遵循原子性。即表中字段的数据,不可以在拆分。
2NF:
消除部分依赖(有主键)
一个表只能描述一件事情。
3NF:
消除传递依赖(外键关联)
在满足第二范式的情况下,消除传递依赖。
1.数据库约束
对表中的数据进行限制,保证数据的正确性、有效性和完整性。如果一个表添加了约束,不正确的数据将无法插入到表中。有点像过滤器
2. 约束类型
对表中的数据进行限制,保证数据的正确性、有效性和完整性。如果一个表添加了约束,不正确的数据将无法插入到表中。
- 非空约束: 限制该字段的数据不能为NULL
NOT NULL
- 唯一约束:限制该字段的数据都是唯一的,不重复
UNIQUE
- 主键约束:主键是一行数据的唯一表示,非空且唯一
PRIMARY KEY
- 检查约束(8.0之后的版本才有效):保证字段满足某一个条件
CHECK
- 默认约束:保存数据时,如果不指定该字段的值,则使用默认值
DEFUALT
- 外键约束:用于让两张表的数据之间建立连接,保证数据的一致性
FOREIGN KEY
3. 外键操作
创建外键约束1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17-- 创建外键约束
create table emp(
id int primary key auto_increment,
name varchar(20),
dno int, -- 外键(从表)
-- constraint[约束] fk_dno[约束名] foreign key [外键约束](外键字段名) references[引用]
constraint fk_dno foreign key(dno) references dept(dno) on update cascade on delete cascade
)
create table dept(
dno int primary key auto_increment,-- 主键(主键)
dname varchar(20)
)
insert into emp values(null,'jack',10);
insert into emp values(null,'Tom',10);
insert into emp values(null,'Lucy',20);
删除外键1
2
3
4
5-- 删除外键
alter table emp drop foreign key fk_dno;
-- 在emp表存在的情况下添加外键
alter table emp add constraint fk_dno foreign key(dno) references dept(dno);
级联操作
级联操作指的是在数据库表之间建立起一种关联关系,使得对一个表的操作(如更新或删除)能够自动触发对相关联表中数据的相应操作。
- 级联更新(ON UPDATE CASCADE)
- 级联删除(ON DELETE CASCADE)
当设置了级联更新,如果主表(包含外键的表)中的数据发生变化,那么从表(被引用的表)中相应的数据也会自动更新。同样,当设置了级联删除,如果主表中的数据被删除,从表中相应的数据也会被自动删除。
1 | -- 创建学生表 |
通过FOREIGN KEY (sid) REFERENCES stu(sid)建立了外键关系,并通过ON DELETE CASCADE和ON UPDATE CASCADE指定了级联删除和级联更新的行为。
SQL 多表连接分类详解
1. 内连接 (INNER JOIN)
显式内连接
使用 INNER JOIN
和 ON
关键字明确指定连接条件:1
2
3SELECT s.StuName, c.ClassName
FROM StudentInfo s
INNER JOIN ClassInfo c ON s.SClassID = c.ClassID
隐式内连接
使用 WHERE
子句指定连接条件(不推荐):1
2
3SELECT s.StuName, c.ClassName
FROM StudentInfo s, ClassInfo c
WHERE s.SClassID = c.ClassID
特点:
- 只返回两表中匹配的行
- 显式写法更清晰,推荐使用
2. 外连接 (OUTER JOIN)
左外连接 (LEFT JOIN)
返回左表所有行,右表无匹配则显示NULL:1
2
3SELECT s.StuName, e.ExamName
FROM StudentInfo s
LEFT JOIN StudentExam e ON s.StuID = e.EStuID
右外连接 (RIGHT JOIN)
返回右表所有行,左表无匹配则显示NULL:1
2
3SELECT s.StuName, e.ExamName
FROM StudentInfo s
RIGHT JOIN StudentExam e ON s.StuID = e.EStuID
内外连接对比
特性 | 内连接 | 外连接 |
---|---|---|
结果集 | 只返回匹配行 | 返回匹配行+未匹配行(补NULL) |
性能 | 通常更快 | 稍慢 |
用途 | 需要精确匹配时 | 需要保留所有记录时 |
NULL处理 | 不包含NULL | 包含NULL |
特点:
- 左连接保留左表全部数据
- 右连接保留右表全部数据
- 实际开发中左连接使用更频繁
3. 自连接 (SELF JOIN)
表与自身连接,常用于层级数据查询:1
2
3
4-- 查询员工及其经理信息
SELECT e1.EmpName AS 员工, e2.EmpName AS 经理
FROM Employee e1
LEFT JOIN Employee e2 ON e1.ManagerID = e2.EmpID
特点:
- 必须使用表别名区分
- 常用于组织结构、分类层级等场景
4. 交叉连接 (CROSS JOIN)
返回两表的笛卡尔积(所有可能的组合):1
2
3SELECT s.StuName, c.ClassName
FROM StudentInfo s
CROSS JOIN ClassInfo c
特点:
- 结果行数 = 表1行数 × 表2行数
- 谨慎使用,可能产生大量数据
5. 子查询 (SUBQUERY)
WHERE 子句中的子查询
1 | -- 查询高于平均分的学员 |
FROM 子句中的子查询(派生表)
1 | -- 查询每个班级的平均分 |
SELECT 子句中的子查询
1 | -- 查询学生及其班级平均分 |
子查询类型:
| 类型 | 说明 | 示例 |
|———|———|———|
| 标量子查询 | 返回单个值 | SELECT ... WHERE col > (SELECT AVG(col) FROM ...)
|
| 列子查询 | 返回单列多行 | SELECT ... WHERE col IN (SELECT col FROM ...)
|
| 行子查询 | 返回单行多列 | SELECT ... WHERE (col1,col2) = (SELECT col1,col2 FROM ...)
|
| 表子查询 | 返回多行多列 | FROM (SELECT ...) AS t
|
七、高级特性
1. 事务控制
1 | START TRANSACTION; |
2. 视图创建
1 | CREATE VIEW emp_dept_view AS |
3. 索引优化
1 | -- 创建索引 |
八、经典面试题
1. CHAR vs VARCHAR
char和varchar都可以描述字符串,char是固定字符串,无论使用几个字符串都占满全部。varchar可变字符串,使用几个字符串就占用几个。
- CHAR:固定长度,适合存储定长数据(如身份证号)
- VARCHAR:可变长度,适合存储变长数据(如用户名)
例子:
CHAR(11) — 固定长度
一定要初始化一个长度,键入内容不到该长度会用空格补齐,不可超出定义长度,内存占用小
VARCHAR(50) — 可变长度
一定要初始化一个长度,用多少就分配多少长度,可以超出定义长度
2. DELETE vs TRUNCATE
- DELETE:逐行删除,可回滚,不影响自增
- TRUNCATE:整表删除,不可回滚,重置自增
1.删除的方式不同
delete命令执行的时候会产生数据的日志文件,而日志记录需要消耗时间,方便数据回滚恢复。
truncate命令执行的时候不回产生数据日志,因此比delete更快。
2.表结构的影响
delete不会影响表的结构。
truncate会把表的自增进行重置和索引恢复初始大小。
3. WHERE vs HAVING
- WHERE:分组前过滤,不能使用聚合函数
- HAVING:分组后过滤,可以使用聚合函数
执行时机不同: where是在分组之前进行过滤,不满足where条件,不参与分组,而having是分组之后对结果进行筛选。
判断条件不同:where 不能对聚合函数进行判断,having是可以的
九、实用技巧
1. 数据导出导入
1 | # 导出整个数据库 |
2. 性能分析
1 | -- 查看执行计划 |
3. 安全设置
1 | -- 创建用户并授权 |
十、实战练习
1. 多表联合查询
1 | SELECT o.order_id, c.customer_name, p.product_name |
2. 复杂统计报表
1 | SELECT |
3. 数据清洗转换
1 | -- 将旧数据迁移到新表 |