Skip to content

Mysql 指南

常用命令

bash

mysql -u root -p   # 登录
show databases;   # 查看数据库
select version();   # 查看数据库版本
use database_name;   # 使用数据库
create database database_name;   # 创建数据库
show tables;   # 查看表
desc table_name;   # 查看表结构
select * from table_name;   # 查看表数据

mysql -u root -p   # 登录
show databases;   # 查看数据库
select version();   # 查看数据库版本
use database_name;   # 使用数据库
create database database_name;   # 创建数据库
show tables;   # 查看表
desc table_name;   # 查看表结构
select * from table_name;   # 查看表数据

DQL 查询语句

简单查询

bash
select field_name from tabel_name;  # 查询表中单个的字段
select field_name1,field_name2 from tabel_name;  # 查询表中多个的字段
select * from tabel_name;  # 查询表中所有的字段
select field_name as 别名 from tabel_name;  # 查询表中字段并起别名
select field_name newFieldName from tabel_name;  # 查询表中字段并起别名 省略as
select field_name 'new Field Name' from tabel_name;  # 查询表中字段并起别名 使用单引号(有空格)
select field_name * number from table_name;  # 查询表中字段并乘以一个数(参与数学运算)
select field_name from tabel_name;  # 查询表中单个的字段
select field_name1,field_name2 from tabel_name;  # 查询表中多个的字段
select * from tabel_name;  # 查询表中所有的字段
select field_name as 别名 from tabel_name;  # 查询表中字段并起别名
select field_name newFieldName from tabel_name;  # 查询表中字段并起别名 省略as
select field_name 'new Field Name' from tabel_name;  # 查询表中字段并起别名 使用单引号(有空格)
select field_name * number from table_name;  # 查询表中字段并乘以一个数(参与数学运算)

条件查询

bash
select field_name from tabel_name where field_name = 'value';  # 查询表中字段并指定条件
select field_age from tabel_name where field_age > 19 and field_age < 30;  # and:并且 or:或者
select field_age from tabel_name where field_age between 19 and  30;  # and:并且 or:或者

select * from table_name whele sex = male and (age > 18 or age <23);  # and:并且 or:或者
# and 优先级比or高,想让or先执行可以使用括号来提高优先级
select field_age from tabel_name where field_age is null;  #查询字段为null
select field_age from tabel_name where field_age is not null;  #查询字段不为null

select * from tabel_name where field_age = 18 or field = 20;  # 查询字段为18或者20

select * from table_name where field_age in (18,20);  # in操作符 (不是区间,是指18或20)
select * from table_name where field_age not in (18,20);  # in操作符取反

select * from table_name whele field_name like '%o%';  # like操作符 %:任意多个字符 查询名字有o的
select * from table_name whele field_name like '%o';  #  查询名字以o结尾的
select * from table_name whele field_name like 'o%';  #  查询名字以o开头的
select * from table_name whele field_name like '_o%';  #  _:任意单个字符 查询名字第二个字符是o的
select * from table_name whele field_name like '_o_';  #  查询名字第二个字符是o的
select * from table_name whele filed_name like '% /_%'; #  查询名字中包含_的
select field_name from tabel_name where field_name = 'value';  # 查询表中字段并指定条件
select field_age from tabel_name where field_age > 19 and field_age < 30;  # and:并且 or:或者
select field_age from tabel_name where field_age between 19 and  30;  # and:并且 or:或者

select * from table_name whele sex = male and (age > 18 or age <23);  # and:并且 or:或者
# and 优先级比or高,想让or先执行可以使用括号来提高优先级
select field_age from tabel_name where field_age is null;  #查询字段为null
select field_age from tabel_name where field_age is not null;  #查询字段不为null

select * from tabel_name where field_age = 18 or field = 20;  # 查询字段为18或者20

select * from table_name where field_age in (18,20);  # in操作符 (不是区间,是指18或20)
select * from table_name where field_age not in (18,20);  # in操作符取反

