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

news2024/11/11 23:09:31

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

  • 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展示及格;否则展示不及格
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;

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.coloradmin.cn/o/2139202.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习大数据DAY58 增量抽取数据表

作业 1 SQL 优化的常见写法有哪些 - 面试经常被问 使用索引&#xff1a;合理创建和使用索引是提高查询效率的关键。索引可以加速数据的检 索速度&#xff0c;但是索引也会占用额外的存储空间&#xff0c;并且在插入、删除和更新操作时会 有额外的开销。 避免全表扫描&…

Git+Jenkins 基本使用(Basic Usage of Git+Jenkins)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

Linux命令分享 四 (ubuntu 16.04)(vi操作文件)

1、su 切换用户 su - 用户名 切换到该用户并将目录切换至该用户的主目录 **注意该语句执行后需要输入密码&#xff0c;输入密码时终端不回显&#xff08;不会显示你输入的密码&#xff09;&#xff0c;输完直接回车即可 su 用户名 切换用户但不切换目录 su - root su root **注…

你可能遗漏的一些C#/.NET/.NET Core知识点

前言 在这个快速发展的技术世界中&#xff0c;时常会有一些重要的知识点、信息或细节被忽略或遗漏。《C#/.NET/.NET Core拾遗补漏》专栏我们将探讨一些可能被忽略或遗漏的重要知识点、信息或细节&#xff0c;以帮助大家更全面地了解这些技术栈的特性和发展方向。 拾遗补漏Git…

NISP 一级 | 5.3 电子邮件安全

关注这个证书的其他相关笔记&#xff1a;NISP 一级 —— 考证笔记合集-CSDN博客 0x01&#xff1a;电子邮件安全威胁 电子邮件&#xff08;Electronic mail&#xff0c;Email&#xff09;是一种用电子手段提供信息交换的服务方式&#xff0c;是因特网上应用最为广泛的服务之一。…

【原创 架构设计】多级缓存的应用、常见问题与解决方式

1. 简介 多级缓存是一种常见的性能优化手段&#xff0c;对于多级缓存一般意义上的理解具体主要实现其实指的就是本地缓存和分布式缓存。 本地缓存一般采用Caffeine或者Guava Cache来进行实现&#xff0c;而分布式缓存一般采用Redis来进行实现。 2. 业务流程 业务线程先在本…

聚类_K均值

import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_blobs1.数据预处理 #创建基于高斯分布的样本点, x是点的坐标&#xff0c;y是所属聚类值 x, y make_blobs(n_samples100, centers6, random_state100, cluster_std0.6) # 设置图形尺寸…

整数在内存中的存储原码反码补码

目录 1.整数在内存中以二进制的形式存在 1.1&#xff08;正数存储情况&#xff09; 1.2 负数存储情况 1.3整数的补码如何得到原码 2.无符号整数的原反补码 小心&#xff01;VS2022不可直接接触&#xff0c;否则&#xff01;没这个必要&#xff0c;方源面色淡然一把抓住&am…

Linux网络——守护进程、会话、进程组

文章目录 会话守护进程编写守护进程的注意事项编写样例 会话 会话是session&#xff0c;代表的是客户端与服务器的一次交互过程&#xff0c;我们可以简单理解为&#xff0c;当我们打开一个终端&#xff0c;在用户登录时&#xff0c;就是创建了一个会话 一般来说会话都与各自的…

62. 不同路径、64. 最小路径和

思路 dp&#xff1a;代表到达当前位置的总方式 初始化&#xff1a;第一行的位置dp[0][j]&#xff1a;当前位置只能由左边的位置向右移动得到 所以只有1种方式 d[0][j]1, d[0][0]1 第一列的位置 dp[i][0]&#xff1a;当前位置只能由上一个位置向下移动得到 除此之外的位置可以由…

python画图|同时输出二维和三维图

