【MySQL】基础部分——DDL,DML,DQL,DCL,函数,约束,多表查询,事务

个人学习记录,供以后回顾和复习

  • ubuntu下安装使用
  • 1.DDL,DML,DQL,DCL
    • DDL
      • 数据库
    • DML
    • DQL
      • 条件查询
      • 分组查询
      • 排序查询
      • 分页查询
    • DCL
      • 管理用户
      • 权限控制
  • 2.函数
    • 字符串函数
    • 数值函数
    • 日期函数
    • 流程函数
  • 3.约束
  • 4.多表查询
    • 多表关系
    • 内连接
    • 外连接
    • 自连接
    • 联合查询union
    • 子查询
      • 标量子查询
      • 列子查询
      • 行子查询
      • 表子查询
    • 案例学习
  • 5.事务
    • 事务操作
    • 事务四大特性
    • 并发事务问题
    • 事务隔离级别

ubuntu下安装使用

参考文章:传送
进入mysql用命令 mysq -u root -p(密码)
注意p和密码之间没有空格

1.DDL,DML,DQL,DCL

在这里插入图片描述

sql可以单行或者多行,以分号结尾,可以用空格和缩进来增强可读性,也不区分大小写 。
单行注释:-- 内容,或者# 内容
多行注释:/* 内容 */

DDL

数据库

show databases;
select database();
create database 数据库名;
create database [if not exists] 数据库名 [default charset 字符集] [collate 排序规则];#不存在某某数据库,就创建
drop database [if exists] 数据库名;
use 数据库名;

实操:
每一个sql语句都要写分号,不然系统默认还没结束只是转行
create database itheima default charset utf8mb4;
创建itheima数据库,默认是utf8mb4的字符集,尽量不用utf8,因为他只有3个字节。

show tables;#先用use
desc 表名;
show create table 表名;#查询指定标的建表语句
#表的创建
create table 表名{字段1 字段1类型{comment 字段1注释},字段2 字段2类型{comment 字段2注释},....字段n 字段n类型{comment 字段n注释}
}{comment 表注释};

创建表举例:
eg1在这里插入图片描述
eg2
在这里插入图片描述

表的修改以及删除:

alter table 表名 add 字段名 类型(长度) [comment 注释] [约束];#添加字段
alter table 表名 modify 字段名 新数据类型(长度);#修改数据类型
alter table  表名 change 旧字段名 新字段名 类型(长度) [comment 注释] [约束];#修改字
段名和字段类型
alter table 表名 drop 字段名 # 删除字段名
alter table  表名 rename(to) 新表名 # 修改表名,可以不加to也能修改
drop table [if exists] 表名;#删除表
truncate table 表名;#清空表
create table new_table_name select * from old_table_name; # 复制表结构及数据
#复制表结构到新表,不复制数据
create table new_table_name select * from old_table_name where 1 = 2;
#或
create table new_table_name like old_table_name;

操作:

#添加一行nickname到emp表中
alter table emp add nickname varchar(20) comment '昵称';
#修改nickname字段名以及他的类型
alter table emp change nickname username varchar(30) comment '用户名';
#删除字段
alter table emp drop username
#更改表名
alter tale emp rename to employee
#删除表
drop table if exists tb_user;
#清空表
truncate table employee;

DML

主要是对数据记录的增删改

1.给指定字段添加数据
insert into 表名(字段名1, 字段名2, ......) values (值1, 值2, ......);insert into employee(id, workno, name, gender, age, idcard, entrydate)
VALUES (1, '1', 'Itcast', '男', 10, '123412341234123412', '2022-09-18');
2.未指定字段名,则是给全部字段添加数据
insert into 表名 values(值1,值2,...);insert into employee values (2, '2', 'Itcast', '男', 10,
'123412348234123412', '2022-09-17');
3.批量添加
#不想一段一段来,一次性添加多段
insert into employee values (....), (.....).....;
#模仿2,后面跟着多段,用逗号分开

