一、初识MySQL
1.1 什么是数据库
数据库(DB,DataBase)
概念:数据仓库,是一个软件,安装在操作系统上,可存储大量数据。
作用:存储数据,管理数据。
1.2 数据库分类
关系型数据库:
- MySQL、Oracle、Sql Server、 DB2、SQLlite
- 通过表和表之间,行和列之间的关系进行数据的存储。
非关系型数据库:NoSQL(Not Only SQL)
- Redis、MongDB
- 非关系型数据库,对象存储,通过对象自身的属性来决定。
DBMS(数据库管理系统)
- 可理解为数据库的管理软件,更科学有效的管理数据。
- MySQL,RDBMS(关系型数据库管理系统)
1.3 MySQL简介
MySQL是一个 关系型数据库管理系统
瑞典MySL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
关键词:开源、体积小、成本低。
1.4 MySQL安装
选择压缩包安装,安装程序安装卸载不干净。
链接:https://dev.mysql.com/downloads/mysql/
-
下载解压后,配置环境变量,将bin目录添加到path环境变量中
-
新建一个文件 my.ini 在安装目录下,内容如下:
[client] # 设置mysql客户端默认字符集 default-character-set=utf8 [mysqld] # 设置3306端口 port = 3306 # 设置mysql的安装目录 basedir=E:\mysql-8.0.28-winx64 # 允许最大连接数 max_connections=20 # 服务端使用的字符集默认为8比特编码的latin1字符集 character-set-server=utf8
-
启动管理员模式下的CMD,并将路径切换至mysql下的bin目录,输入
mysqld -install
。出现这句话表示成功 -
初始化数据库,输入命令
mysqld --initialize-insecure
。什么都不提示表示成功(我图中输入错了) -
启动mysql服务,
net start mysql
,如果出现无法启动且不报错的情况,将安装目录下的data目录删掉,然后输入命令mysqld --initialize-insecure
,即可启动成功。 -
输入
mysql -u root -p
登录MySQL,密码不用输入,直接回车。命令行变为 mysql> 表示成功
-
进去后修改密码,命令为
alter user 'root'@'localhost' identified by '123456';
,意为将密码修改为123456,出现如上图提示即为成功,还可以再输入FLUSH PRIVILEGES;
刷新权限。
1.7SQLyog安装
SQLyog是一个MySQL的图形化管理工具。
资源就不说了,网上一搜一大堆,这里介绍一些常用操作。
-
安装完成后,打开sqlyog,新建一个连接:
3306是默认端口号,不用修改。
-
右键root@localhost新建一个数据库:
设置字符集以及排序规则,utf8和utf8mb4都可以,utf8mb4用四个比特存储字符,utf8用三个比特存储字符。排序规则general_ci不区分大小写,常用的还有unicode_ci和bin。随便选一个就行
-
右键表创建表
引擎选择InnoDB,字符和刚才一样,数据类型稍有不一样但都差不多,varchar就像是字符串。
-
有了表就可以添加记录了
sqlyog有很多傻瓜式操作,对应的命令可以在历史记录中找到。
1.6 我踩的坑
-
之前装过mysql 没有卸载干净,要把之前的删干净,然后sc delete mysql
再把注册表中的Imagepath修改为现在装的bin目录下的mysqld
-
密码一直错误
停止mysql服务
杀掉进程
莫名奇妙就好了
-
修改密码语句错误
我是8版本
修改密码的语句是
ALTER user 'root'@'localhost' IDENTIFIED BY 'newpassword';
-
链接SQLyog错误
原因是8版本之后加密规则变了
解决:进入MySQL中 依次执行
-- 修改加密规则 ALTER USER 'root'@'localhost' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER; -- 更新用户的密码 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'; -- 刷新权限 FLUSH PRIVILEGES; -- 重置密码 alter user 'root'@'localhost' identified by '123456';
1.7 一些基本的命令操作
有了图形化管理工具确实会方便很多,但是命令操作也必须要会,编程的时候SQL语句必须要会。
mysql>
之后的所有命令,都必须以分号结尾,且不区分大小写。
-- 连接数据库
mysql -uroot -ppassword
-- password填自己的密码
ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';
-- 修改密码
-- 所有的语句都使用分号结尾
show databases:
-- 查看所有的数据库
use school;
-- 切换数据库 use 数据库名
show tables;
-- 查看数据库中所有的表
describe student;
-- 显示表中所有信息 descibe 表名
create database school;
-- 创建一个数据库 create databases 数据库名
exit;
-- 退出连接
-- 这是注释 这是sql本来的注释
/* 这也是注释
这是sql的多行注释
*/
# 这也是注释 不推荐 但yog里面能用
二、MySQL的表
和其他语言一样,也有很多数据类型,但不用强记,记住常用就可以了。
2.1 数据类型(列类型)
MySQL中的数据类型大概分为三种:数值、字符串、时间。
有个特殊的null值,表示没有值,如果参与运算,则结果为null。
2.1.1 数值类型
-
整形:
-
tinyint:很小的数据 1比特
-
smallint:较小的数据 2比特
-
mediumint:一般小的数据 3比特
-
int:标准的数据 4比特
-
bigint:很大的数据 8比特
-
-
浮点型:
-
float:单精度浮点数值 4比特
-
double:双精度浮点值 8比特
-
-
decimal:比较精确的小数值
2.1.2 字符串类型
-
字符:
-
char:定长字符串 0~255比特
-
varchar:变长字符串 0~65535比特
-
-
文本:
-
tinytext:短文本字符串 0~255比特
-
text:一般文本数据 0~65535比特
-
mediumtext:中等文本数据 0~16777215比特
-
longtext:极大文本数据 0~4294967295比特
-
-
二进制:
-
tinyblob:二进制形式的短字符串 0~255比特
-
blob:二进制形式的一般文本数据 0~65535比特
-
mediumblob:二进制形式的中等文本数据 0~16777215比特
-
longblob:二进制形式的极大文本数据 0~4294967295比特
-
2.1.3 日期和时间类型
-
date:存储YYYY-MM-DD格式的日期值,占3个比特的空间。
-
time:存储HH:MM:SS格式的时间或持续时间值,占3个比特的空间。
-
year:存储YYYY格式的年份值,占1个比特的空间。
-
datetime:存储YYYY-MM-DD HH:MM:SS格式的时间,占8个比特的空间。
-
timestamp:存储时间戳,1970-1-1到现在的毫秒数, 占4个比特的空间
2.2字段属性
字段名和字段类型不必多说,说几个常用的。
-
长度:
长度可以指定varchar的长度,还可以指定数值0填充的长度。
-
默认
默认就是什么都不填时的值。
-
主键
每个表只能有一个主键,主键不能为null,表中不能存在有相同主键值的两行数据(唯一性原则),有点键值对中的键的感觉,通过主键唯一表示每一条记录。
-
非空
表示该字段不能为空。
-
unsigned
表示是无符号数,不能为负数。
-
自增
就是自动增量,默认每次+1。
-
zerofill
0填充,如设置int长度为5,只是存入1,那么1就会变成00001
三、操作MySQL
操作数据库无非就是操作数据库、操作数据库中的表、操作表中的数据。
常用命令:
show create database xxx; -- 查看创建xxx数据库时的命令
show create table xxx; -- 查看创建xxx表时的命令
3.1 操作数据库
- 创建数据库
创建一个新的数据,如果xxx存在则会报错
create database xxx
如果xxx存在则不创建
create database if not exists xxx
- 删除数据库
删除一个数据库,如果数据库不存在会报错
drop database xxx
如果存在xxx数据库则删除
drop database if exists xxx
- 使用数据库
切换到xxx数据库,养成好习惯名字用反引号括起来
use `xxx`;
- 查看数据库
show databases
3.2 操作表
-
创建表:
既然创建数据库为create database,那么创建表大概率就是create table
-- 创建表 【】 括起来表示可选 create table [if not exists] `表名` ( `字段名` 列类型 [属性] [属性] [注释], `字段名` 列类型 [属性] [属性] [注释], `字段名` 列类型 [属性] [属性] [注释], …… )[表类型] [字符集设置] [注释];
实例:
-- 创建一个名为teacher的表 CREATE TABLE IF NOT EXISTS `teacher` ( `id` INT(4) ZEROFILL NOT NULL AUTO_INCREMENT COMMENT'工号', `name` VARCHAR(20) NOT NULL DEFAULT '张三' COMMENT'姓名', `sex` VARCHAR(4) NOT NULL DEFAULT'男' COMMENT'性别', `age` INT(3) NOT NULL COMMENT'年龄', PRIMARY KEY(`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8;
-
查看表结构
desc xxx
或是describe xxx
-
删除表
DROP TABLE IF EXISTS xxx
建议能每次都加上判断,不然会报错
-
修改表
alter table `旧表名` rename as `新表名`; -- 修改表名 alter table `表名` add `字段名` 属性; -- 添加属性 alter table `表名` modify `字段名` 属性; -- 修改属性,不可修改字段名 alter table `表名` change `旧字段名` `新字段名` 属性; -- 修改属性,还可以修改字段名 alter table `表名` drop `字段名`; -- 删除字段
四、MySQL数据
4.1 外键
简单的说,就是将此表的某一列,与另一张表的某一列关联上,外键不是通过列名实现的,而是通过定义外键约束:
- 创建表的时候指定约束:
CREATE TABLE `grade` (
`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT'年级id',
`gradename` VARCHAR(50) NOT NULL COMMENT'年级名称',
PRIMARY KEY(`gradeid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `student`(
`id` INT(4) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT COMMENT'年级学号',
`name` VARCHAR(50) NOT NULL COMMENT'姓名',
`gradeid` INT(10) NOT NULL COMMENT'学生年级',
PRIMARY KEY(`id`),
KEY `FK_gradeid`(gradeid), -- 定义外键
CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade`(`gradeid`) -- 添加约束和引用
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
-
创建完成后添加约束
CREATE TABLE `grade` ( `gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT'年级id', `gradename` VARCHAR(50) NOT NULL COMMENT'年级名称', PRIMARY KEY(`gradeid`) ) ENGINE=INNODB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `student`( `id` INT(4) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT COMMENT'年级学号', `name` VARCHAR(50) NOT NULL COMMENT'姓名', `gradeid` INT(10) NOT NULL COMMENT'学生年级', PRIMARY KEY(`id`), )ENGINE=INNODB DEFAULT CHARSET=utf8mb4; alter table `student` add constraint `FK_gradeid` foreign key(`gradeid`) references `grade`(`gradeid`);
但不管是哪种方式,都不推荐(物理外键)!
因为表就是单纯的表,只用来存数据,只有行和列,如果想使用多张表的数据,我们就用程序去实现外键(逻辑外键)。
4.2 DML语言(重点)
也就是数据库管理语言
4.2.1 Insert
插入数据
insert into `表名`(`属性1`,`属性2`,……) values('值1','值2',……),('值1','值2',……),……;
实例:
-- 在student表中添加三条数据
INSERT INTO `student`(`name`, `gradeid`) VALUES('李四','5'),('李七','5'),('王五','6');
属性名可以省略,如果属性名省略,那么值就要和表的字段一一对,不能少写。
4.2.2 Update
修改数据
update `表名` set `字段名`='值' where 条件;
-- where 后面表示条件,限定了只修改符合此条件记录
update `表名` set `字段名`='值';
-- 如果不加条件,那么就是修改表中所有记录
update update `表名` set `字段名`='值',`字段名`='值',…… where 条件;
-- 如果要修改记录的多个字段,用英文逗号隔开
实例:
UPDATE `student` SET `name` = 'lq' WHERE id = 1;
-- 将student表中id为1的记录的name的值改为lq
UPDATE `student` SET `name` = 'lq';
-- 将student表中所有记录的name的值改为lq
UPDATE `student` SET `name` = 'lq' WHERE id < 5;
-- 将student表中所有id小于5的记录的name改为lq
-
比较特殊一点的操作符
“ <> ” 在mysql中相当于 “ != ”,
between 2 and 5 表示2(含)到5(含),
多个条件还可以用and和or(相当于Java中的&& 和 ||)
4.2.3 Delete
删除数据
delete from `表名` where 条件
实例:
DELETE FROM `student` WHERE `name`='lq';
-- 将student表中name为lq的记录删除
DELETE FROM `student`;
-- 如果不加条件,则为删除表中所有数据(避免这样些)
清空表还有更好的做法:
truncate `表名`
-
truncate和delete的区别
delete不会影响自动增量
truncate会重置自动增量 不会影响事务
五、DQL查询数据(超级重点)
DQL(Data Query Language)即数据库查询语言。
查询语句是使用频率最高的语句,所有的查询操作都用select,是数据库最核心,最重要的语句。
select语法:
select [all | distinct] column1[as c1],column2[as c2],..... -- all是查询所有,distinct是去重
FROM table1[as t1] -- as是取别名
[left | right | inner join table2] -- 联合查询,左连接、右连接、内连接
[where ....] -- 指定结果需要满足的条件,这里可以写嵌套查询语句(子查询)
[group by...] -- 指定结果按n个字段来分组
[having ...] -- 过滤分组的记录需要满足的次要条件,条件和where一样,位置不同
[order by ...] -- 查询记录按一个或多个条件排序,ASC、DESC
[limit x,y] -- 指定查询记录从第x条到第y条,分页查询
这是完整的,中括号括起来表示可选,接下来会一个一个解释。
顺序不能颠倒。
5.1 做一些简单的查询
select * from `表名`;
-- 查询表的所有数据
select `字段`,`字段`,…… from `表名`;
-- 查询指定的字段
select `字段名` as `新字段名`,`字段名` as `新字段名`,…… from `表名` as `新表名`;
-- 查询指定的字段,并给结果取名字
-- 函数concat(a,b) 连接a,b
-- 例:
select concat('姓名:', `name`) from student;
-- 在表student中查询所有记录的name字段,并将结果的前面拼上一个字符串"姓名:",结果如图:
5.2 带点小操作的查询
-
去重 distinct
SELECT DISTINCT `name` FROM student; -- 意为查询student表中name不同的数据
-
查看版本
SELECT VERSION();
-
甚至可以做点计算
SELECT 100*3-1 AS `做点计算`;
-
还可以查点奇奇怪怪的东西
-- 比如查自增步长 SELECT @@auto_increment_increment; -- @@auto_increment_increment就是一个变量
-
让所有记录的某字段+1
SELECT `id`+1 FROM student; -- 查询student表中所有id,使结果+1
等等等等……select就是这么牛逼
5.3 where条件子句
5.3.1 逻辑运算
之前我们修改数据或者删除数据时,where作用就是来筛选符合条件的记录。
where后面跟着条件,既然要判断,就得有逻辑运算,而这些运算符,大多数都和其他语言相同,下面说几个比较特殊的
等于:sql中就是”=“不是双等号。
不等于: 即可”!=“ 也可”<>“,
与:即可”&&“ 也可”and“,
或:即可”||“ 也可”or“,
非:即可”!“ 也可”not“,
还有between…and……这种写法。
举个例子,假如我现在要查询 id 为2~10(含)之间的所有记录,则有以下三种写法:
-- 查询 id 在2~10之间的所有记录
SELECT * FROM `student`
WHERE `id` >= 2 AND `id` <= 10;
SELECT * FROM `student`
WHERE `id` >= 2 && `id` <= 10;
SELECT * FROM `student`
WHERE `id` BETWEEN 2 AND 10;
5.3.2 模糊查询
is null: a is null,意为 如果a为null,则为真。
is not null:a is not null 意为如果a不是null,则为真。
between:之前说过。
like:a like b, SQL匹配,如果a匹配b,则为真(下面代码中细说)。
in:a in (a1, a2, a3, ……),如果a时其中某一个值,则为真。
还是上代码:
-- like 实例
SELECT * FROM `student`
WHERE `name` LIKE '李_';
-- 查询student表中所有 name 为 李开头的两个字的记录
SELECT * FROM `student`
WHERE `name` LIKE '%李%';
-- 查询student表中所有 name 中带李的的记录
这里出现了 ” _ “下划线和” % “百分号,下划线表示任意一个字符,百分号表示0到任意个字符(含0)。(只在like中用)
接下来就是in的应用
-- in 实例
SELECT * FROM `student`
WHERE `name` IN ('李七', '王五', '张一', '李四');
-- 查询student表中所有 name 为'李七', '王五', '张一', '李四'的记录。
5.4 联表查询
可以用join连接表在多张表种进行查询,连接方式有7种,这里只说三种最基本的,其他方式都可以通过这三种加一些条件来实现。
-
inner join (内连接)
红色区域就是查询到的部分
select * from A inner join B on A.key = B.key; -- 在A和B表中查询所有A.key = B.key的记录
-
left join(左连接)
红色区域就是查询部分
select * from A left join B on A.key = B.key; -- 查询A表中所有数据以及B表中A.key = B.key的数据,右表中没有匹配的值则为null
-
right join(右连接)
红色区域就是查询部分,正好和左连接相反
select * from A right join B on A.key = B.key; -- 查询B表中所有数据以及A表中A.key = B.key的数据,左表中没有匹配的值则为null
-
on 和 where的区别
联表查询时,join搭配on生成一个临时表,若再加上一个where,那么where就是过滤的这个临时表格的数据,而on是过滤的这个临时表生成出来之前的数据。
自连接
自己和自己连接,也就是两张一样的表连接,上代码!
-- 创建表
CREATE TABLE IF NOT EXISTS `test` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT'ID',
`pid` INT(10) UNSIGNED NULL COMMENT'父ID',
`name` VARCHAR(20) NOT NULL COMMENT'名称;',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
-- 添加数据
INSERT INTO `test`(`pid`, `name`) VALUES
(0, '动物'),
(0, '植物'),
(1, '猫'),
(2, '花'),
(1, '牛'),
(2, '草'),
(1, '羊'),
(2, '树');
-- 查询
SELECT A.`name` AS `父类`, B.`name` AS `子类`
FROM `test` AS `A` INNER JOIN `test` AS `B`
ON A.`id` = B.`pid`;
原本表是这样的:
生成的临时表是这样的:
自连接也就是两张一样的表连接,过滤一些数据。
5.5 分页
语法LIMIT 起始值 页面大小
如limit 0,5就表示 一页显示五个数据 从 0开始 也就是 0 1 2 3 4。
实例:
SELECT * FROM student
LIMIT 0,5;
-- 表示查询 student 表中前五条数据
5.6 排序
语法 ORDER BY 字段名
DESC(降序) 或 ASC(升序)
实例:
SELECT * FROM student
ORDER BY `id` DESC;
-- 表示查询student表中所有数据,并将这些数据按照 id 降序排序。
和分页混合一下:
SELECT * FROM student
ORDER BY `id` DESC
LIMIT 0,5;
-- 表示查询student表中所有数据,并将这些数据按照 id 降序排序 然后查询前五条数据。
5.7 子查询 嵌套查询
假如现在有一个这样的联表查询
SELECT s.*
FROM student s INNER JOIN teacher t
ON s.`id` = t.`id` ;
-- 查询student表中 所有与teacher表中id相同的记录
修改一下
SELECT s.*
FROM student s, teacher t
WHERE s.`id` = t.`id`;
写的花点
SELECT *
FROM student
WHERE `id` = ANY(
SELECT `id` FROM `teacher`
)
-- 这个就是子查询,但是子查询的结果只能为一条,不然就得像这样加上any
或是
SELECT *
FROM student
WHERE id IN (
SELECT id FROM teacher
)
总之,sql可以嵌套着写,查询某种数据的方式有很多种,能满足需求都可以。
嵌套查询大致规律:由内到外查询。
六、MySQL函数
我们基本上不会再数据库层面上使用这些函数,若是遇到了,就去查就行了,我就不再啰嗦了。
6.1 聚合函数
倒是得说一下聚合函数:
聚合函数就是对一组值进行计算并返回单一的值。
- count
SELECT COUNT(`name`) FROM `student`;
-- 查询student表中有多少个name不为空的记录
SELECT COUNT(*) FROM `student`;
-- 查询student表中 总共的记录数
SELECT COUNT(1) FROM `student`;
-- 和上一条sql效果一样
-- count可以查询记录数(行数)
-
帮我我们处理数据的聚合函数
SELECT SUM(`id`) FROM `student`; SELECT AVG(`id`) FROM `student`; SELECT MAX(`id`) FROM `student`; SELECT MIN(`id`) FROM `student`; -- 其实看函数名都能知道它们的作用了 -- 分别是求 student 表中 id 这个字段的 总和、平均数、最大值和最小值
6.2 group by 和 having
能查询某些数据的最大值或最小值后,我们就会遇到一些问题,现在有这么一张表:
CREATE TABLE IF NOT EXISTS `student` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(20) NOT NULL,
`subjectName` VARCHAR(12) NOT NULL,
`point` INT(3) UNSIGNED NOT NULL,
`group` INT(1) UNSIGNED NOT NULL,
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
INSERT INTO `student` (`name`,`subjectName`,`point`,`group`)
VALUES
('张三', '语文', 86, 1),
('李四', '语文', 103, 2),
('王五', '数学', 120, 1),
('杨七', '数学', 94, 2),
('孙八', '英语', 124, 3),
('甘强', '英语', 57, 2),
('罗二', '英语', 96, 3);
如果我们要一次性查出每一科的平均分、最高分、最低分,应该怎么写?
这个时候就需要用到group by 了。
SELECT `subjectName`, AVG(`point`), MAX(`point`), MIN(`point`)
FROM `student`
GROUP BY `subjectName`;
-- 查询平均分、最高分、最低分,按照字段subjectName分组
结果:
因为where要写在group by上面,我们怎么才能对查询出来的数据进行过滤呢,比如 只显示 最高分在120以上的科目,这个时候,就需要用到
HAVING
SELECT `subjectName`, AVG(`point`), MAX(`point`), MIN(`point`)
FROM `student`
GROUP BY `subjectName`
HAVING MAX(`point`) >= 120;
-- 表示过滤掉 MAX(`point`) < 120 的记录
结果:
七、事务
事务(Transaction),就是要做或所做的事情。一般就是指一条或一组SQL语句。
7.1 ACID
事务,应该具有4个属性(A C I D):
Atomicity:原子性。一个事务是一个不可分割的单位,如一个事务有两条sql,要么都成功,要么都失败。
Consistency:一致性。事务必须是使数据库从一个一致性状态变为另一个一致性状态。比如A,B共有一千块,经过一些转账(AB互转)后,A,B的总和还是一千块。
Isolation:隔离性。每个事务执行互不干扰。
Durability:持久性。如果没有提交事务,那么数据不变,一旦提交,数据永久性改变。
7.2 事务的隔离级别
-
脏读
一个事务读取了另一个事务未提交的数据。
-
不可重读
在一个事务内读取表中的某一行数据,多次读取结果不同。
-
虚读(幻读)
一个事务读到了另一个事务插入的数据,前后总量不一致。
事务实例:
-- 创建数据库
CREATE DATABASE shop CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 切换到shop
USE shop;
-- 创建表
CREATE TABLE `account` (
`id` INT(4) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
-- 插入记录
INSERT INTO `account`(`name`,`money`)
VALUES ('A',2000.00),
('B',10000.00);
-- 关闭自动提交
SET autocommit=0;
-- 开启事务
START TRANSACTION;
-- 进行操作
UPDATE account SET money=money-500 WHERE `name` = 'A';
UPDATE account SET money=money+500 WHERE `name` = 'B';
-- 提交事务
COMMIT;
-- 回滚
ROLLBACK;
-- 恢复默认值,恢复自动提交
SET autocommit=1;
ion),就是要做或所做的事情。一般就是指一条或一组SQL语句。
7.1 ACID
事务,应该具有4个属性(A C I D):
Atomicity:原子性。一个事务是一个不可分割的单位,如一个事务有两条sql,要么都成功,要么都失败。
Consistency:一致性。事务必须是使数据库从一个一致性状态变为另一个一致性状态。比如A,B共有一千块,经过一些转账(AB互转)后,A,B的总和还是一千块。
Isolation:隔离性。每个事务执行互不干扰。
Durability:持久性。如果没有提交事务,那么数据不变,一旦提交,数据永久性改变。
7.2 事务的隔离级别
-
脏读
一个事务读取了另一个事务未提交的数据。
-
不可重读
在一个事务内读取表中的某一行数据,多次读取结果不同。
-
虚读(幻读)
一个事务读到了另一个事务插入的数据,前后总量不一致。
事务实例:
-- 创建数据库
CREATE DATABASE shop CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 切换到shop
USE shop;
-- 创建表
CREATE TABLE `account` (
`id` INT(4) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
-- 插入记录
INSERT INTO `account`(`name`,`money`)
VALUES ('A',2000.00),
('B',10000.00);
-- 关闭自动提交
SET autocommit=0;
-- 开启事务
START TRANSACTION;
-- 进行操作
UPDATE account SET money=money-500 WHERE `name` = 'A';
UPDATE account SET money=money+500 WHERE `name` = 'B';
-- 提交事务
COMMIT;
-- 回滚
ROLLBACK;
-- 恢复默认值,恢复自动提交
SET autocommit=1;