前面已经学习了如何输出二维图和三维图&#xff0c;部分文章详见下述链接&#xff1a; python画图|极坐标下的3D surface-CSDN博客 python画图|垂线标记系列_如何用pyplot画垂直x轴的线-CSDN博客 有时候也需要同时输出二位和三维图&#xff0c;因此有必要学习一下。 【1】…

三明儿童自闭症寄宿制学校:关爱、教育、成长一站式服务

三明儿童自闭症寄宿制学校的启示&#xff1a;广州星贝育园——自闭症儿童的一站式成长乐园 在探讨自闭症儿童教育的道路上&#xff0c;寄宿制学校以其独特的优势&#xff0c;为孩子们提供了集关爱、教育、成长于一体的全方位服务。虽然文章开头提及了“三明儿童自闭症寄宿制学…

AI预测体彩排3采取888=3策略+和值012路或胆码测试9月15日升级新模型预测第81弹

经过80多期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率非常高&#xff0c;已到达90%的命中率&#xff0c;这给喜欢打私菜的朋友提供了极高价值的预测结果~当然了&#xff0c;大部…

请求响应-05.请求-日期参数JSON参数

一.日期参数 当浏览器发起的请求参数类型是日期参数时&#xff0c;我们通常使用LocalDateTime对象来接收&#xff0c;前面使用DateTimeFormat注解来完成日期的格式转换&#xff08;日期时间格式有多种&#xff0c;需要哪种就设置为哪种&#xff1a;如yyyy-MM-dd HH:mm:ss&…

C++比大小游戏

目录 开头程序程序的流程图程序游玩的效果下一篇博客要说的东西 开头 大家好&#xff0c;我叫这是我58。 程序 #include <iostream> #include <Windows.h> using namespace std; int main() {int ir 1;char chparr[2] { 0 };int ip1 0;int ip2 0;int i 1;c…

【ARM】Cache深度解读

Cache的基本概念和使用场景 不同的Master硬件共享数据时—invalid cache 外设和DDR之间没有cache&#xff0c;所以外设直接把数据写入DDR中&#xff0c;但是cpu和DDR之间有cache&#xff0c;cpu会首先访问cache&#xff0c;如果命中直接从cache中拿数据&#xff0c;但是此时的…

完整版订单超时自动取消功能

前几天对实习还是继续学习技术产生了抉择&#xff0c;问了一个前辈&#xff0c;他抛给我一个问题&#xff0c;怎么做15分钟订单自动取消&#xff0c;我说然后到时间之后&#xff0c;自动执行这个订单关闭业务&#xff0c;比如把锁了的库存给解开等等操作&#xff0c;然后在数据…

后续学习规划 ----含我个人的学习路线,经历及感受

目前的基础 开发相关&#xff08;最重要&#xff09; 1.Java SE 从入门到起飞 2.Java Web开发 3.苍穹外卖 以上三个是和开发相关的基础。 我是按照书写的顺序学习的&#xff0c;有需要的朋友可以参考。 计算机相关 其他的话&#xff0c;都是比较久远的了。隔得时间一年半…

【大数据方案】智慧大数据平台总体建设方案书(word原件)

第1章 总体说明 1.1 建设背景 1.2 建设目标 1.3 项目建设主要内容 1.4 设计原则 第2章 对项目的理解 2.1 现状分析 2.2 业务需求分析 2.3 功能需求分析 第3章 大数据平台建设方案 3.1 大数据平台总体设计 3.2 大数据平台功能设计 3.3 平台应用 第4章 政策标准保障体系 4.1 政策…

nginx: [emerg] unknown “connection_upgrade“ variable 解决与思考

问题,如下图&#xff1a; 一天更新完主分支后启动nginx,结果报错&#xff1a;nginx: [emerg] unknown "connection_upgrade" variable 解决方法 网上查&#xff0c;发现是nginx配置文件出了问题&#xff0c;将下面map代码块补上即可。 http { map $http_upgrade …