登录数据库
mysql -u用户名 -p 密码
数据库命令以分号;结尾,一条可以分为好几行,不区分大小写
注释方式是
单行 -- 内容 注意--后面有一个空格
多行 /* */
SQL语句
分类 | 全称 | 说明 |
---|---|---|
DDL | Data Definition Language | 数据定义语言,用来定义数据库结构和对象(数据库,表,字段) |
DML | Data Manipulation Language | 数据操作语言,用来对数据库中的数据进行增删改 |
DQL | Data Query Language | 数据查询语言,用来查询数据库中的记录 |
DCL | Data Control Language | 数据控制语言,用来创建或撤销用户账户,控制数据库的访问权限 |
数据库设计DDL
DDL数据库设计
创建数据库
database也可以改为schema
create database 数据库名字; -- create schemas 数据库名字
如果创建的数据库已经有了会报错。加一个判断语句if not exists
create database if not exists 数据库名字; CREATE DATABASE mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
查询数据库
show databases -- show schemas
切换数据库
use 数据库名字;
查看当前正在使用的数据库是哪个数据库
select database();
删除数据库
drop database 数据库名
如果该数据库已经没有了在删除会报错,此时使用判断语句if exists
drop database if exists 数据库名
DDL表操作
约束关键字
字段 | 描述 | 约束 |
---|---|---|
非空约束 | 该字段值不能为null | not null |
唯一约束 | 保证字段的所有有效数据都是唯一的,不能重复 | unique |
主键约束 | 主键是一个或数个的唯一标识,要求非空且唯一,主键自增auto_increment | primary key |
默认约束 | 保存数据时,如果未指定该字段值,则采用默认值 | default |
外键约束 | 让两张表的数据建立逻辑连接,保证数据的一致性和完整性 | foreign key |
创建表
create table 表名( 字段1 字段1类型 [约束] [comment '字段1注释' ], 字段2 字段2类型 [约束] [comment '字段2注释' ], ...... 字段n 字段n类型 [约束] [comment '字段n注释' ] ) [ comment '表注释' ] ; []代表可写可不写
create table tb_user( id int primary key comment '用户id', username varchar(20) not null unique comment '用户账号', -- 约束可以多个存在 name varchar(5) not null comment '名字', age int comment '年龄', gender char(1) default '男' comment '性别' )comment '用户表';
查询表
-
查看当前数据库所有表格:show tables;
-
查看表结构:desc 表名;
-
查看建表语句:show create table 表名;
修改表
-
添加字段:
alter table 表名 add 字段名 类型(长度) [comment 注释] [约束];
-
修改字段类型:
alter table 表名 modify 字段名 新类型(长度);
-
修改字段名和字段类型:
alter table 表名 change 原字段名 新字段名 类型(长度) [comment 注释] [约束];
-
删除字段:
alter table 表名 drop column 字段名;
-
重命名表:
rename table 旧名 to 新名;
以上操作最好以可视化工具的方式修改,不使用sql语句
Mysql数据类型
数值类型
分类 | 类型 | 大小 (byte) | 有符号 (SIGNED) 范围 | 无符号 (UNSIGNED) 范围 | 描述 |
---|---|---|---|---|---|
数值类型 | tinyint | 1 | (-128, 127) | (0, 255) | 小整数值 |
smallint | 2 | (-32768, 32767) | (0, 65535) | 大整数值 | |
mediumint | 3 | (-8388608, 8388607) | (0, 16777215) | 大整数值 | |
int | 4 | (-2147483648, 2147483647) | (0, 4294967295) | 大整数值 | |
bigint | 8 | (-2^63, 2^63-1) | (0, 2^64-1) | 极大整数值 | |
float | 4 | (-3.402823466 E+38, 3.402823466351 E+38) | 0 和 (1.175494351 E-38, 3.402823466 E+38) | 单精度浮点数值 | |
double | 8 | (-1.7976931348623157 E+308, 1.7976931348623157 E+308) | 0 和 (2.2250738585072014 E-308, 1.7976931348623157 E+308) | 双精度浮点数值 | |
decimal | 小数值 (精度更高) |
关键字unsigned。控制是否有符号 -- 创建一个无字符的极小整数值 gender tinyint unsigned not null, float(5,2):5表示整个数字长度,2 表示小数位个数 double(5,2):5表示整个数字长度,2 表示小数位个数 decimal(5,2):5表示整个数字长度,2 表示小数位个数
字符串类型
分类 | 类型 | 大小 | 描述 |
---|---|---|---|
字符串类型 | char | 0-255 bytes | 定长字符串 |
varchar | 0-65535 bytes | 变长字符串 | |
tinyblob | 0-255 bytes | 不超过255个字符的二进制数据 | |
tinytext | 0-255 bytes | 短文本字符串 | |
blob | 0-65,535 bytes | 二进制形式的长文本数据 | |
text | 0-65,535 bytes | 长文本数据 | |
mediumblob | 0-16,777,215 bytes | 二进制形式的中等长度文本数据 | |
mediumtext | 0-16,777,215 bytes | 中等长度文本数据 | |
longblob | 0-4,294,967,295 bytes | 二进制形式的极大文本数据 | |
longtext | 0-4,294,967,295 bytes | 极大文本数据 |
char(10): 最多只能存10个字符,不足10个字符,占用10个字符空间 AB 性能高 浪费空间 varchar(10): 最多只能存10个字符,不足10个字符, 按照实际长度存储 ABC 性能低 节省空间
日期类型
分类 | 类型 | 大小(byte) | 范围 | 格式 | 描述 |
---|---|---|---|---|---|
日期类型 | date | 3 | 1000-01-01 至 9999-12-31 | YYYY-MM-DD | 日期值 |
time | 3 | -838:59:59 至 838:59:59 | HH:MM:SS | 时间值或持续时间 | |
year | 1 | 1901 至 2155 | YYYY | 年份值 | |
datetime | 8 | 1000-01-01 00:00:00 至 9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 | |
timestamp | 4 | 1970-01-01 00:00:01 至 2038-01-19 03:14:07 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值,时间戳 |
数据库操作DML
insert语法
-
插入字段映射规范插入:
insert into 表名 (字段1, 字段2) values (值1, 值2);
-
全部字段映射规范插入:
insert into 表名 values (值1, 值2, ...);
-
批量映射插入(指定字段):
insert into 表名 (字段1, 字段2) values (值1, 值2), (值1, 值2);
-
批量映射插入(全部字段):
insert into 表名 values (值1, 值2, ...), (值1, 值2, ...);
insert into table_emp(id, username, name, gender, img, entrydate, create_time, update_time) values (null,'zhizhu','蜘蛛',1,'1.jpg','2021-02-12',now(),now()); insert into table_emp values (null,'papa','蜘蛛',1,'1.jpg','2021-02-12',now(),now()); insert into table_emp(id, username, name, gender, img, entrydate, create_time, update_time) values(null,'assa','蜘蛛',1,'1.jpg','2021-02-12',now(),now()), (null,'asasa','蜘蛛',1,'1.jpg','2021-02-12',now(),now()); insert into table_emp values (null,'bbbb','蜘蛛',1,'1.jpg','2021-02-12',now(),now()), (null,'cccccc','蜘蛛',1,'1.jpg','2021-02-12',now(),now());
update语法
-
修改数据:update 表名 set 字段1=值1,字段2=值2 [where 条件]
-- 1.将table_emp表id为1的员工名字修改为‘张三’(注意,除了名字以外还有一个隐藏的字段需要更新,就是update_time) update table_emp set name='张三',update_time=now() where id=1; -- 2.将所有员工信息的入职日期修改为'2010-10-10' update table_emp set entrydate='2010-10-10',update_time=now();
delete语法
删除数据:delete from 表名 [where 条件]
-- 1.删除id为1的员工 delete from table_emp where id=1; -- 2.删除所有的员工 delete from table_emp
数据库查询DQL
基本查询
-
查询多个字段:
select 字段1, 字段2, 字段3 from 表名;
-
查询所有字段(通配符):
select * from 表名;
-
设置别名:
select 字段1 [as 别名1], 字段2 [as 别名2] from 表名;
-
去除重复记录:
select distinct 字段列表 from 表名;
-- 1.查询指定字段name,entrydate,并返回 select name,entrydate from tb_emp; -- 2.查询返回所有字段 -- 推荐 select id, username, password, name, gender, image, job, entrydate, create_time, update_time from tb_emp; -- 不推荐(不直观,效率低) select * from tb_emp; -- 3.查询所有员工的name,entrydate,并起一个别名(姓名,入职日期) select name as 姓名,entrydate as 入职日期 from tb_emp; -- 输出的表的字段名变味了别名,如果有特殊符号用单引号圈主整体'姓 名' select name '姓 名',entrydate 入职日期 from tb_emp; -- as可以省略,输出的别名为'姓 名' -- 4.查询已有员工的职位(去重复) select distinct job from tb_emp;
条件查询(where)
比较运算符 | 功能 |
---|---|
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
= | 等于 |
<> 或 != | 不等于 |
between ... and ... | 在某个范围之内(含最小值, 最大值) |
in(...) | 在in之后的列表中的值, 多选一 |
like 与位符 | 模糊匹配(_匹配单个字符, %匹配任意字符) |
is null(is not null) | 是null(非空) |
逻辑运算符 | 功能 |
---|---|
and 或 && | 并且(多个条件同时成立) |
or 或 || | 或者(多个条件任意一个成立) |
not 或 ! | 非,不是 |
-- 1.查询姓名为杨逍的员工 select * from tb_emp where name='杨逍'; -- 2.查询id小于等于5的员工信息 select * from tb_emp where id<=5; -- 3.没有分配职位的员工信息 select * from tb_emp where job is null ; -- 4.查询有职位的员工信息 select * from tb_emp where job is not null; -- 5.查询密码不等于'123456'的员工信息 select * from tb_emp where password !='123456'; -- 6. 查询入职日期在'2000-01-01'(包含)到'2010-01-01'(包含)之间的员工信息 select * from tb_emp where entrydate>='2000-01-01' and entrydate<='2010-01-01'; select * from tb_emp where entrydate between '2000-01-01' and '2010-01-01'; -- 7.查询入职日期在'2000-01-01'(包含)到'2010-01-01'(包含)之间 并且性别为女 的员工信息 select * from tb_emp where entrydate between '2000-01-01' and '2010-01-01' and gender = 2; -- 8.查询职位是2,3,4的员工信息 select * from tb_emp where job=2 or job=3 or job=4; -- 只要出现括号里面任意就查询 select * from tb_emp where job in (2,3,4); -- 9.查询姓名为两个字的员工信息 select * from tb_emp where name like '__'; -- 10.查询姓张的员工信息 select * from tb_emp where name like '张%'; -- 11.名字里有无 select * from tb_emp where name like '%无%'; -- %代表任意的占位符,代表张前面可以有0或无数个字符 -- %张代表最后一个字是张 -- %无%代表无前面和后面可有可无字符
分组查询(group by)
聚合函数
-
介绍:将一列数据作为一个整体,进行总体计算。
-
语法:
select
最合适的(字段列表)from
表名;
函数 | 功能 |
---|---|
count | 统计数量 |
max | 最大值 |
min | 最小值 |
avg | 平均值 |
sum | 求和 |
-- 1.统计该企业员工数量 -- 使用count(字段) select count(id) from tb_emp; -- 29 select count(name) from tb_emp;-- 29 -- 注意聚合函数不统计null,job有一个null所以没算 select count(job) from tb_emp;-- 28 -- 使用count(常量) select count(0) from tb_emp;-- 29 -- 使用count(*) 推荐 select count(*) from tb_emp;-- 29 -- 2. 统计该企业最早入职的员工 select min(entrydate) from tb_emp; -- 3.统计在最晚入职的员工 select max(entrydate) from tb_emp; -- 4.统计该企业员工id的平均值 select avg(id) from tb_emp; -- 5.统计该企业员工的id之和 select sum(id) from tb_emp;
分组查询
select 分组字段 [,聚合函数] from 表名 [where 条件] [group by 分组字段] [having 分组后过滤条件]
在 SQL 查询处理中,查询的执行顺序对于理解和优化查询非常关键。对于一个包含 GROUP BY 的查询,执行顺序通常如下: FROM 子句: 首先,SQL 引擎读取 FROM 子句指定的表格。 WHERE 子句: 然后,应用 WHERE 子句中的条件来过滤数据。这一步是在数据进行分组之前执行的,因此它只影响哪些行会被包含在后续的分组和计算中。 GROUP BY 子句: 接着执行 GROUP BY 子句,根据指定的字段将数据分组。只有通过 WHERE 子句的数据才会被分组。 聚合函数: 在数据被分组之后,对每个组应用聚合函数(如 SUM(), AVG(), MAX(), 等)。 HAVING 子句: HAVING 子句用来过滤分组后的结果。它是在所有的聚合函数执行完毕之后才应用的,用于进一步限制哪些分组应该被包括在最终结果中。 SELECT 子句: 最后,SELECT 子句决定了哪些列将被显示在最终的查询结果中。如果使用了聚合函数,只有被 GROUP BY 或聚合函数涵盖的列才能被包括。 ORDER BY 子句: 如果有的话,最后按 ORDER BY 子句指定的顺序排序查询结果。
-- 1.根据性别分组,统计男性和女性员工的数量 - count(*) select gender ,count(*) from tb_emp group by gender; -- 2.先查询入职时间在'2015-01-01'(包含)以前的员工,并对结果根据职位分组,获取员工数量大于等于2的职位 select job,count(*) from tb_emp where entrydate>='2015-01-01' group by job having count(*)>2;
● where与having区别
-
执行的机不同:where是分组之前进行过滤,不满足条件者,不参与分组;而having是分组之后对结果进行过滤。
-
判断条件不同:where不能对聚合函数进行判断,而having可以。
排序查询(order by)
排序方式 ASC:升序(默认) DESC降序
select 分组字段 [,聚合函数] from 表名 [where 条件] [group by 分组字段] [having 分组后过滤条件] [order by 字段1 排序方式1, 字段2 排序方式2 ...];
-- 1.根据入职时间对员工进行升序排序 select * from tb_emp order by entrydate esc; select * from tb_emp order by entrydate; -- 2.根据入职时间对员工进行降序排序 select * from tb_emp order by entrydate desc; -- 3.根据入职时间对员工进行升序排序,入职时间一样,按照更新时间进行降序排序 select * from tb_emp order by entrydate,create_time desc; -- 多字段当第一个字段一样时候,才会进行第二个字段排序
分页查询(limit)
select * from 表名 limit [起始索引,] 查询记录数
-- 1.从起始索引0开始查询员工数据,每页展示5条记录 select * from tb_emp limit 0,5; -- 查询起始索引=(页数-1)*每页展示个数 -- 2.查询第1页员工数据,每页展示5条 select * from tb_emp limit 0,5; select * from tb_emp limit 5;-- 查询第一页可以省略起始索引 -- 起始索引默认从0开始 -- 3.查询第2页员工数据,每页展示5条 select * from tb_emp limit 5,5; -- 4.查询第3页员工数据,每页展示5条 select * from tb_emp limit 10,5; -- 查询起始索引=(页数-1)*每页展示个数
查询关键字运行和运行顺序
SELECT 分组字段 [, 聚合函数] FROM 表名 [WHERE 条件] [GROUP BY 分组字段] [HAVING 分组后过滤条件] [ORDER BY 字段1 排序方式1, 字段2 排序方式2 ...] LIMIT 指定行数;
-
FROM 子句:
-
这是查询处理的第一步,SQL 引擎首先从指定的表中读取数据。这包括对所有相关表的访问,如果涉及到多个表,可能包括连接操作。
-
-
WHERE 子句:
-
接下来,应用
WHERE
子句的过滤条件。这个步骤在数据被进一步处理前,对原始数据进行过滤。只有满足WHERE
条件的行才会被包括在后续的操作中。
-
-
GROUP BY 子句:
-
然后,执行
GROUP BY
子句,按照指定的列或表达式对数据进行分组。这一步是在WHERE
过滤后进行的,确保只对符合条件的数据进行分组。
-
-
聚合函数:
-
对每个分组执行聚合函数(如
COUNT()
,SUM()
,AVG()
等)。这些函数计算分组后每个组的统计信息。
-
-
HAVING 子句:
-
如果有
HAVING
子句,它将在聚合函数计算之后应用。HAVING
子句用于过滤分组的结果,类似于WHERE
子句,但它是在聚合后对组进行过滤。
-
-
SELECT 子句:
-
此时,选择需要输出的列。这些列可以是表中的列、聚合的结果或表达式的结果。如果使用
SELECT *
,则选择所有列。
-
-
ORDER BY 子句:
-
如果查询中包含
ORDER BY
子句,将在最后对结果集进行排序。这一步确保了返回的数据按照指定的列和排序方式(升序或降序)排序。
-
-
LIMIT 子句:
-
最后,
LIMIT
子句用于限制返回的记录数,通常用在ORDER BY
之后,以确保从排序后的结果集中选择顶部或底部的指定数量的行。
-
多表设计
一对多
-
根据页面原型及需求文档,完成部门及员工模块的表结构设计 。
-
一个部门对应多个员工
-
一对多关系实现:在数据库表中多的一方,添加字段,来关联一的一方的主键。
外键约束(不建议).建议使用代码逻辑进行绑定
创建表的指令 create table 表名( 字段名 数据类型, ... [constraint] [外键名称] foreign key(外键字段名) references 主表(字段名) ); 修改表添加外键的指令 alter table 表名 add constraint 外键名称 foreign key(外键字段名) references 主表(字段名);
一对一
-
案例:用户与身份证信息的关系
-
关系:一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他字段放在另一张表中,以提升操作效率。
-
实现:在任意一方加入外键,关联另一方的主键,并且设置外键为唯一的(unique)
多对多
多对多 |
---|
案例: 学生 与 课程的关系 |
关系: 一个学生可以选修多门课程, 一门课程也可以供多个学生选择 |
实现: 建立第三张中间表, 中间表至少包含两个外键, 分别关联两方主键 |
多表查询
-
多表查询:指从多张表中查询数据
-
笛卡尔积:笛卡尔乘积是指在数学中,两个集合(A集合和B集合)的所有组合情况。
-- 多表查询 select * from tb_emp,tb_dept; -- tb_emp只有17个,tb_dept只有5个最后却输出了85行数据 -- 直接两个查询会出现笛卡尔积 -- tb_emp和tb_dept每一行数据相互结合,17*5 -- 如何解决,我最终要查询员工和所属部门信息 select * from tb_emp,tb_dept where tb_emp.dept_id=tb_dept.id; -- 最终结果16条,只查询了员工信息中dept_id和部门id相等的数据 -- 也就是两个表交叉的数据
连接查询
内连接:相当于查询A、B交集部分数据 b) 外连接:
-
左外连接:查询左表所有数据(包括两张表交集部分数据)
-
右外连接:查询右表所有数据(包括两张表交集部分数据)
内连接
相当于查询A与B的交集
隐士内连接: select 字段列表 from 表1,表2 where 条件...; 显示内连接: select 字段列表 from 表1 [inner] join 表2 on 连接条件...;
-- 内连接 -- 1.查询员工姓名和所属部门。由于有的员工没有部门,有的部门没有员工。所以这一部分无法查询 -- A。隐士内连接 select tb_emp.name,tb_dept.name from tb_emp,tb_dept where tb_emp.dept_id=tb_dept.id; -- 起别名 select e.name,d.name from tb_emp e,tb_dept d where e.dept_id=d.id; -- B.显示内连接 select e.name,d.name from tb_emp e inner join tb_dept d on e.dept_id = d.id; -- inner可以省略不写 select e.name,d.name from tb_emp e join tb_dept d on e.dept_id = d.id;
外连接
-
左外连接:查询左表所有数据(包括两张表交集数据)
-
右外连接:查询右表所有数据(包括两张表交集数据)
左外连接 select 字段列表 from 表1 left [outer] join 表2 on 连接条件; 右外连接 select 字段列表 from 表1 right [outer] join 表2 on 连接条件;
-- A查询所有的员工的姓名,和对应的部门名称(左外连接) select e.name,d.name from tb_emp e left outer join tb_dept d on e.dept_id = d.id; -- outer可以省略不写 select e.name,d.name from tb_emp e left join tb_dept d on e.dept_id = d.id; -- B查询所有部门的名称,和对应的员工名称(右外连接) select e.name,d.name from tb_emp e right join tb_dept d on e.dept_id = d.id; -- 通过左外连接方式实现 select e.name,d.name from tb_dept d left join tb_emp e on e.dept_id = d.id;
子查询
sql语句中嵌套select语句,称为嵌套查询,又称子查询
select * from 表1 where column1=(select column1 from 表2); 把查询条件更改为另一个查询的结果
子查询外部的语句可以是insert/update/delete/select任意一个。
标量子查询
子查询返回的结果是一个值
-- 标量子查询 -- A查询"教研部"的所有员工信息 -- a要先查询教研部的id是什么 select id from tb_dept where name='教研部'; -- b再通过教研部的id查询教研部的员工信息 select * from tb_emp where dept_id=2; -- 合并上述便是子查询 select * from tb_emp where dept_id=(select id from tb_dept where name = '教研部');
列子查询
子查询返回的结果为一列
-- 列子查询 -- A.查询'教研部'和'咨询部'的所有员工信息 -- a.查询'教研部'和'咨询部'的部门id select id from tb_dept where name in ('教研部','咨询部'); select id from tb_dept where name='教研部' or name='咨询部'; -- 根据'教研部'和'咨询部'的部门id查询员工信息 select * from tb_emp where dept_id in (select id from tb_dept where name in ('教研部','咨询部'));
行子查询
子查询返回的结果为一行
-- A.查询与‘韦一笑’的入职日期及职位都相同的员工信息 -- a.查询‘韦一笑’的入职日期及职位 select entrydate,job from tb_emp where name='韦一笑'; -- b.查询与入职日期及职位都相同的员工信息 select * from tb_emp where (entrydate,job)=(select entrydate,job from tb_emp where name='韦一笑');
表子查询
子查询返回结果为多行多表
-- 表子查询 -- A. 查询入职日期是'2006-01-01'之后的员工信息,及其部门名称 -- a. 查询入职日期是'2006-01-01'之后的员工信息 select * from tb_emp where entrydate>'2006-01-01';-- 输出为一个表 -- b.查询这部分员工信息及其部门名称 select e.name,d.name from (select * from tb_emp where entrydate>'2006-01-01') e,tb_dept d where e.dept_id=d.id;
事务
-- 案例 -- 学工部整个部门解散了,该部门下所有员工都需要被删除 -- 删除学工部 delete from tb_dept where id=1; -- 删除学工部员工 delete from tb_emp where dept_id=1; -- 但是如果部门删除成功,员工删除失败就会导致数据不一致了。 -- 如何让它们删除成功就一起删除,失败就都不删除呢?
事务 是一组操作的集合,它是一个不可分割的工作单位。事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作 要么同时成功,要么同时失败.
在上述代码中,默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐士的提交事务。
事务控制 开启事务:start transaction;/begin; 提交事务:commit; 回滚事务:rollback
-- 开启事务 start transaction; -- 删除学工部 delete from tb_dept where id=1; -- 删除学工部员工 delete from tb_emp where dept_id=1; -- 提交事务 commit; -- 回滚事务 rollback; -- 在数据库中的事物启动就相当于在当前开启一个副本,后续操作在副本上执行,如果在副本操作成功了就提交,失败了就放弃修改也就是rollback。
事务的操作过程
-
启动事务(Begin Transaction):这标志着事务的开始。
-
执行操作:在事务内执行一系列数据库操作,这些操作作为一个整体单元处理。
-
提交(Commit):如果所有操作成功执行,事务被提交,所有数据修改被永久保存。
-
回滚(Rollback):如果操作中有任何一个失败,事务将回滚到开始状态,撤销所有未提交的修改。
事务四大特性
在数据库中,事务通常遵循ACID原则,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability):
-
原子性(Atomicity):确保事务中的所有操作要么全部完成,要么全部不完成,没有中间状态。如果事务中的任何操作失败,整个事务都会回滚(rollback),之前的操作也会被撤销。
-
一致性(Consistency):事务必须将数据库从一个一致性状态转变到另一个一致性状态。事务开始和完成时,所有的数据库规则必须应用于事务的修改,以保持数据库的完整性。
-
隔离性(Isolation):事务的执行不应受到其他事务的干扰。多个事务同时进行时,一个事务的中间状态不应该被其他事务看到。这通常通过锁定机制或时间戳等方法实现。
-
持久性(Durability):一旦事务提交,其结果就是永久的,即使系统发生故障也不会丢失。这通常通过将事务日志记录在非易失性存储介质上实现。
数据库优化
索引
索引优缺点
优点:
-
提高数据查询的效率,降低数据库的IO成本。
-
通过索引列对数据进行排序,降低数据排序的成本,降低CPU消耗。
缺点:
-
索引会占用存储空间。
-
索引大大提高了查询效率,同时却也降低了insert、update、delete的效率。
创建索引语法
-- 创建索引 create [unique] index 索引名 on 表名(字段名,...); -- 查看索引 show index from 表名; -- 删除索引 drop index 索引名 on 表名;
注意
主键字段,在建表的时候。会自动创建主键索引.而且主键索引是效率最高的。
添加唯一约束时,数据库实际上就是添加了唯一索引。
-- 创建 tb_emp表的name字段建立索引 create index idx_emp_name on tb_emp(name); -- 查询 tb_emp表的索引信息 show index from tb_emp; -- 删除tb_emp表的name字段的索引 drop index idx_emp_name on tb_emp;
索引原理
索引底层为b+树。