#修改id为1的数据,将name改为itheima
update employee set name = 'itheima' where id = 1;
#修改id为1的数据,将name改为小昭,gender改为女
update employee set name = '小昭',gender = '女'  where id = 1;
#所有员工入职日期改为2008-01-01
update employee set entrydate = '2008-01-01';

delete from 表名 where 条件delete from employee where gender = '女';
delete from employee;

DQL

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

基本查询:select,from
条件查询:where,having
聚合函数:count,max,min,avg,sum(null不会参与)
分组查询:group by
排序查询:order by
分页查询:limit

条件查询

关键字含义
>,>=,<,<=,=大于,大于等于,小于,小于等于,等于
<>,!=不等于
between…and在某个范围之内(中间最小、and后大值)
in(…)在in之后的列表中的值,多选一
like占位符,模糊匹配,_匹配单个字符,&匹配任意个
is null是null
and或&&并且
or或II或者
not或者!不是
select * from 'order'; # 关键字重名时使用
select * from emp where age in (15, 20, 70); # age = 15 or age = 20 or age = 70是一个意思
select * from emp where name like '__';#两个下划线
select * from emp where idcard like '%x';#身份证号最后一位是x的员工信息

分组查询

select 字段列表 from 表名 where 条件 group by 分组字段名 havin 分组后过滤条件
where不能对聚合函数进行判断,而having可以!

  1. 执行顺序:where > 聚合函数 > having
  2. 分组之后,查询的字段一般为聚合函数和分组字段,查询其他字段无任何意义。
#根据性别分组,统计男员工和女员工的数量
select gender,count(*) from emp group by gender
#根据性别分组,统计男性员工和女性员工的平均年龄
select gender,avg(age) from emp group by gender
#查询年龄小于45的员工,并根据工作地址分组,获取员工数量大于等于3的工作地址
select workaddress,count(*) from where age < 45 group by workaddress having count(*) >= 3;

排序查询

select 字段列表 from 表名 order by 字段1 排序方式1 字段2 排序方式2
支持多字段排序!
asc升序(默认),desc降序

#根据年龄对公司的员工进行升序排序
select * from emp order by age asc;
#根据年龄对公司的员工进行升序排序,年龄相同,再按照入职时间进行降序排序
select * from emp order by age asc,entrydate desc;

分页查询

select 字段列表 from 表名 limit 起始索引,查询记录数
起始索引从0开始,
起始索引=(查询页码-1)*每页显示记录数

#查询第1页的员工数据,每页展示10条
select * from emp limit 0,10;
#查询第2页的员工数据,每页展示10条记录
select * from emp limit 10,10;

案例练习

1.查询年龄为20,21,22,23岁的员工信息
select * from emp where gender = '女' and age in(20, 21, 22, 23);
2.查询性别为男,并且年龄在20-40岁以内的姓名为三个字的员工
select * from emp where gender = '男' and age between 20 and 40 and name like '___';
3.统计员工表中,年龄小于60的,男性员工和女性员工的人数
select gender, count(*) from emp where age < 60 group by gender
4.查询所有年龄小于等于35岁员工的姓名和年龄,并对查询结果按年龄升序排序,如果年龄相同按入职时间降序排序
select name, age from emp where age <= 35 order by age asc, entrydate desc;
5.查询所有性别为男,且年龄在20-40内的前5个员工信息,对查询结果按照年龄升序排序,年龄相同的按照入职时间降序排序
select * from emp where gender = ‘男’ and age between 20 and 40 order by age asc, entrydate desc limit 5;

DQL执行顺序:from->where->group by->select->order by->limit
所以在from中给表起了别名的话,在后序中可以直接使用别名

select name,age from emp e where age > 15 order by age asc;

DCL

用来管理数据库 用户、控制数据库访问权限

管理用户

1. 查询用户
use mysql;
select * from user;2. 创建用户
create user '用户名'@'主机名' identified by '密码';3. 修改用户密码
alter user '用户名'@'主机名' identified with mysql_native_password by '新密码';4. 删除用户
drop user '用户名'@'主机名';

具体操作:

