跳到主要内容

启动和登录

mysql -u[账户] -p[密码]

// 修改登录密码
// 1. 用 setpassword 命令,首先登录mysql
mysql > set password for 用户名@localhost = password('新密码')

// 2. 用 mysqladmin
mysqladmin -uroot -p旧密码 password 新密码

// mac 登录 我的密码是 root
/usr/local/mysql/bin/mysql -u root -p

SQL 语句分类

  • DQL(数据查询语句):查询语句,凡事 Select 语句都是 DQL;
  • DML(数据操作语句):insert delete update,对表当中的数据进行增删改查;
  • DDL(数据定义语句):create drop alter,对表结构的增删改查;
  • TCL(事物控制语句):commit 提交事物,rollback 回滚事物;
  • DCL(数据控制语句):grant 授权、revoke 撤销权限等

mysql 的语句(DML)

show databases; 查看数据库

create database 数据库名称; 创建数据库

drop database 数据库名称; 删除数据库

use 数据库名称; 进入数据库

show tables;查看表格

source sql脚本路径执行脚本,导入数据

desc 表名;查看表结构

select * from 表;查看表中的数据

select database();查看当前使用的数据库

show version();查看数据库版本

退出 mysql:\q 或者 QUIT 或者 EXIT

查看创建表的语句:show create table 表;

sql 语句(DQL)

简单查询语句

select 字段名1,字段名2,字段名3,... from 表名;

select empno,ename,sal * 12 from emp;

# 查询并重命名
select empno,ename,sal * 12 as yearsal from emp;

条件查询

image-20210719220151963

语法:select 字段 from 表 where 条件;

select empno,ename,sal from emp where sal = 5000;

select empno,ename,sal from emp where sal >= 1000 and sal <= 3000;

select empno,ename,comm from emp where comm is null or comm = 0;

select empno,ename,comm from emp where comm is not null or comm = 0;

select empno,ename,job from emp where job = 'salesman' or job = 'manager';

select empno,ename,job from emp where job in ('salesman','manager');

# like 模糊查询 %代表多个字符,_代表1个字符:

select empno,ename from emp where ename like '%O%';

select empno,ename from emp where ename like '%\_%';

数据排序

  • asc 升序
  • desc降序
# 按照工资升序排:
select empno,ename,sal from emp order by sal asc;

# 工资降序排,工资一样名字升序排:
select empno,ename,sal from emp order by sal desc, ename asc;

select empno,ename,sal from emp where job = 'salesman' order by sal asc, ename desc;

分组函数(多行处理函数)

count:取得记录数;select count(*) from emp;

sum:求和;select sum(sal) as total from emp; sum 自动忽略 null

avg:取平均值;select avg(sal) from emp;

max/min:取最大/小值select max(sal) from emp;

分组函数自动忽略 null;

找出工资高于平均工资的员工:

分组函数不能用在 where 中!

count(*) 和 count(字段)的区别?

count(*) 表示所有,count(字段)表示该字段不为空的。

单行处理函数

在数学表达式中,有 null 参与,结果都是 null

select ename,(sal+comm) * 12 as total from emp;

# ifnull(字段,新增)

select ename,ifnull(comm,0),(sal+ifnull(comm,0)) * 12 as total from emp;

group by 和 having

  • group by:按照某个字段或者某些字段进行分组;
  • having:是对分组之后的数据进行再次过滤。

案例:找出每个工作岗位的最高薪资?

select * from emp order by job;
select max(sal) from emp group by job;
select ename,job,max(sal) from emp group by job;
# group by 实在 where 执行结束之后执行
select ename,sal from emp where sal > (select avg(sal) from emp);

# sql 顺序
select 5
..
from 1
..
where 2
..
group by 3
..
having 4
..
order by 6
..

# 找出每个工作岗位的最高薪资
select job,max(sal) from emp group by job;

select ename,job,max(sal) from emp group by job; # 无意义

# 每一个工作岗位的平均薪资
select job,avg(sal) from emp group by job;

# 多个字段能不能联合起来一块分组
# 找出每个部门不同岗位的最高薪资
select deptno,job,max(sal) from emp group by deptno,job;

# 找出每个部门的最高薪资,要求显示薪资大于2900的数据
select deptno,max(sal) from emp group by dempno;
having max(sal) > 2900;

select deptno,max(sal) from emp group by deptno having max(sal) > 2900;
select deptno,max(sal) from emp where sal > 2900 group by dempno;

# 找出每个部门的平均薪资,要求显示薪资大于2000 的数据
select deptno,avg(sal) from emp group by emptno;
select deptno,avg(sal) from emp group by emptno having avg(sal) > 2000;

# 查询工作岗位并去重
select destinct job from emp;
select destinct deptno,job from emp; # 联合去重