select * from table_name whele field_name like '%o%';  # like操作符 %:任意多个字符 查询名字有o的
select * from table_name whele field_name like '%o';  #  查询名字以o结尾的
select * from table_name whele field_name like 'o%';  #  查询名字以o开头的
select * from table_name whele field_name like '_o%';  #  _:任意单个字符 查询名字第二个字符是o的
select * from table_name whele field_name like '_o_';  #  查询名字第二个字符是o的
select * from table_name whele filed_name like '% /_%'; #  查询名字中包含_的

排序查询

bash
select * from table_name order by field_name;  # 升序
select * from table_name order by field_name desc;  # 降序(asc指定升序)
select * from table_name order by field_name1,field_name2;  # 多个字段排序
select * from table_name order by field_name1 asc,field_name2 asc; # 这意味着首先按 "field_name1" 进行排序,如果有多行具有相同的 "field_name1" 值,则再按 "field_name2" 进行排序
select * from table_name order by field_name;  # 升序
select * from table_name order by field_name desc;  # 降序(asc指定升序)
select * from table_name order by field_name1,field_name2;  # 多个字段排序
select * from table_name order by field_name1 asc,field_name2 asc; # 这意味着首先按 "field_name1" 进行排序,如果有多行具有相同的 "field_name1" 值,则再按 "field_name2" 进行排序

数据处理函数

单行处理函数

数据处理函数又称为单行函数,是对一组数据进行操作,返回一个单一的结果 常见的数据处理函数有:lower,upper,substr,length,concat,round,floor,ceil,mod,now,rand,date_format,ifnull,if ,case when then else end

bash
select lower(field_name) from table_name;  # 将字段转换为小写
select upper(field_name) from table_name;  # 将字段转换为大写
select substr(field_name,1,2) from table_name;  # 截取字段
select length(field_name) from table_name;  # 获取字段长度
select concat(field_name1,field_name2) from table_name;  # 拼接字段
select round(field_name) from table_name;  # 四舍五入
select floor(field_name) from table_name;  # 向下取整
select ceil(field_name) from table_name;  # 向上取整
select mod(field_name) from table_name;  # 取余
select now() from table_name;  # 获取当前时间
select rand() from table_name;  # 获取随机数
select date_format(field_name,'%Y-%m-%d') from table_name;  # 格式化日期
select ifnull(field_name,'替换值') from table_name;  # 替换null值
select if(field_name1 > field_name2,'大于','小于') from table_name;  # if函数
select case field_name when 'value1' then '替换值1' when 'value2' then '替换值2' else '替换值3' end from table_name;  # case when then else end

select name,(salary + bonus) * 12 from employee;  # 计算年薪
# ifnull 函数判断为空
select name,(ifnull(salary,0) + ifnull(bonus,0)) * 12 from employee;  # 有null的情况下
select lower(field_name) from table_name;  # 将字段转换为小写
select upper(field_name) from table_name;  # 将字段转换为大写
select substr(field_name,1,2) from table_name;  # 截取字段
select length(field_name) from table_name;  # 获取字段长度
select concat(field_name1,field_name2) from table_name;  # 拼接字段
select round(field_name) from table_name;  # 四舍五入
select floor(field_name) from table_name;  # 向下取整
select ceil(field_name) from table_name;  # 向上取整
select mod(field_name) from table_name;  # 取余
select now() from table_name;  # 获取当前时间
select rand() from table_name;  # 获取随机数
select date_format(field_name,'%Y-%m-%d') from table_name;  # 格式化日期
select ifnull(field_name,'替换值') from table_name;  # 替换null值
select if(field_name1 > field_name2,'大于','小于') from table_name;  # if函数
select case field_name when 'value1' then '替换值1' when 'value2' then '替换值2' else '替换值3' end from table_name;  # case when then else end

select name,(salary + bonus) * 12 from employee;  # 计算年薪
# ifnull 函数判断为空
select name,(ifnull(salary,0) + ifnull(bonus,0)) * 12 from employee;  # 有null的情况下