# 创建用户itcast,只能够在当前主机localhost访问,密码123456
create user 'itcast'@'localhost' identified by '123456';
# 创建用户heima,可以在任意主机访问该数据库,密码123456
create user 'heima'@'%' identified by '123456';
# 修改用户heima的访问密码为1234
alter user 'heima'@'%' identified with mysql_native_password by '1234';
# 删除itcast@localhost用户
drop user 'itcast'@'localhost';

权限控制

在这里插入图片描述

1. 查询权限
show grants for '用户名'@'主机名';2. 授予权限
grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';3. 撤销权限
revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';

具体操作:

#查询权限
show grants for 'heima'@'%';
#授予权限
grant all on itcast.* to 'heima'@'%';
#撤销权限
revoke all on itcast.* from 'heima'@'%';

tips:
多个权限之间,使用逗号进行分隔
授权时,数据库名和表名可以使用*进行通配,代表所有

2.函数

字符串函数

在这里插入图片描述
演示:

select concat('Hello','MySQL');#HelloMySQL
select lower('Hello');#hello
select upper('Hello');#HELLO
select lpad('01',5,'-');#---01
select rpad('01',5,'-');#01---
select trim(' Hello MySQL ');#Hello MySQL
select substring('Hello MySQL',1,5)#Hello

操作:

#由于业务需求变更,企业员工的工号,统一为5位数,目前不足5位数的全部在前面补0
update emp from workno = lpad(workno,5,‘0’);

数值函数

在这里插入图片描述
演示:

select ceil(1.1)#2
select floor(1.9)#1
select mod(3,4)#3
select rand()#0~1之间的随机数
select round(2.345,2)#2.35

实操:

#根据数据库的函数,生成一个六位数的随机验证码
select lpad(round(rand() * 1000000,0),6,‘0’)
#0~1之间的数字小数点移6位
#保留0个小数
#lpad在不足的情况下前面补0

日期函数

在这里插入图片描述
演示:

select curdate();#本机获取当前日期
select curtime();#本机获取当前时间
select now();#年月日时分秒
select year(now())
select month(now())
select day(now())
select date_add(now(),interval 70 day) #当前时间往后推70天
select datediff('2021-12-01','2021-11-01')#30

实操:

#查询所有员工入职天数,并根据入职天数倒序排列
select name,datediff(curdate(),entrydate) as 'entrydays' from emp order by entrydays desc;

流程函数

在这里插入图片描述
演示:

select if(true,'OK','ERROR')#OK
select ifnull('OK','Default')#OK,' '也可以返回,只有null不返回

操作:

1.
# 查询emp表的员工姓名和工作地址(北京---->一线城市,其他---->二线城市)
select name, (case workaddress when '北京' then '一线城市' when '上海' then '一线城市' else '二线城市' end) as '工作地址'
from emp;2.
# 统计班级各个学员的成绩,展示的规则如下:
# >= 85展示优秀;>=60展示及格;否则展示不及格
selectid,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;

3.约束

在这里插入图片描述
演示:
根据需求,完成表结构的创建:
在这里插入图片描述

create table user(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 '性别'
} comment '用户表';-------------------------------插入数据
insert into user(name, age, status, gender) values('Tom1', 19, '1', '男'),('Tom2', 25, '0', '男');
insert into user(name, age, status, gender) values('Tom3', 19, '1', '男');

结果:
在这里插入图片描述
外键用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性。

1.添加外键
#方式1
create table 表名(字段名 数据类型,....[constraint] [外键名称] foreign key(外键字段名) references 主表(主表列名)
);
#方式2
alter table 表名 add constraint 外键名称 foreign key(外键字段名) references 主表(主表列名);2.删除外键
alter table emp drop foreign key fk_emp_dept_id;

外键的删除/更新行为:
在这里插入图片描述

#on update在更新时怎么操作,on delete在删除时怎么操作
alter table 表名 add constraint 外键名称 foreign key (外键字段) references 主表名(主表字段名) on update cascade on delete cascade;

4.多表查询

多表关系