当一条语句中有 group by 的话,select 后面只能跟分组函数和参与分组的字段。

连接查询

内连接:等值连接、非等值连接、自连接

外连接:左外连接、右外连接

# 找出员工名和所在的部门名
# 1.找出员工名和部门编号 A表的外键
select ename,deptno from emp;
# 2.找出部门编号对应的部门名 B表的主键
select deptno,dname from dept;
# 最终 SQL92语法
select e.ename,e.deptno,d.dname from emp e,dept d where e.deptno = d.deptno;

# 内连接 等值连接:最大特点:条件是等量关系
# 找出员工名和所在的部门名SQL99语法
select e.ename,e.deptno,d.dname from emp e inner join dept d on e.deptno = d.deptno; # inner 可以省略
# select e.ename,e.deptno,d.dname from emp e join dept d on e.deptno = d.deptno where ...;

# 内连接 非等值连接:最大特点:条件是非等量关系
# 找出每个员工的工资等级,要求显示员工名、工资、工资等级。
select e.ename,e.sal,s.grade from emp e inner join salgrade s on e.sal between s.losal and s.hisal;

# 内连接 自连接:最大特点:一张表看成俩张表,自己连接自己。
# 找出每个员工的上级领导,要求显示员工名,员工编号,以及领导名和编号
select a.empno,a.ename,b.ename as '领导',b.empno as '领导编号' from emp a inner join emp b on a.mgr = b.empno; # null 会被 丢失

外连接

什么是外连接,和内连接有什么区别?

内连接:

  • 假设 A 和 B 两张表,使用内连接,凡是 A 表和 B 表能够匹配上的记录都查询出来,这就是内连接
  • AB 两张表没有主副之分,两张表是平等的。

外连接

  • 假设 A 表和 B 表进行连接,使用外连接的话,AB 两张表中有一张表是主表,一张表是副表,主要查询主表中 的数据,捎带着查询副表,当副表中的数据没雨和主表中的数据匹配上,副表自动模拟出 null 与之匹配。
  • 外连接的特点:主表中的数据无条件的全部查询出来。
# 找出每个员工的上级领导,要求显示员工名,员工编号,以及领导名和编号
select a.ename as '员工',b.ename as '领导' from emp a left join emp b on a.mgr = b.empno;
# null 也会被查出来
select a.ename,a.empno,b.ename,b.empno from emp b right outer join emp a on a.mgr =
b.empno;

# 找出没有员工的部门
# 找出部门和员工所在部门对应的所有数据,部门编号在副表不存在,副表自动模拟出 null 与之匹配(说明该部门没有员工)
# where 筛选 null
select b.* from emp a right join dept b on a.deptno = b.deptno where a.empno is null;

三张表连接

# 找出员工的部门名称和工资等级 两次 join...on...
select
e.ename,e.sal,d.dname,s.grade
from
emp e
join
dept d
on
e.deptno = d.deptno
join
salgrade s
on
e.sal
between
s.losal
and
s.hisal;

# 找出员工的部门名称和工资等级、上级领导
select
e.ename '员工',d.dname '部门',s.grade '工资等级',el.ename '领导'
from
emp e
join
dept d
on
e.deptno = d.deptno
join
salgrade s
on
e.sal
between
s.losal
and
s.hisal
left join
emp el
on
e.mgr = el.empno;

子查询

select 语句当中嵌套 select 语句,被嵌套的 select 就是子查询。

select
...(select)...
from
...(select)...
where
...(select)...

# 找出高于平均薪资的员工信息 where (select)...
select e.ename,e.sal,avg(sal) from emp e where sal > (select avg(sal) from emp);

# 找出每个部门的平均薪资的薪资等级(按照部门编号分组,求 sal 的平均值) from (select)...
# select deptno,avg(sal) from emp group by deptno;

select t.*,s.grade from (select deptno,avg(sal) as avgsal from emp group by deptno) t join salgrade s on t.avgsal between s.losal and s.hisal;

# 找出每个部门平均的薪水等级。
# 1. 找出每个员工的薪资等级
select e.ename,e.sal,e.deptno,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal;
# 2. 基于以上结果,继续按照deptno继续分组,求 grade 平均值。
select e.ename,e.sal,e.deptno,s.grade,avg(s.grade) from emp e join salgrade s on e.sal between s.losal and s.hisal group by e.deptno;

# select 后面的子查询
# 找出每个员工所在的部门名称,要求显示员工名和部门名
select e.ename,(select d.dname from dept d where e.deptno = d.deptno) as dname from emp e;

union

可以将查询结果相加

# 找出工作岗位是 salesman 和 manager 的员工
select e.ename,e.job from emp where job in('salesman','manager');

select e.ename,e.job from emp e where job = 'salesman'
union
select e.ename,e.job from emp e where job = 'manager';