分组函数

count 基数,sum 求和,avg 平均值,max 最大值,min 最小值

bash
select count(*) from table_name;  # 统计表中的记录数
select count(field_name) from table_name;  # 统计表中指定字段的记录数
select count(distinct field_name) from table_name;  # 统计表中指定字段的不重复记录数
select sum(field_name) from table_name;  # 求和
select avg(field_name) from table_name;  # 平均值
select max(field_name) from table_name;  # 最大值
select min(field_name) from table_name;  # 最小值
select count(*) from table_name;  # 统计表中的记录数
select count(field_name) from table_name;  # 统计表中指定字段的记录数
select count(distinct field_name) from table_name;  # 统计表中指定字段的不重复记录数
select sum(field_name) from table_name;  # 求和
select avg(field_name) from table_name;  # 平均值
select max(field_name) from table_name;  # 最大值
select min(field_name) from table_name;  # 最小值

分组查询

bash
 # 按职位分组求和
select job sum(sal) from 'table_name' group by job;
 # 按职位分组求和 并且求和大于1000
select job sum(sal) from 'table_name' group by job having sum(sal) > 1000;
# 按部门分组求最高工资
select deptno,max(sal) from table_name group by deptno
# 按部门和职位分组求最高工资
select deptno,job,max(sal) from table_name group by deptno,job
# 按部门分组求最高工资 并且最高工资大于2000
select deptno,max(sal) from table_name group by deptno having max(sal) > 2000  #效率很低
# 先过滤再分组
select deptno,max(sal) from table_name where sal > 2000 group by deptno
 # 按职位分组求和
select job sum(sal) from 'table_name' group by job;
 # 按职位分组求和 并且求和大于1000
select job sum(sal) from 'table_name' group by job having sum(sal) > 1000;
# 按部门分组求最高工资
select deptno,max(sal) from table_name group by deptno
# 按部门和职位分组求最高工资
select deptno,job,max(sal) from table_name group by deptno,job
# 按部门分组求最高工资 并且最高工资大于2000
select deptno,max(sal) from table_name group by deptno having max(sal) > 2000  #效率很低
# 先过滤再分组
select deptno,max(sal) from table_name where sal > 2000 group by deptno

连接查询

从一张表中单独查询称为单表查询,从多张表中查询称为多表查询也叫连接查询

bash

select name,cname from table_name1,table_name2;  # 笛卡尔积
#  内部连接  等值连接
#  查询效率很慢, name,以及cname不知道是哪个表的字段
select name,cname
from table_name1,table_name2
where table_name1.id = table_name2.id;  # 内连接
# 优化写法并给表起别名 92版本之前 语意不清晰,汇总后表的数据如果还要过滤则需要使用and 或者having
select a.name,b.name from table_name1 a,table_name2 b where a.id = b.id;  # 内连接

# 98版本之后 使用inner明确是内连接
select a.name b.name
from worker a
inner join jiajia b
on a.id = b.id
where a.salary>5000;  # 内连接

```bash
# 内部连接 非等值连接
# 查询员工的工资等级 并且统计工资等级大于3的信息,并且按照等级升序排列
select a.name,b.name
from worker a
inner join jiajia2 b
on a.salary between b.losal and b.hisal # 范围
where b.grade > 3
order by b.grade;

select name,cname from table_name1,table_name2;  # 笛卡尔积
#  内部连接  等值连接
#  查询效率很慢, name,以及cname不知道是哪个表的字段
select name,cname
from table_name1,table_name2
where table_name1.id = table_name2.id;  # 内连接
# 优化写法并给表起别名 92版本之前 语意不清晰,汇总后表的数据如果还要过滤则需要使用and 或者having
select a.name,b.name from table_name1 a,table_name2 b where a.id = b.id;  # 内连接

# 98版本之后 使用inner明确是内连接
select a.name b.name
from worker a
inner join jiajia b
on a.id = b.id
where a.salary>5000;  # 内连接

```bash
# 内部连接 非等值连接
# 查询员工的工资等级 并且统计工资等级大于3的信息,并且按照等级升序排列
select a.name,b.name
from worker a
inner join jiajia2 b
on a.salary between b.losal and b.hisal # 范围
where b.grade > 3
order by b.grade;
bash
# 内部连接 自连接
# 在一张表中查出员工以及老板以及他们的编号 (员工和老板在一张表,员工的老板编号是老板编号)
# 思路:把一张表看成2张表
SELECT
    a.ename as '员工',
    a.mgr,
    b.ename as '老板',
    b.empno