一对多:部门和员工,一个员工属于一个部门,一个部门有多个员工;

  • 在多的一方建立外键,指向一的一方。

多对多:学生与课程,一个学生可以选择多门课,一门课可以被多个学生选择

  • 建立一张中间表,至少包含两个外键,分别关联两方主键
#中间表
create table student_course(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 '学生课程中间表';

结果:
在这里插入图片描述

一对一:用户对用户。多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率。

  • 在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的UNIQUE
# 有一个单表users
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) NOT NULL,email VARCHAR(100),phone VARCHAR(15),address VARCHAR(255),bio TEXT
);

users 存储了用户的基本信息(username,email)和详情信息(phone,address,bio),现在决定将这个表拆分成两个表:

  1. users_basic表,存储用户的基本信息。
  2. users_details表,存储用户的详细信息。
#创建基本信息表
CREATE TABLE users_basic (id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) NOT NULL,email VARCHAR(100)
);
#创建详细信息表
CREATE TABLE users_details (user_id INT PRIMARY KEY,phone VARCHAR(15),address VARCHAR(255),bio TEXT,FOREIGN KEY (user_id) REFERENCES users_basic(id)
);

users_details表中的user_id字段是外键,引用了users_basic表中的id字段,从而建立一对一的关系,每个用户在 users_basic 表和 users_details 表中只能有一条对应记录。

#进行多表查询
SELECT b.id, b.username, b.email, d.phone, d.address, d.bio
FROM users_basic b
LEFT JOIN users_details d 
ON b.id = d.user_id;

通过 LEFT JOIN,我们可以查询出 users_basic 和 users_details 表中的对应信息,这样实现了将单表拆分为多表后的数据获取。

内连接

查询的是两张表交集的数据:

  • 隐式内连接

select 字段列表 from 表1,表2 where 条件…

#查询每个员工的姓名,以及关联的部门的名称(隐式内连接实现)
#表结构 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 where e.dept_id = d.id;
  • 显示内连接

select 字段列表 from 表1 [inner] join 表2 on 连接条件

#查询每个员工的姓名,以及关联的部门的名称(隐式内连接实现)
#表结构 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;

外连接

  • 左外连接

查询左表的所有数据,包含表1和表2交集部分的数据
select 字段列表 from 表1 left [outer] join 表2 on 条件…

  • 右外连接

查询右表的所有数据,包含表1和表2交集部分的数据
select 字段列表 from 表1 right [outer] join 表2 on 条件…

外连接演示:

#查询emp表的所有数据,和对应部门信息(左外连接)
select e.*,d.name from emp e left outer join dept d on e.dept_id = d.id;#查询dept表的所有数据,和对应的员工信息(右外连接)
select d.*,e.* from emp e right outer join dept d on e.dept_id = d.id;

自连接

自连接查询语法:
select 字段列表 from 表A 别名A join 表A 别名B on 条件…
演示:

  1. 查询员工 及其 所属领导的名字

在这里插入图片描述
emp表中有id,name,managerid,其中managerid的id指的是领导的id,领导id对应的name就是领导的name

所以不要把这个表看做一个表,同一个表看做两个表,一个是员工表,一个是领导表,员工表的managerid对应的就是领导表的主键id

select a.name,b.name from emp a,emp b where a.managerid = b.id;

联合查询union

对于union查询,就是把多次查询的结果合并起来,形成一个新的查询结果集
语法:
select 字段列表 from 表A
union[all]
select 字段列表 from 表B

其中:对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致!union all 会将全部的数据直接合并在一起,union 会对合并后的数据去重。

# 将薪资低于5000的员工,和年龄大于50岁的员工全部查询出来
select * from emp where salary < 5000 
union all
select * from emp where age > 50

union 和 or 的区别:如果某一行同时满足 salary < 5000 和 age > 50,or 的话,它会返回一次;而union all合并多个查询的结果集,而不会去除重复的行。如果某一行满足两个条件,则会返回多次(因为 UNION ALL 不去重)。如果使用union也想去重的话,可以只写union,不写all

