MYSQL基础速成,没有一句废话
目录
分组查询
- 根据性别分组
select sex ,count(*) 人数 from stu group by sex;
- 根据性别分组,统计男女员工的平均年龄
select sex,avg(age) 平均年龄 from stu group by sex;
- where 与 having 的区别
- where是在分组之前进行过滤,不满足where条件,不参与分组
- having是在分组之后进行过滤
- where不能对聚合函数进行判断
- having可以对聚合函数进行判断
- where > 聚合函数 > having
select address, count(*) 人数
from stu
where age < 45
group by address
having 人数 >= 2;
建表语句(数据自己随便填,加深对表的熟悉程度)
emp表
create table emp
(
id int not null
primary key,
ename varchar(50) null,
job_id int null,
mar int null,
joindata date null,
salary decimal(7, 2) null,
bonus decimal(7, 2) null,
dept_id int null,
constraint fk_emp_dept
foreign key (dept_id) references dept (id),
constraint fk_emp_job
foreign key (job_id) references job (id)
);
-- id 编号
-- ename 姓名
-- job_id 职业编号
-- mar 领导编号
-- joindat 入职日期
-- salary 薪水
-- bonus 奖金
-- dept_id 部门编号
dept表
create table dept
(
id int not null
primary key,
dname varchar(50) null,
loc varchar(50) null
);
-- id 部门编号
-- dname 部门名称
-- loc 部门地址
job表
create table job
(
id int not null
primary key,
jname varchar(20) null,
description varchar(50) null
);
-- id 工作编号
-- jname 职务
-- description 职务描述
salarygrade表(暂时用不到)
create table salarygrade
(
grade int not null
primary key,
losalary int null,
hisalary int null
);
排序查询
select * from emp order by salary ;
select * from emp order by salary desc ;
select * from emp order by salary ,id desc ;
-
默认为升序
-
第三行先按salary查询,当salary相同时,再按id升序
分页查询
- 查询第一页数据,每页显示五个
- 第一页的索引默认为0
select * from emp limit 0,5;
select * from emp limit 5;
- 查询第二页数据,每页显示五个
select * from emp limit 5,4;
用户管理
- 查看数据库的用户(在mysql的user表中可以看到)
- 创建用户 (不要在@处多打空格)
create user 'zjw'@'localhost' identified by '123456';
-- 刷新权限
flush privileges;
- 任意主机可以访问
create user 'zjw'@'%' identified by '123456';
-- 刷新权限
flush privileges;
- 修改用户密码
alter user 'zjw'@'localhost' identified with mysql_native_password by '1234';
- 删除用户
drop user 'zjw'@'localhost';
权限控制
- 查询用户权限
show grants for 'zjw'@'localhost';
- 授权
grant all on brand.* to 'zjw'@'localhost';
- 回收权限
revoke all on brand.* from 'zjw'@'localhost';
字符串函数
- 字符串拼接
select concat('hello',' MYSQL');
- 变小写
select lower('MYSQl');
- 变大写
select upper('hello');
- 填充
-- 左填充
select lpad('pad', 8, '-');
-- 右填充
select rpad('pad', 8, '-');
- 去除开头和结尾的空格
select trim(' hello mysql ');
- 截取字符串
select substring('hello mysql',1,5);
数值函数
- 向上取整
select ceil(1.1);
- 向下取整
select floor(1.9);
- 求模取余
select mod(6,4);
- 随机数
select rand();
- 限制小数位数
select round(3.156, 2);
生成一个六位的验证码
- 方法一
-- 返回小于一的正数 例如:0.041271461212329066
select rand();
-- 小数点前有 5位(十分位为 0的时候)或者 6位 例如:799453.843198208
select rand() * 1000000;
-- 保留一位小数
select round(rand() * 1000000, 0);
-- 不足六位的右填充为六位(左右填充都可以)
select rpad(round(rand() * 1000000, 0), 6, '0');
- 方法二
-- 返回小于一的正数 例如:0.041271461212329066
select rand();
-- 小数点后面保留 6位 例如:0.156836
select round(rand(), 6);
-- 放大1000000倍
select round(rand(), 6) * 1000000;
日期函数
- 2022-03-12 (效果)
select curdate();
- 15:46:57 (效果)
select curtime();
- 2022-03-12 15:47:09 (效果)
select now();
- 12 (效果)
select day(curtime());
- 3 (效果)
select month(curtime());
- 2022 (效果)
select year(curtime());
- 在当前时间上添加指定间隔
select date_add(curtime(), interval 70 day);
-- 与当前时间间隔70天
select date_add(curtime(), interval 70 month);
-- 与当前时间间隔70个月
select date_add(curtime(), interval 70 year);
-- 与当前时间间隔70年
- 返回相差的天数(6890)
select datediff('2021-10-12', '2002-12-01');
-- 6890
- 根据入职日期进行排序
select ename, datediff(curdate(), joindata) as entrydate
from emp
order by entrydate desc;
流程控制函数
- IF (类似Java中的 ?:表达式)
select if(false, 'ok', 'error');
select if(true, 'ok', 'error');
- IFNULL(expr1,expr2)
- 如果 expr1 不为 NULL,则 IFNULL() 返回 expr1;否则返回 expr2。 IFNULL() 返回一个数字或字符串值,具体取决于使用它的上下文
-- expr1不为空,返回 '不是null'
select ifnull('不是null', 'Default');
-- expr1不为空,返回 ''(就是空白)
select ifnull('', 'Default');
-- expr1为空,返回 expr2
select ifnull(null, 'Default');
- case when then else end ( 类似Switch-case )
select ename,
(case job_id
when 1 then '高级员工'
when 2 then '中级员工'
when 3 then '普通员工'
else '实习生' end) as '等级'
from emp;
-- 注意不要把end漏掉
外键约束
- 级联
alter table emp
add constraint fk_emp_dept
foreign key (dept_id) references dept (id) on UPDATE cascade on DELETE cascade;
- 设置为空
alter table emp
add constraint fk_emp_dept
foreign key (dept_id) references dept (id) on UPDATE set null on DELETE set null ;
多表查询
- 隐式内连接
select *
from emp,
dept
where emp.dept_id = dept.id;
- 显示内连接
select ename, dept_id
from emp e
inner join dept d on e.dept_id = d.id
- 左外链接 (out关键字可以省略 ,会完全包含左表的数据)
select e.*, d.dname
from emp e
left join dept d on d.id = e.dept_id;
- 右外连接(会完全包含右表的数据,左表不含的会被设置为null)
select e.*, d.*
from emp e
right outer join dept d on d.id = e.dept_id;
- 自连接 (必须起别名)
查询员工对应的领导
select a.ename, b.ename
from emp a,
emp b
where a.mar = b.id;
联合查询
- 就是把两次的查询结果简单的拼接在一起
select * from emp where salary>10000
union all
select * from emp where bonus>5000;
- 把两次的查询结果简单的拼接在一起 ,但是会去重
select * from emp where salary>10000
union
select * from emp where bonus>5000;
- 注意: 对于联合查询的多张表的列数必须保持一致,字段列表也要保持一致
嵌套查询
- 标量子查询
- 查询在教研部的员工信息
select *
from emp
where dept_id =
(select id
from dept
where dname = '教研部');
- 查询在李逵之后入职的员工
select *
from emp
where joindata > (select joindata
from emp
where ename = '李逵');
-
列子查询(单列可多行)
-
查询在销售部或者财务部的员工信息
select *
from emp
where dept_id in (select id
from dept
where dname = '销售部'
or dname = '财务部');
- 查询工资比所有销售部员工工资高的人的姓名
select ename
from emp
where salary > all (select salary
from emp
where dept_id = (select id
from dept
where dname = '销售部'));
- 查询工资比任意一个销售部员工工资高的人的姓名
select ename
from emp
where salary > any (select salary
from emp
where dept_id = (select id
from dept
where dname = '销售部'));
- 行子查询(单行多列)
- 查询和关羽工资和直属领导相同的员工
select *
from emp
where (salary, mar) = (select salary, mar
from emp
where ename = '关羽'
);
- 表子查询
- 查询与关羽和宋江工资和直属领导相同的员工
select *
from emp
where (salary, mar) in (select salary, mar
from emp
where ename = '关羽'
or ename = '宋江'
);
- 查询在 2001-12-03 之后入职的员工信息和部门信息
select e.*, d.*
from (select *
from emp
where joindata > '2001-12-03'
) e
left join dept d on e.dept_id = d.id;
事务
- 建表语句
- account表(数据自己随便填,加深对表的熟悉程度)
create table account
(
id int auto_increment
primary key,
name varchar(10) null,
money double(10, 2) null
);
- 经典转账操作
-- 查询张三账户余额
select *
from account
where name = '张三';
-- 张三减去1000元
update account
set money=money - 1000
where name = '张三';
-- 李四加上1000元
update account
set money=money + 1000
where name = '李四';
- 上面的转账方式容易出错,可以采用事务的方式
- 方式一
-- 默认事务是自动提交的
select @@autocommit;
-- 把事务的提交方式设置为手动提交
set @@autocommit = 0;
-- 查询张三账户余额
select *
from account
where name = '张三';
-- 张三减去1000元
update account
set money=money - 1000
where name = '张三';
-- 李四加上1000元
update account
set money=money + 1000
where name = '李四';
-- 提交事务
commit;
-- 回滚事务,出现异常时执行
rollback;
- 方式二
-- 自动提交已经开启
set @@autocommit = 1;
-- 开启事务,只是限制本次操作为手动提交
start transaction;
-- 查询张三账户余额
select *
from account
where name = '张三';
-- 张三减去1000元
update account
set money=money - 1000
where name = '张三';
-- 李四加上1000元
update account
set money=money + 1000
where name = '李四';
-- 提交事务
commit;
-- 回滚事务,出现异常时执行
rollback;
事务的隔离级别
- 隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
read uncommitted | √ | √ | √ |
read committed | × | √ | √ |
repeatable read | × | × | √ |
serializable | × | × | × |
- 语句
-- 查看事务隔离级别,mysql默认为REPEATABLE-READ
select @@transaction_isolation;
-- 设置事务的隔离级别
set session transaction isolation level read committed;
- 注意
事务隔离级别越高,数据越安全,但是性能越低