limit

select ename,sal from emp order by sal desc limit 0,5; # 从0开始,取5条数据

表的创建

create table 表名 {
字段名1 数据类型,
字段名2 数据类型,
字段名3 数据类型,
};

数据类型

int    整数型(java的long)
bigint 长整型(java的long)
float 浮点型(java的float double
char 定长字符串(String)
varchar 可变长字符串 255(StringBuffer StringBuilder)
date 日期类型(java的java.sql.Date
BLOB 二进制大对象(流媒体) Binary Large OBject
CLOB 字符大对象(大文本) Charcter Large OBject

charvarchar如何选择

create table t_student (
no bigint,
name varchar(255),
sex char(1),
classno varchar(255),
birth char(10),
);

insert

# 插入一条
insert into t_student(no,name,sex,classno,birth) value (110,'zs','1','2010A','1995-12-12');
# 插入2条数据
insert into t_student(no,name,sex,classno,birth) value (110,'zs','1','2010A','1995-12-12'),(220,'zs1','2','2010B','1992-12-31');
# 根据字段顺序插入
insert into t_student(name,sex,classno,birth,no) value ('zs','1','2010A','1995-12-12',220);
# 省略表字段,必须按照表的字段来
insert into t_student value (440,'zs','1','2010A','1995-12-12');

# 删除表
drop table if exists t_student;
# 再次创建表
create table t_student (
no bigint,
name varchar(255),
sex char(1) default '1',
classno varchar(255),
birth char(10),
);

# 复制一张表
create table emp1 as select emp.ename,emp.edeptno from emp;

update

update 表名 set 字段1=1,字段2=2,字段3=3,字段4=4,... where 条件;

update t_student set name='ls' where no = 330;

delete

delete from 表名 where 条件;
detele from t_student where no = 220;
truncate table 表名;

修改表结构(DDL)

约束(constraint)

唯一性约束:unique 列级约束、表级约束(unique(id,name))。

非空约束:not null

主键约束:primary key

外键约束:foreign key 必须先创建父表,再创建子表

检查约束:check(Oracle)

drop table if exists t_user;
create table t_user(
id int primary key auto_increment,
username varchar(255),
email varchar(255)
);
insert into t_user(id,username,email) value(1,'zs','zs@123.com');
insert into t_user(username,email) value('zs','zs@123.com');

# 外键约束
drop table if exists t_class;
drop table if exists t_student;
create table t_class(
cno int,
cname varchar(255),
primary key(cno)
);

create table t_student(
sno int,
sname varchar(255),
classno int,
foreign key(classno) references t_class(cno)
);

存储引擎

show create table emp; 查看建表语句

engine=InnoDB DEFAULT CHARTSET=utf8;

存储引擎:只在 MySQL 存在, Oracle 中没有特殊名字。

查看当前 MySQL 支持的存储引擎:show engines \G

MyISAM: 不支持事务 InnoDB: 支持事务,行级锁,支持外键、安全 MEMORY: 不支持事务、数据容易丢失, 数据和索引存在内存当中

事务

事务的特性:

  • 原子性(Atomicity): 整个事务中的所有操作,必须作为一个单元全部完成(或全部取消)。
  • 一致性(Consistency): 在事务开始之前与结束之后,数据库都保持一致状态。
  • 隔离性(Isolation): 一个事务不会影响其他事务的运行。
  • 持久性(Durability): 在事务完成以后,该事务对数据库所作的更改将持久地保存在数据库之中,并不会被回滚 。

事务的隔离:

第一级别:读未提交(read uncommitted)

  • 对方事务还没有提交,我们当前事务可以读取到对方未提交的数据
  • 读未提交存在脏读(Dirty Read)现象:表是读到了脏的数据

第二级别:读已提交(read committed)

  • 对方事务提交之后的数据我方才可以读取到
  • 读已提交存在的问题:不可重复读

第三级别:可重复读(repeatable read)

  • 这种隔离级别解决了不可重复读的问题
  • 这种隔离存在的问题:读到的数据都是幻象

第四级别:序列化读/串行化读

  • 解决了所有的问题
  • 效率低,需要事务排队

Oracle 数据库默认的隔离级别是:读已提交。

MySQL 数据库默认的隔离级别是:可重复读。

演示事务

MySQL 的事务是关闭动提交机制:start transaction

34 个练习题

# 1. 取得每个部门最高薪水的人员名称
# 获取每个部门的最高薪水
select deptno,max(sal) from emp group by deptno;
# 将以上结果当做临时表 t,t 表和 emp e 表连接: t.deptno = e.deptno and t.maxsal = e.sal

select
e.ename,t.*
from
(select deptno,max(sal) as maxsal from emp group by deptno) t
join
emp e
on
t.deptno = e.deptno and t.maxsal = e.sal;