子查询

sql中嵌套select语句,称为嵌套查询,又称子查询。比如:在这里插入图片描述
子查询外部的语句可以是insert/update/delete/select的任何一个。

根据子查询的结果不同,分为:

  • 标量子查询,子查询结果为单个值
  • 列子查询,子查询结果为一列
  • 行子查询,子查询结果为一行
  • 表子查询,子查询结果为多行多列

标量子查询

返回的是单个值,最简单形式

查询销售部的所有员工信息:

a.首先要查销售部id
select id from dept where name = '销售部';#4
b.然后根据销售部部门id查询员工信息
select * from emp where dept_id = 4;a+b:
select * from emp where dept_id = (select id from dept where name = '销售部');

列子查询

返回的是一列,也可以是多行

查询销售部和市场部的所有员工信息

a. 查询销售部和市场部的id
select id from dept where name = '销售部' or name = '市场部';#2,4
b. 根据部门id,查询员工信息
select * from emp where dept_id in (2,4);a+b:
select * from emp where dept_id in (select id from dept where name = '销售部' or name = '市场部');

查询比财务部所有人工资都高的员工信息

a. 查询比财务部所有人工资都高的员工信息
select salary from emp where dept_id = (select id from dept where name = '财务部');
b. 比财务部所有人工资都高的员工信息
select * from emp where salary > all (select salary from emp where dept_id = (select id from dept where name = '财务部'));

比研发部其中任意一人工资高的员工信息

a. 查询研发部所有人工资
select salary from emp where dept_id = (select id from dept where name = '研发部');
b. 比研发部任意一人工资高的员工信息
select * from emp where salary > any(select salary from emp where dept_id = (select id from dept where name = '研发部'));

上面的any也可以换成some,效果一样

行子查询

可以是一行多列

查询与张无忌的薪资及直属领导相同的员工信息

a. 查询张无忌的薪资及其直属领导
select salary,managerid from emp where name = '张无忌';#12500,1
b. 查询与张无忌的薪资及直属领导相同的员工信息
select * from emp where salary = 12500 and managerid = 1;a+b:
select * from emp where (salary,managerid) = (select salary,managerid from emp where name = '张无忌')

表子查询

返回多行多列

查询与鹿杖客,宋远桥的职位和薪资相同的员工信息

a. 查询鹿杖客,宋远桥的职位和薪资
select job,salary from emp where name = '鹿杖客' or name = '宋远桥';
b. 查询鹿杖客,宋远桥的职位和薪资相同的员工信息
select * from emp (job,salary) in (select job,salary from emp where name = '鹿杖客' or name = '宋远桥');

查询入职日期是2006-01-01之后的员工信息,及其部门信息

a. 入职日期是2006-01-01之后的员工信息
select * from emp where entrydate > '2006-01-01';
b. 查询这部分员工,对应的部门信息
select * from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id;

案例学习

主要涉及emp表,dept表,还有一个salgrade表,
emp与dept的关系,以及salgrade表:
在这里插入图片描述
salgrade表是薪资等级表,里面有薪资等级grade字段,等级对应的最低薪资losal字段,等级对应的最高薪资hisal字段

  1. 查询员工的姓名,年龄,职位,部门信息

涉及到员工的部门,就会涉及到两个表的连接查询,这个地方涉及的是隐式内连接

select e.name,e.age,e.job,d.name from emp e,dept d where e.dept_id = d.id;
  1. 查询年龄小于30的员工姓名,年龄,职位,部门信息

显示内连接

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;
  1. 查询拥有员工的部门id,部门名称

去重!

select distinct d.id,d.name from emp e,dept d where e.dept_id = d.id;
  1. 查询所有年龄大于40岁的员工,及其归属的部门名称;如果员工没有分配部门,也需要展示出来
select * from emp e left join dept d on e.dept_id = d.id where e.age > 40;
  1. 查询所有员工的工作等级

emp与salgrade之间没有外键关联,但emp中有salary,从salgrade中通过hisal和losal推测

