MySQL
MySQL-基础
数据库管理系统DBMS
MySQL数据模型
客户端->DBMS->多个数据库->多个二维表
SQL语句
DDL(Data Definition Language)数据定义语言(数据库、表、字段)
DML(Data Manipulation Language)数据操作语言
DQL(Data Query Language)数据查询语言
DCL(Data Control Language)数据控制语言,管理数据库用户,控制数据库的访问权限
DDL-数据定义
数据库操作
大类 | 语句 | 作用 |
---|---|---|
查询 | show databases | 查询所有数据库 |
seclect database() | 查询当前数据库 | |
创建 | create database [if not exists] 数据库名 | (如果不存在)创建一个数据库 |
使用 | use 数据库名; | 使用数据库 |
删除 | drop database [if exists] 数据库名 | 删除数据库 |
表操作-查询
语句 | 作用 |
---|---|
show tables; | 查询当前数据库所有表 |
desc 表名; | 查询表结构 |
show create table 表名; | 查询指定表的建表语句 |
表操作-创建
1 | create table 表名( |
关于约束:
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制字段值不能为null | not null |
唯一约束 | 保证字段所有数据唯一 | unique |
主键约束 | 主键是一行数据的唯一标识,非空且唯一 | primary key |
默认约束 | 字段未指定值则用默认值 | default |
外键约束 | 让两张表的数据建立连接 | foreign key |
字段数据类型
数值
类型 | 大小(byte) | 描述 |
---|---|---|
tinyint | 1 | 小整数值 |
smallint | 2 | 大整数值 |
mediumint | 3 | 大整数值 |
int | 4 | 大整数值 |
bigint | 8 | 极大整数值 |
float | 4 | 单精度浮点数 |
double | 8 | 双精度浮点数 |
decimal | 小数值(精确定点数) |
例如double,需使用double(整个数的长度,小数部分长度)
字符串
类型 | 描述 |
---|---|
char | 定长字符串 |
varchar | 变长字符串 |
tinyblob | 不超过255个字符的二进制数据 |
tinytext | 短文本字符串 |
blob | 二进制形式的长文本数据 |
text | 长文本数据 |
midiumblob | 二进制形式的中等长度文本数据 |
midiumtext | 中等长度文本数据 |
longblob | 二进制形式的极大文本数据 |
longtext | 极大文本数据 |
日期时间
大小 | 范围 | 格式 | 描述 | |
---|---|---|---|---|
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 | 年份值 |
datatime | 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 | 混合日期和时间值,时间戳 |
修改、删除表结构
语言可以不掌握,但是要会图形化操作
DML-数据操作
添加数据:
insert into 表名(字段1,字段2,……) values(值1,值2,……);
- 字符串应该和日期型数据应该包含在引号内
- 插入的数据大小,应该在字段的规定范围内
修改数据
update 表名 set 字段名1=值1,字段名2=值2,…[where 条件]
删除数据
delete from 表名 [where 条件]
DQL-数据查询
基本查询:
基本查询
select 字段列表 from 表名;
select * from 表名;(不建议在开发中使用这种方式,因为不直观)
起别名
select 字段 as ‘别名’ from 表名;as可省略
去重
select distinct 字段名称 from 表名;
条件查询:
select 字段列表 from 表名 where 条件列表;
比较运算符 | 功能 |
---|---|
> >= < <= = !=或<> | 比较 |
between…and … | 在某个范围之内(含最小值、最大值) |
in(…) | 在in之后的列表中的值,多选一 |
like 占位符 | 模糊匹配(_ 匹配单个字符,%匹配任意个字符) |
is null | 是null |
逻辑运算符 | 功能 |
---|---|
and或&& | 并且 |
or或|| | 或 |
not或! | 非 |
例子:
1 | select * from emp where name ='初音未来'; |
聚合函数:
select 聚合函数(字段列表) from 表名;
1 | -- 聚合函数 |
分组查询:
select 字段列表 from 表名 [where 条件] group by 分组字段名 [having 分组后过滤条件];
where与having区别
- 执行时间不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组之后对结果进行过滤;
- 判断条件不同:where不能对聚合函数进行判断,而having可以。
执行顺序:where > 聚合函数 > having
分组之后,查询的字段一般为聚合函数和分组字段,查询其他的字段毫无意义
1 | -- 根据性别分组,统计男性员工和女性员工的数量 |
排序查询:
select 字段列表 from 表名 order by 字段1 排序方式,字段2 排序方式;
排序方式:
ASC:升序(默认值)
DESC:降序
如果多字段排序,当第一个字段值相同的时候,才会根据第二个字段进行排序
分页查询:
select 字段列表 from 表名 limit 起始索引,查询记录数;
- 起始索引从0开始,起始索引=(查询页码-1)*每页显示记录数;
- 分页查询是数据库的方言,不同的数据库有不同的实现,MySQL是limit;
- 如果查询的是第一页数据,起始索引可以省略,直接简写为limit 10。
顺序
- 编写顺序:select>from>where>group by>order by>limit
- 执行顺序:from>where>group by>select>order by>limit
DCL-数据控制
管理用户:
1 | -- 查询用户 |
权限控制:
1 | -- 查询权限 |
- 多个权限之间,用逗号分隔;
- 授权时,数据库名和表名可以使用*进行通配,代表所有。
函数
字符串函数
concat(s1,s2,s3,…,sn)字符串拼接
lower(str)转大写
upper(str)转小写
lpad(str,n,pad)用pad左填充
rpad(str,n,pad)用pad右填充
trim(str)去除头部和尾部的空格
substring(str,start,len)截取字符串,索引从1开始
数值函数
ceil向上取整
floor向下取整
mod(x,y)求x/y的模
rand0~1之间的随机数
round(x,y)对x四舍五入后保留y位小数
案例:
1 | -- 产生一个6位数的随机验证码 |
日期函数
curdate()返回当前的日期
curtime()返回当前的时间
now()返回当前的日期和时间
year(date)返回日期的年份
month(date)返回日期的月份
day(date)返回日期的天数
date_add(date,interval expr type)返回一个推移指定时间长度后的日期
1 | select date_add(now(),interval 70 day); |
datediff(date1,date2)求取两个日期之间的天数,前边减后边的
流程函数
if(value,t,f)如果value为true,返回t,为false则返回f
ifnull()如果第一个值为null,则返回第二个值;如果第一个值非null,则返回第一个值
case when [value1] then [res1]… else [default] end如果value1为true,返回res1,…否则返回default
case [expr] when [val1] then [res1]… else [default] end如果expr的值为val1则返回res1,…否则返回default
约束
约束-概述
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制字段值不能为null | not null |
唯一约束 | 保证字段所有数据唯一 | unique |
主键约束 | 主键是一行数据的唯一标识,非空且唯一 | primary key |
默认约束 | 字段未指定值则用默认值 | default |
检查约束(8.0.16版本之后) | 保证字段值满足某一个条件 | check |
外键约束 | 让两张表的数据建立连接 | foreign key |
约束-外键约束
外键约束是让两张表之间的数据建立连接,从而保证数据的一致性。
语法
1 | -- 方法一 |
示例:
1 | -- 添加外键 |
外键删除更新行为
行为 | 说明 |
---|---|
no action | 当在父表中删除/更新对应记录时,首先检查该记录中是否有对应外键,如果有则不允许更改 |
restrict | 当在父表中删除/更新对应记录时,首先检查该记录中是否有对应外键,如果有则不允许更改 |
cascade | 当在父表中删除/更新对应记录时,首先检查该记录中是否有对应外键,如果有,则也删除/更新外键在子表中的记录 |
set null | 当在父表中删除对应记录时,首先检查该记录中是否有对应外键,如果有则设置为null(前提是允许为null) |
set default | 父表有变更时,子表将外键设置成一个默认的值(Innodb不支持) |
1 | alter table 表名 add constraint 外键名称 foreign key(外键字段) references 主表(主表列名) on update cascade on delete cascade; |
多表查询
多表关系
一对多
通常在多的一方添加外键,关联到一的一方的主键
多对多
建立第三方中间表,中间表至少包含两个外键,分别关联两方主键
一对一
通常用于单表查询,或者将其拆分,并在任意一方加入外键来关联。注意在外键中添加unique约束以保证一对一
连接查询
内连接
隐式内连接:select 字段列表 from 表1,表2 where 条件…;
显示内连接:select 字段列表 from 表1 [inner] join 表2 on 连接条件…;
1 | -- 隐式内连接 |
- 内连接查询的是两张表交集的部分
外连接
左外连接
select 字段列表 from 表1 left [outer] join 表2 on 条件…;
相当于查询表1(左表)的所有数据包括交集部分的数据
右外连接
select 字段列表 from 表1 right [outer] join 表2 on 条件…;
相当于查询表2(右表)的所有数据包括交集部分的数据
1 | -- 左外连接 |
常用左外连接实现
自连接
自连接查询使用内连接查询和外连接查询均可,重点是要给一张表起两个不同的别名
内连接查询(例)
select 字段列表 from 表A 别名A join 表 A 别名B on 条件…;
外连接查询(例)
select 字段列表 from 表A 别名A left join 表 A 别名B on 条件…;
联合查询
对于联合查询实际上就是将多次查询的结果合并起来,形成一个新的查询结果集,要使用到关键字union,union all。
语法:
1 | select 字段列表 from 表A… |
- 对于联合查询的多张表的列数和字段类型需要保持一致
- union all会将全部的数据直接贴合在一起,union会对合并之后的数据去重
子查询
标量子查询
子查询的结果是单个的值,就称为标量子查询
例如如下的需求,查询某某部门的所有员工信息
1 | -- 分步查询 |
列子查询
查询的结果为一列多行,就称为列子查询
常用的操作符
操作符 | 描述 |
---|---|
in | 在指定的集合范围之内,多选一 |
not in | 不在指定的集合范围之内 |
any | 子查询返回的列表中,有一个满足即可 |
some | 等同于any |
all | 子查询返回的列表的所有值必须满足 |
行子查询
查询的结果为一行多列,就称为列子查询
1 | -- 查询与“张无忌”的薪资及直属领导相同的员工信息 |
表子查询
查询的结果为多行多列,就称为表子查询。通常将表子查询的结果作为一个新的表进行多表查询。
1 | -- 查询与“鹿杖客”,“宋远桥”的职位和薪资相同的员工信息 |
事务
事务是一组操作的集合,这组操作,要么全部执行成功,要么全部执行失败
事务操作
第一种方式
- 查看/设置事务提交方式
select @@autocommit;
set @@autocommit=1; - 提交事务
commit; - 回归事务
rollback;
第二种方式
- 开启事务
start transaction或begin; - 提交事务
commit; - 回归事务
rollback;
事务的四大特性ACID
原子性、一致性、隔离性、持久性
并发事务问题
问题 | 描述 |
---|---|
脏读 | 一个事务读到另一个事物还没有提交的数据 |
不可重复读 | 一个事务先后读取同一条记录,但两次读取的数据不同 |
幻读 | 一个事务按条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在 |
事务隔离级别
事务的隔离级别就是来解决并发事务问题的,下表表示解决情况。√表示未解决,×表示解决
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable Read(默认) | × | × | √ |
Serializable | × | × | × |
查看事务的隔离级别
select @@transaction_isolation;
设置事务的隔离级别
set [global/session] transaction isolation level [隔离级别];
MySQL-进阶
数据引擎
(说到引擎,我个人的理解,就是类似于驱动的意思,是使一个器件、物体、工具能够具有他最基础的功能,比如车辆能够启动、屏幕能够显示……是不包括后续一些精调定制化的部分的。)
不过这并不是很重要,只要知道存储引擎的特点及如何选择就够了
InnoDB:是MySQL的默认存储引擎,支持事务、外键。如果应用对事物的完整性又比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包含很多的更新、删除操作,那么InnoDB存储引擎是比较合适的选择。
MyISAM:如果应用是以读取和插入为主,很少有更新、删除操作,并且对事务的完整性、并发性要求不是很高,那么选择这个存储引擎比较合适。
MEMORY:将所有数据保存在内存中,访问速度快,通常用于临时表及缓存。MEMORY的缺陷就是对表的大小有限制,太大的表无法缓存在内存中,而且无法保证数据的安全性。
说是这么说,但是实际上主要用的就是InnoDB了,在MyISAM的使用场景基本被nosql系列的数据库取代了,而MEMORY的场景被Redis取代了。
索引
索引(index)本质上一种数据结构,是为了帮助数据库高效获取数据。
索引大大提高了查询效率,同时却也降低了insert、update、delete的效率吗,不过本身查询就是占大头的,所以瑕不掩瑜。
MySQL常用(默认)的结构就是B+Tree(多路平衡搜索树)
- 每一个节点,可以存储多个key
- 所有的数据存储在叶子节点,非叶子节点仅用于索引数据
- 叶子节点形成了一颗双向链表,便于数据的排序及区间范围查询
这种结构实际上就像一个矮胖的树,避免了二叉树容易层级过深的问题。
语法
- 创建索引
create [unique] index 索引名 on 表名(字段名,…);
- 查看索引
show index from 表名
- 删除索引
drop index 索引名 on 表名;
- 建表时如果添加了主键约束,那么就会自动创建主键索引,是性能最高的
- 建表时添加唯一约束,本质就是添加了唯一索引