from emp a
    INNER JOIN emp b on a.mgr = b.empno
# 内部连接 自连接
# 在一张表中查出员工以及老板以及他们的编号 (员工和老板在一张表,员工的老板编号是老板编号)
# 思路:把一张表看成2张表
SELECT
    a.ename as '员工',
    a.mgr,
    b.ename as '老板',
    b.empno
from emp a
    INNER JOIN emp b on a.mgr = b.empno
bash
#外部连接
# 根据员工的部门编号查询员工的信息以及部门的信息(部门表中存有null)
select e.ename,d.dname
from emp e
right join dept d
on e.deptno = d.deptno;  # 右外连接 也可以左连接
#right表示将右边的表作为主表,主表的信息都要,次表为emp

# 根据员工上级编号查询员工的信息以及上级的信息(员工表中存有null)并且将带有null的员工信息也查询出来、
select a.ename as '员工',b.ename as '上级'
from emp a
left join emp b
on a.mgr = b.empno;  # 左外连接(主表要确定清楚!!!)
#外部连接
# 根据员工的部门编号查询员工的信息以及部门的信息(部门表中存有null)
select e.ename,d.dname
from emp e
right join dept d
on e.deptno = d.deptno;  # 右外连接 也可以左连接
#right表示将右边的表作为主表,主表的信息都要,次表为emp

# 根据员工上级编号查询员工的信息以及上级的信息(员工表中存有null)并且将带有null的员工信息也查询出来、
select a.ename as '员工',b.ename as '上级'
from emp a
left join emp b
on a.mgr = b.empno;  # 左外连接(主表要确定清楚!!!)
bash
# 多张表连接
# 要求查询员工姓名,部门名称,工资,工资等级,老板信息 其中员工的老板编号为null的也要显示出来
select a.ename as '员工',d.dname as '部门',a.sal as '工资',c.grade as '工资等级',b.ename as '老板'
from emp a
left join emp b
on a.mgr = b.empno
left join salgrade c
on a.sal between c.losal and c.hisal
left join dept d
on a.deptno = d.deptno;
# 多张表连接
# 要求查询员工姓名,部门名称,工资,工资等级,老板信息 其中员工的老板编号为null的也要显示出来
select a.ename as '员工',d.dname as '部门',a.sal as '工资',c.grade as '工资等级',b.ename as '老板'
from emp a
left join emp b
on a.mgr = b.empno
left join salgrade c
on a.sal between c.losal and c.hisal
left join dept d
on a.deptno = d.deptno;

子查询

bash
select
    ...(select)
    from
    ...(select)
    where
    ...(select)
select
    ...(select)
    from
    ...(select)
    where
    ...(select)
bash
# where 中的子查询
select ename,sal from emp where sal
> (select min(sal) from emp)

# from中的子查询
# 找出员工单位,平均薪资以及平均薪资的薪资等级

# 思路 先找 员工信息以及平均薪资
select job,avg(sal) from emp group by job; #把它看成一张表

# 再找出平均薪资的薪资等级
select t1.*,t2.grade
from (select job,avg(sal) avgvgsal from emp group by job) t1
join salgrade t2 on t1.avgvgsal between t2.losal and t2.hisal;

# unione 相加查询结果
select ename,job from emp where job in('MANAGER','SALESMAN')