select e.*,s.grade from emp e,salgrade s where e.salary between s.losal and s.hisal;
  1. 查询研发部所有员工的信息以及工资等级

涉及了3张表emp,salgrade,dept
连接条件:emp.salary between salgrade.losal and salgrade.hisal,emp.dept_id = dept.id
查询条件:dept.name = ‘研发部’

select e.*,s.grade from emp e,dept d,salgrade s where e.dept_id = d.id and (e.salary between s.losal and s.hisal) and (d.name = '研发部');
  1. 查询研发部员工的平均工资

涉及到2张表

select avg(e.salary) from emp e,dept d where e.dept_id = d.id and d.name = '研发部';
  1. 查询工作比“灭绝”高的员工信息
select * from emp where salary > (select salary from emp where name = '灭绝');
  1. 查询比平均薪资高的员工信息
select * from emp where salary > (select avg(salary) from emp);
  1. 查询低于本部门平均工资的员工信息

查询指定部门的平均薪资:select avg(e1.salary) from emp e1 where e1.dept_id = 1;
查询本部门:一张表变成两张就行,当前部门的平均工资用e1来计算,查询的员工用e2表

select * from emp e2 where e2.salary < (select avg(e1.salary) from emp e1 where e1.dept_id = e2.dept_id);
  1. 查询所有的部门信息,并统计部门的员工人数

统计指定部门的员工数量: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 d.id,d.name,(select count(*) from emp e where e.dept_id = d.id) '人数' from dept d;
  1. 查询所有学生的选课情况,展示出学生名称,学号,课程名称
    在这里插入图片描述
    涉及表:student,course,student_course
    连接条件:student.id = student_course.studentid,course.id = student_course.courseid
select s.name,s.no,c.name from student s,student_course sc,course c where s.id = sc.studentid and sc.courseid = c.id;

5.事务

事务是一组操作的集合,它是一个不可分割的工作单位,事物会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。

事务操作

转账操作(张三给李四转账1000)

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 = '李四';

123都是事物,是自动执行的,如果中间有异常,就会失败,所以需要考虑改变事物的方式:

# 方式一
#查看事务提交方式
SELECT @@AUTOCOMMIT;
#设置事务提交方式,1为自动提交,0为手动提交,该设置只对当前会话有效
SET @@AUTOCOMMIT = 0;
#此时为手动提交#提交事务
COMMIT;
#一开始没执行提交时是没有反应的,执行了提交,才会有下一步#一旦出错
#回滚事务
ROLLBACK;

方式1:给转账操作添加手动事务

select @@autocommit;# 1
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;
---回滚事务
rollback;

方式2
开启事务

start transaction 或 begin;

提交事务

commit;

回滚事务

rollback;

自动提交的事务方式:

set @@autocommit = 1;
#自动提交
select @@autocommit;
#开启事务
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;

事务四大特性

这里涉及面试题:原子性;一致性;隔离性;持久性

原子性:事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
一致性:事务完成时,必须使所有的数据都保持一致状态
隔离性:数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
持久性:事务一旦提交或者回滚,它对数据库中的改变就是永久的。

并发事务问题

A事务和B事务同时操作数据库会引发的问题
在这里插入图片描述

事务隔离级别

用来解决并发事务问题的
在这里插入图片描述
4种事务的隔离级别,×是在这种级别下可以解决

---查看事务隔离级别
select @@transaction_isolation;
---设置事务隔离级别
set [session|global] transaction isolation level {read uncommitted|read committed|repeatable read|serializable}

演示一下:

---查询事务隔离级别
select @@transaction_isolation;# repeatable read
---设置事务隔离级别
set session transaction isolation level read uncommitted;
set session transaction isolation level repeatable read;

