MySQL 概述
MySQL 数据库的安装
SQL(操作 MySQL 的语言)
函数( MySQL 内置了许多函数,他们有不同的作用)
约束(保证数据的完整性和正确性)
多表查询(结合具体的案例进行操作)
事务(保证数据的安全性)
数据库:数据组织和管理的仓库
MySQL 数据库:是一种组织和管理的数据库软件
SQL:操作关系型数据库的编程语言,定义了一套操作关系型数据库的标准,我们通过 SQL 操作数据库管理系统,进而来操作相关的数据
主流关系型数据库:Oracle、MySQL、Microsoft SQL Server、SQLLite
社区版(MySQL Community Server):免费,MySQL 不提供任何技术支持(我们下载的版本)
商业版(MySQL Enterprise Edition):收费,可以试用30天,官方提供技术支持
MySQL官网:MySQL :: MySQL Downloads
选择社区版下载
我们这里下载Windows版本的
下载完后就可以开始安装配置了
要以管理员身份运行 cmd!
启动:net start MySQL服务名称
关闭:net stop MySQL服务名称
要先开启 MySQL 服务,才能进行客户端连接
可以直接使用 MySQL 自带的连接器
也可以用系统自带的命令行工具
概念:建立在关系模型基础上,由多张相互连接的二维表组成的数据库
特点:
使用表存储数据, 格式统一,便于维护
使用SQL语言操作,标准统一 ,使用方便
使用表来储存数据的即为关系型数据库,反之属于非关系型数据库
当一台计算机,安装完成 MySQL 后,这台计算机就成为 MySQL 数据库服务器
我们可以通过客户端连接数据库管理系统(DBMS)
然后可以使用 SQL 语句通过 DBMS 来创建不同的数据库和表
一个数据库服务器可以创建多个数据库,同时一个数据库也可以创建多张表
每张表中的每一个数据,称为一个记录
通用语法:
SQL语句可以单行或多行书写,以分号结尾
SQL语句可以使用空格缩进来增强语句的可读性
MySQL数据库的SQL语句不区分大小写,关键字建议使用大写
注释:
单行注释:-- 注释内容或 # 注释内容(MySQL特有)
多行注释:/*注释内容*/
DDL:定义数据库对象(数据库,表,字段)
DML:对表中的数据(记录)进行增删改
DQL:对表中的数据(记录)进行查询
DCL:用来创建数据库用户,控制数据库的访问权限
1 查询所有数据库
show databases;
2 查询当前数据库
select database();
3 创建数据库
create database [if not exists] 数据库名称 [default charset] [collate];
4 删除数据库
drop database [if exists] 数据库名称;
5 使用数据库
use 数据库名称;
注意:
不能创建两个同名的数据库(使用语法 if not exists 可以避免创建同名数据库)
上述语法中 [] 中的部分为可选项,可以不填写
default charset 表示创建数据库的字符集(如 utf8,utf8mb4)推荐使用 utf8mb4
collate 表示排序规则
不要删除不存在的数据库(使用语法 if exists)
在我们对某一张表操作之前,首先要进入这张表所在的数据库
1 查询当前数据库中所有的表
show tables;
2 查询当前数据库指定表(查看字段)
desc 表名;
3 查询指定表的建表语句(查看的信息会更加详细)
show create table 表名;
4 创建表
create table 表名 (
字段1 类型 [comment 字段1注释],
字段2 类型 [comment 字段2注释],
字段3 类型 [comment 字段3注释],
...
)[comment 表注释];
5 添加字段
alter table 表名 add 字段名 类型 [comment] [collate];
6 修改字段数据类型
alter table 表名 modify 字段名 新数据类型(长度);
7 修改字段名和数据类型
alter table 表名 change 旧字段名 新字段名 新数据类型(长度);
8 删除字段
alter table 表名 drop 字段名;
9 修改表名
alter table 表名 rename to 新表名;
10 删除表
drop table [if exists] 表名;
truncate table 表名;
注意:
创建表时,出最后一个字段外,每一个字段最后都必须加上逗号(“,”)
每一条语句都以分号结尾
数值类型
说明:
有符号表示允许负数出现,无符号表示不允许负数出现
精度和标度,精度是数据的长度(有多少个数字),标度是小数点后有多少个数字,如3.14,其精度是3,标度是2
在数据类型后面加上 unsigned 表示该数据是无符号的,如 age tinyint unsigned
使用 double 时,要注明数据的长度和标度,如 double(4,1) 表示整体长度为 1 标度为 1
字符串类型
说明:
blob 用于描述二进制数据,test 用于描述文本数据
使用 char 和 varchar 时后面都用指定字符串的最大长度,如 char(表示能存储最大长度为 10 个字符的字符串)
char 是定长字符串,无论我们存储的字符串是多少个字符,最终都以最长字符为准
varchar 是变长字符串,根据我们存储字符串的字符数来确定
char 的性能相较于 varchar会更好
日期类型
1 给指定字段添加数据
insert into 表名(字段1,字段2,...) values(值1,值2,...);
2 给全部字段添加数据
insert into 表名 values(值1,值2,...);
3 批量添加数据
insert into 表名(字段1,字段2,...) values(值1,值2,...),(值1,值2,...),(值1,值2,...)...;
insert into 表名 values(值1,值2,...),(值1,值2,...),(值1,值2,...)...;
注意:
插入数据时,指定的字段顺序需要与值的顺序是一一对应的
字符串和日期型数据应该包含在引号中
插入的数据太小,应该在字段的规定范围内
update 表名 set 字段名1=值1,字段名2=值2,... [where];
注意:
where 表示条件,可以认为是在某一条记录修改,如果没有条件则表示修改整张表的所有记录
delete from 表名 [where]
注意:
where 可有可无,如果没有则表明删除整张表的所有数据
delete 无法删除某个字段的值,它只能删除符合 where 条件记录
日常应用中,DQL的使用频率远高于其他语句,所以需要重点掌握
select
字段列表
from
表名列表
where
条件列表
group by
分组字段列表
having
分组后条件列表
order by
排序字段列表
limit
分页参数
select 字段1,字段2,字段3,... from 表名;
select * from 表名;
select 字段1[as 别名1] from 表名;
select distinct 字段1[as 别名1] from 表名;
注意:
* 表示查询该表所有记录,在实际开发中最好不要使用这个查询所有记录,这样不太直观
我们可以为每一个字段起别名,使用 as 关键字,起别名不是必须的(as 关键字也可以省略)
distinct 表示去除该字段查询结果的重复记录
select 字段列表 from 表名 where 条件列表;
where后面可以跟以下的条件
注意:
一个下划线表示一个字符,% 表示多个字符
between 后面是较小值,and 后面是较大值,不能反写
聚合函数
将一列数据作为一个整体,进行纵向计算
如 count、min、max、avg、sum 都是针对某一列数据(根据字段确定)进行计算
聚合函数使用
select 聚合函数(字段列表) from 表名;
注意:
使用聚合函数时所有的 null 值不参与运算
分组查询
select 字段列表 from 表名 [where 条件列表] group by 分组字段名 [having 分组后过滤条件];
注意:
区别 where 和 having,where 是在分组之前进行过滤,不满足 where 的条件不会过滤,having 是对分组后的结果进行过滤
where 不能使用聚合函数进行判断,而 having 可以
执行顺序:where > 聚合函数 > having
分组之后查询的字段一般为聚合函数和分组字段,查询其他字段没什么意义
排序方式:
select 字段列表 from 表名 order by 字段1 排序方式1,字段2 排序方式2,...;
注意:
排序查询支持多字段排序,当第一个字段值相同则会根据第二个字段值排序
select 字段列表 from 表名 [order by] limit ;起始索引,查询记录数
例子:
select * from table limit 1,5;
表示查询表第二页的数据每页展示5条记录
注意:
起始索引从0开始,起始索引= (查询页码-1) * 每页显示记录数
分页查询是数据库的方言,不同的数据库有不同的实现,MySQL 中是LIMIT
如果查询的是第一页数据,起始索引可以省略,直接简写为limit 10
如果有分组,那么 order by 在 limit 前面
from > where > group by 以及 having > select > order by > limit
注意:后一个执行顺序中的别名无法在前一个执行顺序中使用
用来管理数据库的用户,控制数据库的访问权限
1 查询用户
select * from user;
2 创建用户
create user '用户名'@'主机名' identified by '密码';
3 修改密码
alter user '用户名'@'主机名' identified with mysql_native_password by '新密码';
4 删除用户
drop user '用户名'@'主机名';
注意:
所有的用户都储存在 user 表中,在 user 表中有 host 和 user 两个字段,user 表示用户名 host 表示主机(用于限定用户在哪些主机才可以访问相关数据库)
localhost 表示只当前主机才能访问数据库,% 表示任意主机都可以访问数据库
SQL 开发人员很少使用 DCL 语句,主要是数据库管理人员(DBA)在使用
刚创建的用户并没有分配具体的权限,我们需要为用户分配权限
可以去官方文档中查看更多的权限内容
1 查询权限
show grants for '用户名'@'主机名';
2 授予权限
grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';
3 撤销权限
revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';
注意:
usage:表示只能连接到数据库无其他权限
all privileges on 数据库:表示在该数据库中有所有的权限
多个权限之间使用逗号进行分隔
通配符表示所有(可以是所有数据库或数据库中所有表)
以下是常用的字符串函数
使用函数
SQL语句 = 函数(参数);
例子:
select contact("","");
select lower("");
select lpad("",n,"")
select trim(" hello ")
select substring("hello",1,3)
注意:
substring 起始位置是 1 不是 0;
生成一个六位的随机数
lpad(floor(rand() * 1000000),6,'0')
这里需要一个补 0 的函数,因为最后生成的随机数可能少于 6 位
date_add(now(),INTERVAL 1 MONTH)
表示在当前时间往后推一个月
date_add(now(),INTERVAL 1 DAY)
表示在当前时间往后推一个天
date_add(now(),INTERVAL 1 YEAR)
表示在当前时间往后推一个年
dateiff("2022-3-1","2022-12-01")
表示 2022-3-1 和 2022-12-01 的时间之差
ifnull(null,"hello")
返回 hello
case expr when '' then '' when '' then '' ... end
case when a > 50 then '' when '' then '' ... end
可以增加多个条件
概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据
约束保证了数据的正确性,完整性,有效性,一致性
注意:约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束
create table user (
id int primary key auto_increment ,
name varchar(10) not null unique,
age int check ( age > 0 && age <= 120),
status char(1) default '1',
gender char(1)
) comment '用户名';
插入数据
insert into user(name,age,status,gender) values();
auto_increment:自动增长
外键用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性。
当我们创建外键后,外键为了保证数据的完整性而使我们无法随意删除主表记录,我们也可以设置这种行为
如下图, 其中 dept_id 就是外键,它关联着父表 dept 中的 id 键
1 添加外键
方式一:create table 表名(
字段名 数据类型,
...
[constraint] [外键名称] foreign key(外键字段名) references 主表(主表列名)
);
方式二:
alter table 表名 add constraint 外键名称 foreign key(外键字段名) references 主表(主表列名);
2 删除外键
alter table 表名 drop foreign key 外键名称;
父表并不是永远无法修改的,事实上我们可以设置这种规则
1 cascade 的使用
alter table 表名 add constraint 外键名称 foreign key(外键字段名) references 主表(主表列名) on update cascade on delete cascade;
2 set null 的使用
alter table 表名 add constraint 外键名称 foreign key(外键字段名) references 主表(主表列名) on update set null on delete set null;
注意:
on update 表示更新的规则,即主表发生更新,子表该如何
on delete 表示删除的规则,即主表中有记录被删除,子表该如何
更新和删除的规则可以不一样
项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本.上分为三种:
一对多(多对一)
多对多
一对一
一对多:在多的一方建立外键,指向一的一方
多对多:如学生选择课程,我们需要第三张表来建立多对多的关系,第三张表包含两张表的主键
一对一:多用于单表的拆分,将一张表的基础字段放在一张表中,将详情字段放在另一张表中
实现:在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(unique)
多表查询:在多张表中进行查询
笛卡尔积:笛卡尔乘积是指在数学中,两个集合A集合和B集合的所有组合情况(在多表查询时,需要消除无效的笛卡尔积)
对于多表查询而言,笛卡尔积就是表数据个数的乘积
内连接:相当于查询A、B交集部分数据
外连接:
左外连接:查询左表所有数据,以及两张表交集部分数据
右外连接:查询右表所有数据,以及两张表交集部分数据
自连接:当前表与自身的连接查询,自连接必须使用表别名
查询两张表交集的部分
分为隐式内连接和显示内连接
隐式内连接使用 where 消除笛卡尔积
1 隐式内连接
select 字段列表 from 表1 别名1,表2 别名2 where 条件...;
2 显示内连接
select 字段列表 from 表1 [inner] join 表2 on 条件...;
注意:
一般会为表起一个别名,起别名后只能使用别名来使用表
inner 可以被省略
左外连接:查询左表所有数据,以及两张表交集部分数据
右外连接:查询右表所有数据,以及两张表交集部分数据
1 左外连接
select 字段列表 from 表1 [outer] left join 表2 on 条件...;
2 右外连接
select 字段列表 from 表1 [outer] right join 表2 on 条件...;
自连接就是在同一张表进行查询,比如一张表的某一个字段关联这张表的主键
我们在理解自连接时,可以把一张表看成两张一模一样的表,在这两张一模一样的表进行查询
select 字段列表 from 表1 别名1 join 表1 别名2 on 条件...;
注意:
自连接查询中必须起别名
把多次查询的结果合并起来,形成一个新的结果集,即为联合查询
使用 union 或 union all 关键字
最终的结果集是可能存在重复的部分的,我们直接使用 union 关键字查询可以去重
select 字段列表 from 表1...
union [all]
select 字段列表 from 表2...;
注意:
对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致
union all 会将全部的数据直接合并在一起,union 会对合并之后的数据去重
子查询又为嵌套查询,是SQL语句中嵌套 select 语句
子查询外部的语句可以是 insert/ update/ delete/ select 的任何一个
根据查询结果分类:
标量子查询(子查询结果为单个值)
列子查询(子查询结果为一 列)
行子查询(子查询结果为一行)
表子查询(子查询结果为多行多列)
根据子查询位置分类:
where之后、from之后、select之后
标量子查询
子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询成为标量子查询
常用的操作符:= <> > >= < <=
实例
1 查询张三的入职日期后的所有员工日期
A 先查询张三的入职日期
B 查询所有员工日期 where > (张三入职日期)
列子查询
子查询返回的结果是一列(可以是多行),这种子查询称为列子查询
实例
1 查询 销售部 和 市场部 的所有员工信息
A 查询 销售部 和 市场部 的部门id
B 查询员工表 in (A的SQL语句)
行子查询
子查询返回的结果是一行(可以是多列),这种子查询称为行子查询
常用的操作符: =、<>、in、not in
表子查询
子查询返回的结果是多行多列,这种子查询称为表子查询。
常用的操作符:IN
实例
查询和 张三 和 李四 薪资和职位相同的员工信息
A 查询 张三 和 李四 薪资和职位
B select * from emp where (job,salary) in (A的SQL语句)
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向 系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败
比较典型的事务是银行转账,如张三向李四转账500元,操作如下
查询张三账户的余额
张三账户余额-500
李四账户余额+500
这三部操作就必须控制在一个事务的范围内,使其要不全部成功要不全部失败
如果中间某个操作出现异常,我们就需要回滚事务,使数据护恢复至事务开启以前的情况
默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务
create table account (
id int primary key auto_increment,
name varchar(10),
money int
) comment '账户表';
-- 插入数据
insert into account(id,name,money) values (null,'张三',2000),(null,'李四',2000);
-- 恢复数据
update account set money=2000 where name='张三' or name='李四';
-- 1 查询张三余额
select money from account where name='张三';
-- 2 将张三余额-500
update account set money = money - 500 where name='张三';
-- 3 将李四余额+500
update account set money = money - 500 where name='李四';
-- 以上是正确的情况!!!!
-- 以下是错误的情况!!!!
-- 1 查询张三余额
select money from account where name='张三';
-- 2 将张三余额-500
update account set money = money - 500 where name='张三';
我们写一条非SQL语句,在这里产生异常
-- 3 将李四余额+500
update account set money = money - 500 where name='李四';
1 查看/设置事务提交方式
select @@autocommit;
set @@autocommit = 0; -- 设置为手动提交
2 提交事务
commit
3 回滚事务
rollback
4 开启事务
start transaction 或 begin
注意:
当我们把事务设置为手动提交时,如果我们不提交事务,即使我们使用DML修改表中记录,相应表的数据也不会被改变
当我们程序出现错误时,我们需要回滚事务,将记录复原
-- 开启事务,需要手动提交事务
start transaction
-- 1 查询张三余额
select money from account where name='张三';
-- 2 将张三余额-500
update account set money = money - 500 where name='张三';
我们写一条非SQL语句,在这里产生异常
-- 3 将李四余额+500
update account set money = money - 500 where name='李四';
-- 如果事务执行成功,则提交事务
commit
-- 如果事务执行失败,则回滚事务
rollback
原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败
一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态
隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行
持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的
隔离性可以理解为,两个不同的事务操作同一个数据库彼此之间互不影响
多个并发的事务可能会产生下面的问题
脏读:比如A事务修改了数据库中的某个记录,但并没有提交,B事务读取到了这个修改了但没提交的记录
不可重复读:A事务查询了某个记录,然后B事务修改了这个记录,最后A事务又查询了相同的记录,两次结果不一
隔离级别用来解决并发事务产生的问题
事务的隔离级别越高往往性能也就越差,所以我们既要考虑安全性又要考虑性能,不能仅仅为了安全而盲目选择隔离级别最高的
查看事务隔离级别
select @@transaction_isolation;
设置事务隔离级别
set [session|global]transaction isolation level 隔离级别;
注意:
session:表示针对当前客户端窗口有效
global:表示针对所有客户端窗口有效