select eanme,job from emp where job = 'manager'
unione
select eanme,job from emp where job = 'salesman'


# limit 限制查询结果数量
# limit resultlength
# limit startNum,resultlength
# limit 在order by之后
select * from emp limit 3; # 查询前三条
select * from emp limit 3,3; # 查询第四条开始的三条


# limit 分页

# 用户发起请求包含字段 1:当前页码,字段 2:每页显示的条数,则对应的 sql 语句为

select * from table_name limit (page - 1) * pageSize,pageSize;
# where 中的子查询
select ename,sal from emp where sal
> (select min(sal) from emp)

# from中的子查询
# 找出员工单位,平均薪资以及平均薪资的薪资等级

# 思路 先找 员工信息以及平均薪资
select job,avg(sal) from emp group by job; #把它看成一张表

# 再找出平均薪资的薪资等级
select t1.*,t2.grade
from (select job,avg(sal) avgvgsal from emp group by job) t1
join salgrade t2 on t1.avgvgsal between t2.losal and t2.hisal;

# unione 相加查询结果
select ename,job from emp where job in('MANAGER','SALESMAN')

select eanme,job from emp where job = 'manager'
unione
select eanme,job from emp where job = 'salesman'


# limit 限制查询结果数量
# limit resultlength
# limit startNum,resultlength
# limit 在order by之后
select * from emp limit 3; # 查询前三条
select * from emp limit 3,3; # 查询第四条开始的三条


# limit 分页

# 用户发起请求包含字段 1:当前页码,字段 2:每页显示的条数,则对应的 sql 语句为

select * from table_name limit (page - 1) * pageSize,pageSize;

DQL 语句总结 select ... from ... where ... group by ... having ... order by ... limit ...

执行顺序 from -> where -> group by -> having -> select -> order by -> limit

DDL

DDL 包括 creat ,drop , alter

建表

bash
    create table table_name(
        field_name1 field_type1,
        field_name2 field_type2,
        field_name3 field_type3,
        ...
        field_nameN field_typeN
    );
    ```
    create table table_name(
        field_name1 field_type1,
        field_name2 field_type2,
        field_name3 field_type3,
        ...
        field_nameN field_typeN
    );
    ```

数据类型

typedes
varchar可变长度字符串,动态分配空间
char定长字符串,固定分配空间
int数字的整数型
bigint数字的长整形
flot单精度浮点型
double双精度浮点型
date短日期类型 YYYY-MM-DD
time存储时间 HH:MM:SS
datetime长日期类型 YYYY-MM-DD HH:MM:SS
clob字符大对象 最多 4G 的字符串比如存储文章
text用于存储大量的文本数据,最大长度为 65535 个字符
blob图片,声音,视频,等流媒体数据
jsonjson 格式数据

删除表

bash
# 如果表存在则删除,直接删除如果表不存在则会报错
drop table if exists table_name;
# 如果表存在则删除,直接删除如果表不存在则会报错
drop table if exists table_name;

DML

DML 包括 insert ,update ,delete

bash
# insert 插入数据
insert into table_name(field_name1,field_name2,field_name3) values(value1,value2,value3);
insert into table_name values(value1,value2,value3); # 表示插入所有字段
# 插入多条数据
inser into table_name values
(value1,...),
(value1,...),
(value1,...),
(value1,...),
(value1,...)
# insert 插入数据
insert into table_name(field_name1,field_name2,field_name3) values(value1,value2,value3);
insert into table_name values(value1,value2,value3); # 表示插入所有字段
# 插入多条数据
inser into table_name values
(value1,...),
(value1,...),
(value1,...),
(value1,...),
(value1,...)
bash
# update 更新数据
# 没有条件会更新所有数据
 update table_name set field_name1 = value1,field_name2 = value2 where 条件;
# update 更新数据
# 没有条件会更新所有数据
 update table_name set field_name1 = value1,field_name2 = value2 where 条件;