开启2个终端窗口,相当于2个事务,切换到同一个数据库,演示第一个脏读问题:
窗口A:
设置了事务隔离级别是read uncommitted,它可以出现脏读问题
在这里插入图片描述
窗口B:
给张三减了1000
在这里插入图片描述
接下来看看窗口A:
张三的钱从2000减到了1000
在这里插入图片描述
以上就是脏读,因为窗口B执行的操作根本没有提交,事务开启了,它commit了吗?没有!所以read uncommitted是可以出现脏读问题的!
接下来将事务的隔离级别改成read committed
在这里插入图片描述
接下来脏读问题就会消失

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/428796.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Git必看系列】—— Git巨好用的神器之git stash篇

应用场景 当我们开发一个新功能时会先从master拉出一个分支dev&#xff0c;然后在这个dev分支下吭哧吭哧的开始写代码开发新功能&#xff0c;就如下代码所示&#xff0c;我们在dev分支下开发Person类的新功能getId() public class Person {private int id;private String nam…

零工市场小程序:推动零工市场建设

人力资源和社会保障部在2024年4月发布了标题为《地方推进零工市场建设经验做法》的文章。 零工市场小程序的功能 信息登记与发布 精准匹配、推送 在线沟通 权益保障 零工市场小程序作为一个找零工的渠道&#xff0c;在往后随着技术的发展和政策的支持下&#xff0c;功能必然…

C++——初步认识C++和namespace的用法

1.编程语言排行榜 我们通过排行可以看出 C在变成语言中还是占据着重要的地位 2.C在工作领域中的应用 1.PC客户端开发。⼀般是开发Windows上的桌面软件&#xff0c;比如WPS之类的&#xff0c;技术栈的话⼀般是C和 QT&#xff0c;QT 是⼀个跨平台的 C图形用户界面&#xff08;G…

表格标记<table>

一.表格标记、 1table&#xff1a;表格标记 2.caption:表单标题标记 3.tr:表格行标记 4.td:表格中数据单元格标记 5.th:标题单元格 table标记是表格中最外层标记&#xff0c;tr表示表格中的行标记&#xff0c;一对<tr>表示表格中的一行&#xff0c;在<tr>中可…

Scrapy爬虫IP代理池:提升爬取效率与稳定性

在互联网时代&#xff0c;数据就是新的黄金。无论是企业还是个人&#xff0c;数据的获取和分析能力都显得尤为重要。而在众多数据获取手段中&#xff0c;使用爬虫技术无疑是一种高效且广泛应用的方法。然而&#xff0c;爬虫在实际操作中常常会遇到IP被封禁的问题。为了解决这个…

小程序构建npm失败

小程序构建npm失败 项目工程结构说明解决方法引入依赖导致的其他问题 今天在初始化后的小程序中引入TDesign组件库&#xff0c;构建npm时报错。 项目工程结构说明 初始化后的项目中&#xff0c;包含miniprogram文件夹和一些项目配置文件&#xff0c;在project.config.json文件中…

【TypeScript入坑】TypeScript 的复杂类型「Interface 接口、class类、Enum枚举、Generics泛型、类型断言」

TypeScript入坑 Interface 接口简介接口合并TS 强校验Interface 里支持方法的写入class 类应用接口接口之间互相继承接口定义函数interface 与 type 的异同小案例 class 类类的定义与继承类的访问类型构造器 constructor静态属性&#xff0c;Setter 和 Getter做个小案例抽象类 …

fiddler抓包06_抓取https请求(chrome)

课程大纲 首次安装Fiddler&#xff0c;抓https请求&#xff0c;除打开抓包功能&#xff08;F12&#xff09;还需要&#xff1a; ① Fiddler开启https抓包 ② Fiddler导出证书&#xff1b; ③ 浏览器导入证书。 否则&#xff0c;无法访问https网站&#xff08;如下图&#xff0…

(十五)、把自己的镜像推送到 DockerHub

文章目录 1、登录Docker Hub2、标记&#xff08;Tag&#xff09;镜像3、推送&#xff08;Push&#xff09;镜像4、查看镜像5、下载镜像6、设置镜像为公开或者私有 1、登录Docker Hub 需要科学上网 https://hub.docker.com/ 如果没有账户&#xff0c;需要先注册一个。登录命令如…

docker搭建个人网盘,支持多种格式,还能画图,一键部署

