一.数据库基础知识
文章目录
- 1.数据库相关概念
- 2.MySQL数据库
- 1.DDL : 数据定义语言,定义数据库对象(数据库,表,字段)
- 2. DML : 数据操纵语言,用来对数据表中的数据进行增删改
- 3.DQL : 数据查询语言,查询数据库中表的记录
- 4. DCL : 数据控制语言,创建数据库用户,控制数据库的访问权限
- 3.函数
- 3.1字符串函数
- 3.2数值函数
- 3.3日期函数
- 3.4流程函数
- 4.约束
- 4.1概念
- 4.2 约束演示
- 4.3外键约束
- 5.多表查询
- 5.1多表关系
- 5.2概述
- 6.事务
- 6.1 事务操作
- 6.2事务四大特性(面试题)
- 6.3并发事务问题
- 6.4 事务的隔离级别
1.数据库相关概念
- 数据库(DataBase)
- 存储数据的仓库,数据是进行有组织的存储
- 数据库管理系统(DataBase Management System)
- 操纵和管理数据库的大型软件
- SQL(Structured Query Language)
- 操作关系型系统数据库的编程语言,是一套标准
2.MySQL数据库
-
启动与停止
- 方法一:windows+r -----输入services.msc-------找到以M开始的文件MySQL80
- 方法二:以管理员身份运行,在命令行输入:net start mysql80(启动) ----net stop mysql80(停止)
-
客户端连接
- 方法一:MySQL提供的客户端命令行工具(菜单里面找到MySQL文件夹)
- MySQL 8.0 Command Line Client
- 方法二:系统自带的命令行工具执行指令()
- 以管理员身份运行,在命令行输入:mysql -u root -p
- 前提配置环境变量
- 在path里添加MySQL的路径(
C:\Program Files\MySQL\MySQL Server 8.0\bin
)
- 在path里添加MySQL的路径(
- 方法一:MySQL提供的客户端命令行工具(菜单里面找到MySQL文件夹)
-
数据模型
- 关系型数据库:
- 概念:建立在关系模型基础上,由多张相互连接的二维表组成的数据库
- 特点:
- 使用表存储数据,格式统一,便于维护
- 使用SQL语言操作,标准统一,使用方便
- 一个数据库可以创建多个表,基于表进行数据存储的数据库被称为关系型数据库
- 关系型数据库:
-
SQL
-
通用语法:
- SQL语句可以单行或多行书写,以分号结尾
- SQL语句可以使用空格或缩进来增强语句的可读性
- MySQL数据库的SQL语句不区分大小写,关键字建议使用大写
- 单行注释:==–注释内容/#==注释内容
- 多行注释:/* 注释内容*/
-
分类:
-
1.DDL : 数据定义语言,定义数据库对象(数据库,表,字段)
-
- 数据库操作(括号里面的可写可不写,视情况而定)
- 查询所有数据库:SHOW DATABASES;
- 查询当前数据库:SELECT DATABASE();
- 创建:CREATE DATEBASE [IF NOT EXISTS] 数据库名 [DEFULT CHARSET 字符集] [COLLATE 排序规则];
- 删除:DROP DATABASE [IF EXISTS] 数据库名;
- 使用:USE 数据库名;
- 表操作:(前提使用数据库,进入数据库)
- 查询当前数据库所有表:SHOW TABLES;
- 查询表结构:DESC 表名;
- 查询指定表的建表语句:SHOW CREATE TABLE 表名;
- 创建:
注意
:[…]里为可选参数,最后一个字段后面没有逗号
CREATE TABLE 表名( 字段1 字段1类型 [COMMENT 字段1注释], 字段2 字段2类型 [COMMENT 字段2注释], .............. 字段n 字段n类型 [COMMENT 字段n注释] )[COMMENT 表注释];
-
- 表操作- 数据类型:数值类型,字符串类型,日期时间类型
- 数值类型
- eg:age TINYINT UNSIGNED // score double (4,1)
- 字符串类型:
- eg:char(10) // varchar(10)
- 区别:char性能高;varchar性能低.因为varchar要计算所处的空间
- 日期时间类型:
- eg:birthday date
- 表操作-修改:
- 添加字段:ALTER TABLE 表名 ADD 字段名 类型(长度) [COMMENT 注释] [约束];
- 修改数据类型:ALTER TABLE 表名 MODIFY 字段名 新数据类型(长度);
- 修改字段名和字段类型:ALTER TABLE 表名 CHANGE 旧字段名 新字段名 类型(长度) [COMMENT 注释] [约束];
- 删除:ALTER TABLE 表名 DROP 字段名;
- 修改表名:ALTER TABLE 表名 RENAME TO 新表名;
- 删除表:DROP TABLE [IF EXISTS] 表名;
- 删除指定表:TRUNCATE TABLE 表名;
- 表操作- 数据类型:数值类型,字符串类型,日期时间类型
- 数据库操作(括号里面的可写可不写,视情况而定)
2. DML : 数据操纵语言,用来对数据表中的数据进行增删改
-
-
添加数据:INSERT
-
给指定字段添加数据
INSERT INTO 表名(字段名1,字段名2,…) VALUES (值1,值2…);
-
给全部字段添加数据
INSERT INTO 表名 VALUES(值1,值2…);
-
批量添加数据
INSERT INTO 表名 (字段名1,字段名2,…) VALUES (值1,值2…);
INSERT INTO 表名(值1,值2,…),(值1,值2,…),(值1,值2,…);
-
注意:
- 插入数据时,指定的字段顺序需要与值的顺序一一对应
- 字符串和日期型数据应该包含在引号内
- 插入数据的大小,应该在字段的规定范围内
-
修改数据:UPDATE
- UPDATE 表名 SET 字段名1 = 值1,字段名2=值2,…[WHERE 条件];
- 注意:
- 修改语句的条件可有可无,如果没有条件则会修改整张表的所有数据
-
删除数据:DELETE
- DELETE FROM 表名 [WHERE 条件];
- 注意:
- 语句的条件可有可无,如果没有条件则会修改整张表的所有数据
- delete语句不能删除某一字段的值(可以使用UPDATE)
-
-
3.DQL : 数据查询语言,查询数据库中表的记录
-
基本查询
- 查询多个字段:SELECT 字段1,字段2,字段3… FROM 表名; SELECT * FROM 表名;
- 设置别名:SELECT 字段1[AS 别名1],字段2[AS别名2]…FROM 表名;
- 去除重复记录:SELECT DISTINCT 字段列表 FROM 表名;
- 条件查询
- 语法:SELECT 字段列表 FROM 表名 WHERE 条件列表;
- 条件:
- 查询多个字段:SELECT 字段1,字段2,字段3… FROM 表名; SELECT * FROM 表名;
in-------------------------------------------------
查询年龄等于18或20或40的员工信息
select * from 表名 where age in(18,20,40)
like----------------------------------------------------
查询名字为两个字符的员工信息
select * from 表名 name like '_';
查询身份证号最后一位是x的员工信息
select * from 表名 where idcard like '%X';
select * from 表名 where idcard like '_________________X';(17个下划线)
- 聚合函数(所有null值不参加运算)
- 将一列数据作为一个整体,进行纵向计算
- 常见聚合函数:
- count:统计数量
- max:最大值
- min:最小值
- avg:平均值
- sum:求和
- 语法:SELECT 聚合函数(字段列表) FROM 表名;
count-------------------------------
统计该企业员工数量(*表示全部)
select count(*) from 表名;
3. 分组查询
- 语法:SELECT 字段列表 FROM 表名 [WHERE 条件] GROUP BY 分组字段名 [HAVING 分组过滤后条件]
- where 与 having区别:
- 执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;having是分组后进行过滤
- 判断条件不同:where不能对聚合函数进行判断,而having可以
根据性别分组,统计女性员工和男性员工的数量
select gender,count(*) from 表名 group by gender;
根据性别分组,统计男性员工和女性员工的平均年龄
select gender,avg(age) from 表名 group by gender;
查询年龄小于45的员工(分组前),并根据工作地址分组,获取员工数量大于等于3的工作地址(分组后)
select workaddress,count(*) from 表名
where age<45 group by workaddress having count(*)>=3;
- 注意:
- 执行顺序:where > 聚合函数 > having
- 分组之后,查询的字段一般为聚合函数和分组字段,查询其他字段无任何意义
4. 排序查询
- 语法:select 字段列表 FROM 表名 ORDER BY 字段1 排序方式1,字段2 排序方式2;(支持多字段排序)
- 排序方式:
- ASC:升序(默认)
- DESC:降序
- 注意:如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序
根据年龄对公司员工进行升序排序,年龄相同,再按照入职时间进行降序排序
select * from 表名 order by age asc,entrydate desc;
- 分页查询
- 语法:SELECT 字段列表 FROM 表名 LIMIT 起始索引,查询记录数;
- 注意:
- 起始索引从0开始,起始索引=(查询页码-1)*每页记录数
- 分页查询是数据库的方言,不同的数据库有不同的实现,MySQL是LIMT
- 如果查询的是第一页数据,起始索引可以省略,直接简写为limit10;
查询第一页员工数据,每页展示10条记录
select * from 表名 limit 0,10;
select * from 表名 limit 10;
查询第二页员工数据,每页展示10条记录
select * from 表名 limit 10,10;
4. DCL : 数据控制语言,创建数据库用户,控制数据库的访问权限
- 用户管理
- 查询用户:USE mysql;SELECT * FROM user
- 创建用户:CREATE USER ‘用户名’@主机名’IDENTIFIED BY’ 密码
- 修改用户密码:ALTER USER ‘用户名’@‘主机名’ IDENTIFIED WITH mysql_native_password BY ‘新密码’
- 删除用户:DEOP USER ‘用户名’@‘主机名’
- 注意:主机名可以使用%通配,表示任意主机;这类语言开发人员操作比较少,主要是DBA使用
创建用户itcast ,只能在当前主机localhost访问,密码123456;
create user 'itcast'@'localhost' identified by 123456;
创建用户heima,可以在任意主机上访问数据库,密码123456;
create heima 'itcast'@'%'identified by 123456;
修改用户heima的访问密码为1234;
alter user 'heima'@'localhost'identified with mysql_native_password by '1234';
删除itcast@localhost用户
drop user 'itcast'@'localhost'
- 权限控制:
- 查询权限:== SHOW GRANTS FOR ‘用户名’@‘主机名’;==
- 授予权限:GRANT 权限列表 ON 数据库名.表名 TO ‘用户名’@‘主机名’;
- 撤销权限:REMOVE 权限列表 ON 数据库名.表名 FROM ‘用户名’@‘主机名’;
- 注意:多个权限之间,使用逗号分隔;授权时,数据库名和表名可以使用*进行通配,代表所有
1.查询
show grant for 'heima'@'%';
2.授予
grant all on itcast.* to 'heima'@'%';
3.撤销
remove all on itcast.* from 'heima'@'%';
3.函数
- 函数:
- 指一段可以被直接被另一端程序调用的程序或代码
3.1字符串函数
1.连接
select concat('Hello','world');
2.小写
select lower('Hello');
3.大写
select upper('Hello');
4.左填充
select lpad('01',5,'-');//(本身字符串,总的字符串长度,添加内容)
5.右填充
select rpad('01',5,'-')
6.去掉头部尾部的空格
select trim(' hello world ');
7.字符串截取
select substring('HelloWorld',1,5);//(截取的字符串,开始位置,个数)
练习:由于业务变更,企业员工的工号,统一为五位数,目前不足五位数的全部在前面补0.比如:1号员工的工号应该为00001.
update 表名 set (更新字段)workno = lpad(workno,5,'0');
3.2数值函数
1.向上取整
select ceil(1.2);
2.向下取整
select floor(1,3);
3.返回x/y的模
select mod(3,4);//3%4
4.返回随机数
select rand();//0-1之间
5.四舍五入
select round(1.234,2);//(数,保留小数位)
练习:通过数据库的函数,生成一个六位数的随机验证码
select rpad(round(rand()*1000000,0),6,'0');
3.3日期函数
1.返回当前日期
select curdate();
2.返回当前时间
select curtime();
3.返回当前日期和时间
select now();
4.获取指定date的年份
select YEAR(now());
5.获取指定date的月份
select MONTH(now());
6.获取指定date的日期
select DAY(now());
7.返回一个日期/时间值加上一个时间间隔expr后的时间值
select date_add(now(),INTERVAL 70 DAY)//(所设置时间,固定的,时间间隔,单位)
8.返回起始时间和结束时间之间的天数
select datediff('2025-1-11','2025-1-30');//前一个减后一个
练习:查询所有员工的入职天数,并根据入职天数倒序排序
select name,datediff(入职日期(),当前日期) as'别名' from 表名 order by 别名 desc;
3.4流程函数
1.if
select if (true,'ok','error');//(条件,如果为true返回的值,如果为false返回的值)
2.ifnull
select ifnull('ok','error');//(如果为null返回的值,如果不为null返回的值);
3.case when then else and
需求:查询emp表的员工姓名和工作地址(北京/上海--->一线城市,其他--->二线城市)
select
name,
(case workaddress when '北京' then '一线城市' when '上海' then '一线城市' else '二线城市' end)as '工作地址'
from emp;
练习:统计班级各个学员的成绩,展示规则如下:>=85,展示优秀;>=60,展示及格;否则,展示不及格
select
id ,
name,
(case when math>=85 then'优秀' when math >=60 then '及格' else '不及格' end)'数学',
(case when english>=85 then'优秀' when english >=60 then '及格' else '不及格' end)'英语',
(case when chinese>=85 then'优秀' when chinese >=60 then '及格' else '不及格' end)'语文'
from score ;
4.约束
4.1概念
:作用于表中字段上的规则,用于限制存储在表中的数据
- 目的:保证数据库中数据的正确,有效性和完整性
- 分类:
- 注意:约束是作用在表中字段上的,可以在创建表/修改表的时候添加约束
4.2 约束演示
use qq;
create table user1(
id int primary key auto_increment comment'主键',
name varchar(10) not null unique comment'姓名',
age int check(age>0 && age <=120) comment '年龄' ,
status char(1) default'1' comment'状态',
gender char(1)
) comment '用户名';
-- 插入数据
insert into user(name,age,status,gender) values('Tom1',12,'1','男'),('Tom2',13,'2','男');
4.3外键约束
- 外键用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性
- 语法:
- 添加外键:
- ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY(外键名称) REFENCES 主表(主表列名);
- CREATE TABLE 表名(字段名 数据类型 ,…[CONSTRAINT] [外键名称] FOREIGN KEY(外键字段名) REFERENCES 主表(主表列名));
- 删除外键:
- ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
- 删除/更新行为:
- ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY(外键名称) REFENCES 主表(主表字段名) ON UPDATE CASCADE ON DELETE CASCADE;
- ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY(外键名称) REFENCES 主表(主表字段名) ON UPDATE CASCADE ON DELETE CASCADE;
- 添加外键:
- 语法:
5.多表查询
5.1多表关系
- 一对多(多对一);多对多;一对一
- 一对多:
- 多对多:
create table s(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment'姓名',
no varchar(10) comment '学号'
) comment'学生表';
insert into s values(null,'1','001'),(null,'2','002'),(null,'3','003');
create table c(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment'课程名称'
)comment '课程表';
insert into c values(null,'c'),(null,'java'),(null,'c++');
create table s_c(
id int auto_increment comment'主键' primary key,
studentid int not null comment'学生ID',
courseid int not null comment'课程ID',
constraint fk_courseid foreign key(courseid) references course(id),
constraint fk_studentid foreign key(studentid) references student(id)
)comment '学生课程中间表';
insert into s_c values(null,1,1),(null,1,2),(null,1,3),(null,1,3),(null,2,1),(null,2,1),(null,3,1);
- 一对一:
5.2概述
- 概念:从多张表查询数据
- 笛卡尔积:笛卡尔积是指在数学中,两个集合A和B集合的所有组合情况(在多表查询时,需要消除无效的笛卡尔积)
- 多表查询分类:
- 内连接查询语法:(查询两张表交集的部分)
- 隐式内连接:SELECT 字段列表 FROM 表1,表2 WHERE 条件…;
- 显式内连接:==SELECT 字段列表 FROM 表1 [INNER] JOIN 表2 ON 连接条件…; ==
1.查询每一个员工的姓名,及相关的部门的名称(隐式内连接实现)
--表结构:emp,dept
--连接条件:emp.dept_id = dept.id
select emp.name,dept.name from emp,dept where emp.dept_id = dept.id;
select e.name,d.name from emp e ,dept d [起别名,可省略as] where e.dept_id = d.id;
//先执行from
2.查询每一个员工的姓名及关联发部门的名称(显示内连接实现)
--表结构:emp,dept
--连接条件:emp.dept_id = dept.id
select e.name,d.name from emp e inner join dept d on e.dept_id = d.id;
select e.name,d.name from emp e join dept d on e.dept_id = d.id;
//inner 可省略
-
- 外连接查询语法:
- 左外连接:SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 条件…;
- 相当于查询表1(左表)的所有数据 包含 表1和表2交集部分的数据
- 右外连接:SELECT 字段列表 FROM 表1 RIGHT [OUTER] JOIN 表2 ON 条件…;
- 相当于查询表2(右表)的所有数据 包含 表1和表2交集部分的数据
1.查询emp表中的所有数据和对应的部门信息(左外连接)
--表结构:emp,dept
--连接条件:emp.dept_id = dept.id
select e.*,d.name from emp e left outer join dept d on e.dept_id = d.id;
select e.*,d.name from emp e left join dept d on e.dept_id = d.id;
2.查询dept表中的所有数据和对应的员工信息(右外连接)
--表结构:emp,dept
--连接条件:emp.dept_id = dept.id
select d.*,e.* from emp e right outer join dept d on e.dept_id = d.id;
//左外
select d.*,e.* from dept d left outer join emp e on e.dept_id = d.id;
-
- 自连接:
- 语法:SELECT 字段列表 FROM 表A 别名A JOIN 表A 别名B ON 条件…;
- 自连接查询,可以是内连接查询,也可以是外连接查询
- 自连接:
1.查询员工及其所属领导的名字
--表结构:emp a,emp b
select a.name , b.name from emp a,emp b where a.managerid = b.id;
2.查询所有员工emp 及其领导的名字 emp ,如果员工没有领导,也需要查出来
select a.name '员工',b.name'领导' from emp a left join emp b on a.managerid=b.id;
-
- 联合查询:(union ; union all)
- 就是把多次查询的结果合并起来,形成一个新的查询结果集
- 语法: SELECT 字段列表 FROM 表A… UNION[ALL] SELECT 字段列表 FROM 表B…;
- 注意:
- 对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致
- union all会将全部的数据直接合并在一起,union会对合并的数据去重
- 联合查询:(union ; union all)
将薪资低于5000的员工和年龄大于50岁的员工全部查询出来
select * from emp where salary<5000
union all
select * from emp where age>50;
//去重(删除掉all)
select * from emp where salary<5000
union
select * from emp where age>50;
-
- 子查询:
- 概念:SQL语句中嵌套select语句,称为嵌套查询,又称子查询
- 语法:SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
- 注意:子查询外部的语句可以是INSERT/UPDATE/DELETE/SELECT的任意一个
- 根据查询
结果不同
,分为:-
标量子查询(子查询结果为单个值(数字,字符串,日期等))
- 常用操作符:
= <> > >= < <=
- 常用操作符:
-
列子查询(子查询结果为一列(可以是多行))
- 常用操作符:
IN ,NOT IN, ANY,SOME,ALL
- 常用操作符:
-
行子查询(子查询结果为一行( 可以是多列))
- 常用操作符:
=, <>,IN,NOT IN
- 常用操作符:
-
表子查询(子查询结果为多行多列)
- 常用操作符:
IN
- 常用操作符:
-
- 根据子查询
位置
,分为:WHERE之后,FROM之后,SELECT之后
- 子查询:
1.标量子查询-------------------------------------------------------------------
1.1 查询"销售部"的所有员工信息
思路:查询"销售部"部门ID;根据销售部部门ID,查询员工信息.
select id from dept where name='销售部';
select * from dept where dept_id = 4;
总:select * from dept where dept_id = (select id from dept where name='销售部');
1.2 查询在"方东白"入职之后的员工信息;
思路:查询方东白的入职日期;根据方东白的入职日期,查询之后的员工
select entry_date from where name = '方东白';
select * from where entry_date > 2000-09-11;
select * from where entry_date > (select entry_date from where name = '方东白');
2.列子查询-------------------------------------------------------------------
2.1 查询"销售部"和"市场部"的所有员工信息
思路:查销售部,市场部的ID;根据部门ID,查询员工信息
select id from dept where name ='销售部' or name ='市场部';//2,4
select * from emp where dept_id in (2,4);
总:select * from emp where dept_id in (select id from dept where name ='销售部' or name ='市场部');
2.1 查询比财务部 所有人工资都高的员工信息
思路:查询财务部所有人的工资;比财务部所有人工资都高的员工信息
select id from dept where name ='财务部';//3
select salary from emp where dept_id=3;
总:select salary from emp where dept_id=(select id from emp where name ='财务部');
select * from emp where salary > all (select salary from emp where dept_id=(select id from emp where name ='财 务部'));
2.3 查询比研发部其中 任意一个人 工资高的员工信息
select salary from emp where name = (select id from dept where name = '市场部');
select * from emp where salary > any(select salary from emp where name = (select id from dept where name = '市场部'));
3.行子查询-------------------------------------------------------------------
3.1 查询与"张无忌"的薪资 及 直属领导相同的员工信息;
思路:查询"张无忌"的薪资及直属领导;据此查询相同的员工信息
select salary,manager_id from emp where name='张无忌';//1234,1
select * from emp where salary = 1234 and manager_id=1;//(普通写法 )
select * from emp where(salary,manager_id) = (1234,1);
select * from emp where(salary,manager_id) = (select salary,manager_id from emp where name='张无忌');//(行子查询)
4.表子查询-------------------------------------------------------------------
4.1 查询与"鹿杖客""宋远桥"的薪资 及 职位 相同的员工信息;
思路:查询"鹿杖客""宋远桥"的薪资及职位;据此查询相同的员工信息
select salary,job from emp where name='鹿杖客','宋远桥';//错误
select salary,job from emp where name='鹿杖客'or name='宋远桥';
select * from emp where (salary,job) in (select salary,job from emp where name='鹿杖客'or name='宋远桥');
4.2 查询入职日期是'2006-01-01' 之后的员工信息,及部门信息
思路:查询入职日期后的员工信息;再查询对应的部门信息
select * from emp where entrydate > '2006-01-01';
select e.*,d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id;
- 练习:
1.
--表结构:emp , dept
--连接条件:emp.dept_id = dept_id;(外键字段)
select e.name ,e.age ,e.job,d.name from emp e , dept d where e.dept_id = d.id;(隐式内连接)
2.
--表结构:emp , dept
--连接条件:emp.dept_id = dept_id;
select e.name ,e.age ,e.job,d.name from emp e inner join dept d on e.dept_id = d.id where e.age<30;(显示内连接)
3.
select distinct d.id,d.name from emp e , dept d where e.dept_id = d.id;(内连接)
4.
--表结构:emp , dept
--连接条件:emp.dept_id = dept_id;
select e.*,e.name from emp e left join dept d on e.dept_id = d.id where e.age>40;
5.
--表结构:emp , salarygrade
--连接条件:emp.salary >= salary.losal and emp.salary <=salarygrade.hisal
select e.* ,s.grade from emp e ,salarygrade s where e.salary >=s.losal and e.salary <=s.hisal;
select e.* ,s.grade from emp e ,salarygrade s where e.salary between s.losal and s.hisal;
6.
--表结构:emp , salarygrade,dept
--连接条件:emp.salary between salarygrade.losal and salarygrade.hisal,emp.dept_id = dept_id;
--查询条件:dept.name = '研发部'
select e.*,s.grade from emp e,dept d,salarygrade s where e.dept_id = d.id and (e.salary between salarygrade.losal and s.hisal) and d.name='研发部';
7.
--表结构:emp , dept
--连接条件:emp.dept_id = dept_id;
select avg(e.salary) from emp e,dept d where emp.dept_id = dept_id and d.name='研发部';
8.
思路:查询灭绝的薪资;查询比她高的员工信息
select salary from emp where name ='灭绝';
select * from emp where salary > (select salary from emp where name ='灭绝');
9.
select avg(salary) from emp;
select * from emp where salary >(select avg(salary) from emp);
10.
思路:查询指定部门的平均薪资;查询低于本部门平均薪资的员工信息
select avg(e1.salary) from emp e1 where e1.dept_id = 1;
select avg(e1.salary) from emp e2 where e1.dept_id = 2;
//select * from emp where salary < (select avg(e1.salary) from emp e2 where e1.dept_id = 2)
select * from emp e2 where salary < (select avg(e1.salary) from emp e2 where e1.dept_id =e2.dept_id )
11.
select id,name from dept;//查询所有部门的信息
select count(*) from emp where dept_id=1;//一号部门员工的人数
select d.id,d.name,(select count(*) from emp e where e.dept_id = d.id )'人数' from dept d;//select嵌套可以出现在select后
12.
--表结构:stu course stu_course
--连接条件: student.id = stu_course.stuid,course.id = stu_course.courseid;
select * from stu s,stu_course sc,course c where s.id = sc.stuid,c.id = sc.courseid;
6.事务
- 事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败
- 应用:银行转账业务
- 默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交业务
6.1 事务操作
- 查看/设置事务提交方式:
- SELECT @@ autocommit;
- ==SET @@ autocommit=0; ==
- 提交事务:COMMIT;
- 回滚事务:ROLLBACK;
- 开启事务:START TRANSACTION 或 BEGIN;
- 事务的控制方式:
- 1.关闭事务自动提交 ,commit提交,rollback回滚
- 2.指令START TRANSACTION 或 BEGIN;开启事务,如果事务成功执行commit,失败执行rollback
数据准备
create table account(
id int auto_increment primary key comment'主键ID',
name varchar(10) comment '姓名',
money int comment'余额'
)comment '账户表';
insert into account(id,name,money) VALUES (null,'张三',2000),(null,'李四',2000);
-------------------
select @@autocommit;//
set @@autocommit=0;//设置为手动提交
转账操作
1.查询张三余额
select * from account where name = '张三';
2.将张三的余额-1000
update account set money = money-1000 where name ='张三';
3.李四余额+1000
update account set money = money + 1000 where name = '李四';
//提交事务
commit;
//异常情况
1---------------------
//李四余额增加出错
//1.查询张三余额
select * from account where name = '张三';
//2.将张三的余额-1000
update account set money = money-1000 where name ='张三';
//3.李四余额+1000
//四余额增加出错
update account set money = money + 1000 where name = '李四';
//提交事务
commit;
//回滚事务//出现异常使用
rollback;
2----------------
start transaction;
//1.查询张三余额
select * from account where name = '张三';
//2.将张三的余额-1000
update account set money = money-1000 where name ='张三';
//3.李四余额+1000
//四余额增加出错
update account set money = money + 1000 where name = '李四';
//提交事务
commit;
//回滚事务//出现异常使用
rollback;
6.2事务四大特性(面试题)
- 原子性( Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败
- 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态
- 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行
- 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的
6.3并发事务问题
6.4 事务的隔离级别
-
隔离级别及出现的问题
-
考虑安全性与并发性
-
查看事务隔离级别:SELECT @@TRANSACTION_ISOLATION;
-
设置事务隔离级别:==SET [SESSION|GLOBAL] TRANSATIONS ISOLATION LEVEL [READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE]
== -
事务的隔离级别越高,数据越安全,但是性能越低,所以设置时需要去权衡选择哪个,一般默认就好
-
脏读:
- read uncommited
- read commited (解决脏读)
- read uncommited
-
-
不可重复读
- read commited
- (解决不可重复读)
- repeatable read
- read commited
-
幻读
-出现的错误- serializable(解决幻读在内的所有问题,但是性能最差)