bash
# delete 删除数据
# 没有条件会删除所有数据
delete from table_name where 条件;

# 这种删除效率比较慢,虽然数据被删除,但是表的空间没有被释放,
# 但如果删除后后悔了可以使用rollback回滚得到数据
truncate table_name; # 删除表中所有数据并且释放表空间 ,还不能回滚
# delete 删除数据
# 没有条件会删除所有数据
delete from table_name where 条件;

# 这种删除效率比较慢,虽然数据被删除,但是表的空间没有被释放,
# 但如果删除后后悔了可以使用rollback回滚得到数据
truncate table_name; # 删除表中所有数据并且释放表空间 ,还不能回滚

约束

  1. 非空约束 not null 约束的字段不能为 null
  2. 唯一约束 unique 约束的字段不能重复 但是可以为 null
  3. 主键约束 primary key
  4. 外键约束 foreign key
  5. 检查约束 check
  6. 默认约束 default

当约束没有在列的后面称为表级约束,当约束在列的后面称为列级约束
使用表级约束的情况:多个字段需要联合约束

当一个字段同时被 not null 以及 unique 约束时,字段成为主键约束

主键约束

主键值是每一行记录的唯一标识,类似于每个人的身份证号码,任何一张表都应该有主键,没有主键,表无效!!

主键特征:unique + not null

bash
create table table_name (
    id int, # primary key 一个字段作主键为单一主键
    name vachar(255),
    primary key(id,name) # 多个字段作为主键为联合主键
)
# 在实际开发不建议使用联合主键, 单一主键即可
# 一张表只能有一个主键

# 主键自增
create table table_name (
    id int primary key auto_increment,
    name vachar(255)
)
# 下面就不需要指定id的值了
insert into table_name(name) values('张三');
insert into table_name(name) values('张三');
insert into table_name(name) values('张三')
create table table_name (
    id int, # primary key 一个字段作主键为单一主键
    name vachar(255),
    primary key(id,name) # 多个字段作为主键为联合主键
)
# 在实际开发不建议使用联合主键, 单一主键即可
# 一张表只能有一个主键

# 主键自增
create table table_name (
    id int primary key auto_increment,
    name vachar(255)
)
# 下面就不需要指定id的值了
insert into table_name(name) values('张三');
insert into table_name(name) values('张三');
insert into table_name(name) values('张三')

外键约束

bash
# 先创建父表
create table t_father (
    classno init primary key,
    classname varchar(255)
)
# 再创建子表
create table t_son  if not exists (  #不存在就创建
    id int primary key auto_increment,
    name varchar(255),
    classno int,
    foreign key(classno) references t_father(classno)
    # classno 是子表的字段,t_father(classno) 是父表的字段
)
# 先创建父表
create table t_father (
    classno init primary key,
    classname varchar(255)
)
# 再创建子表
create table t_son  if not exists (  #不存在就创建
    id int primary key auto_increment,
    name varchar(255),
    classno int,
    foreign key(classno) references t_father(classno)
    # classno 是子表的字段,t_father(classno) 是父表的字段
)

事务

事务就是一个完整的业务逻辑,是一个最小的工作单元,不可再分 只有 dml 语句才有事务一说,数据一旦涉及到增,删,改,就一定要考虑安全问题,数据安全第一位

提交事务 清空事务日志,释放事务占用的资源,将数据全部持久化到数据库表中 提交事务标志着,事务的结束,并且是一种全部成功的结束

回滚事务 将之前所有的 DML 操作(update,insert,delete)全部撤销,并且清空事务性活动的日志文件, 回滚事务标志着,事务的结束,并且是一种全部失败的结束

如何提交事务

提交事务 commit 回滚事务 rollback

事务对应的英语单词是 transaction

mysql 的事务默认是自动提交的,也就是说每执行一条 dml 语句就会自动提交一次事务

关闭 mysql 自动提交机制

bash
start transaction; # 开启事务
start transaction; # 开启事务

然后我们就可以回滚了