1&#xff09;效果 2&#xff09;步骤 2.1&#xff09;docker安装 docker脚本 bash <(curl -sSL https://cdn.jsdelivr.net/gh/SuperManito/LinuxMirrorsmain/DockerInstallation.sh)docker-compose脚本 curl -L "https://github.com/docker/compose/releases/late…

技术成神之路:设计模式(十四)享元模式

介绍 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构性设计模式&#xff0c;旨在通过共享对象来有效地支持大量细粒度的对象。 1.定义 享元模式通过将对象状态分为内部状态&#xff08;可以共享&#xff09;和外部状态&#xff08;不可共享&#xff09;&#xf…

基于SpringBoot+Vue的高校竞赛管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…

力扣115-不同的子序列(Java详细题解)

题目链接&#xff1a;不同的子序列 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 dp五部曲。 1.确定dp数组和i下标的含义。 2.确定递推公式。 3.dp初始化。 4.确定dp的遍历顺序。 5.如果没有ac打印dp数组 利于debug。 每一个dp题目…

java使用ByteBuffer进行多文件合并和拆分

1.背景 因为验证证书的需要&#xff0c;需要把证书文件和公钥给到客户&#xff0c;考虑到多个文件交互的不便性&#xff0c;所以决定将2个文件合并成一个文件交互给客户。刚开始采用字符串拼接2个文件内容&#xff0c;但是由于是加密文件&#xff0c;采用字符串形式合并后&…

界面控件Telerik UI for WinForms 2024 Q3概览 - 支持合并单元格等

Telerik UI for WinForms拥有适用Windows Forms的110多个令人惊叹的UI控件。所有的UI for WinForms控件都具有完整的主题支持&#xff0c;可以轻松地帮助开发人员在桌面和平板电脑应用程序提供一致美观的下一代用户体验。 本文将介绍界面组件Telerik UI for WinForms在今年第一…

LeetCode2414题: 最长的字母序连续子字符串的长度(原创)

【题目描述】 字母序连续字符串 是由字母表中连续字母组成的字符串。换句话说&#xff0c;字符串 "abcdefghijklmnopqrstuvwxyz" 的任意子字符串都是 字母序连续字符串 。 例如&#xff0c;"abc" 是一个字母序连续字符串&#xff0c;而 "acb" 和…

vscode中如何配置c/c++环境

“批判他人总是想的太简单 剖析自己总是想的太困难” 文章目录 前言文章有误敬请斧正 不胜感恩&#xff01;一、准备工作二、安装 VSCode 插件三、配置 VSCode1. 配置编译任务&#xff08;tasks.json&#xff09;2. 配置调试器&#xff08;launch.json&#xff09; 四、运行和调…

Gitee Pipeline 从入门到实战【详细步骤】

文章目录 Gitee Pipeline 简介Gitee Pipeline 实战案例 1 - 前端部署输入源NPM 构建Docker 镜像构建Shell 命令执行案例 2 - 后端部署全局参数输入源Maven 构建Docker 镜像构建Shell 命令执行参考🚀 本文目标:快速了解 Gitee Pipeline,并实现前端及后端打包部署。 Gitee Pi…

Fabric:布匹纺织缺陷检测数据集(猫脸码客 第195期)

布匹数据集在纺织工业中的应用与探索&#xff1a;从布匹检索到纹理检测 引言 在快速发展的纺织工业中&#xff0c;信息技术的深度融合正逐步推动产业向智能化、精细化转型。其中&#xff0c;布匹数据集作为连接传统制造与数字技术的桥梁&#xff0c;其在布匹检索、纹理检测等…

【数据结构与算法 | 灵神题单 | 二叉搜索树篇】力扣99, 1305, 230, 897

1. 力扣99&#xff1a;恢复二叉搜索树 1.1 题目&#xff1a; 给你二叉搜索树的根节点 root &#xff0c;该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下&#xff0c;恢复这棵树 。 示例 1&#xff1a; 输入&#xff1a;root [1,3,null,null,2] 输出&…