https://www.bilibili.com/video/BV12b411K7Zu
https://www.bilibili.com/video/BV1Vy4y1z7EX
常用的SQL命令
select * from stu;
select count(*) from stu where username='zhangsan' and password='123456';#进行登陆验证
select `name` from `stu`;#加上点号不会出现和关键字重合的问题
select * from stu where sex='男';#注意字符型要加单引号或双引号
select name as '名字' from stu;#或者是不写as写成空格
select concat(id,name) from stu;#将两列合并为一列
select distinct id from stu;#去除重复元素
select ifnull(name,'无名氏') from stu;#起别名,如果是null则返回无名氏
select name from stu where id=1;#查询id为1的用户
select name from stu where id>=10 and id <=100;#查询id在[10,100]的名称
select name from stu where id between 10 and 100;#作用同上
select id from stu where name like '_e%'#_代表单个字符,%代表大于等于0个字符
select name from stu where id in (1,2,3);#查询id在1,2,3的名称
select * from stu where name is null;#is not null
select * from stu where id>10 order by id asc,name desc;#id升序,名字降序排列
SQL语句的分类
- DDL(Data Definition Language):数据定义语言,用来定义数据库对象:库、表、列等;
DML(Data Manipulation Language)
:数据操作语言,用来定义数据库记录(数据);- DCL(Data Control Language):数据控制语言,用来定义访问权限和安全级别;
DQL(Data Query Language)
:数据查询语言,用来查询记录(数据)。
我们写的语句将近80%是查询语句
基本数据类型
数值类型
类型 | 大小 | 范围(无符号) | 用途 |
---|---|---|---|
TINYINT | 1 Bytes | (0,255) | 小整数值 |
SMALLINT | 2 Bytes | (0,65 535) | 大整数值 |
MEDIUMINT | 3 Bytes | (0,16 777 215) | 大整数值 |
INT或INTEGER | 4 Bytes | (0,4 294 967 295) | 大整数值 |
BIGINT | 8 Bytes | (0,18 446 744 073 709 551 615) | 极大整数值 |
FLOAT | 4 Bytes | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 单精度 浮点数值 |
DOUBLE | 8 Bytes | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 双精度 浮点数值 |
DECIMAL | 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 | 依赖于M和D的值 | 小数值 |
时间类型
类型 | 大小 ( bytes) | 范围 | 格式 | 用途 |
---|---|---|---|---|
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:00/2038结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 | YYYYMMDD HHMMSS | 混合日期和时间值,时间戳 |
字符串类型
类型 | 大小 | 用途 |
---|---|---|
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(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符。
DQL:查询数据
DQL就是数据查询语言,数据库执行DQL语句不会对数据进行改变,而是让数据库发送结果集给客户端。
语法:
select
selection_list /*要查询的列名称*/
from
table_list /*要查询的表名称*/
where
condition /*行条件*/
group by
grouping_columns /*对结果分组*/
having
condition /*分组后的行条件*/
order by
sorting_columns /*对结果分组*/
limit
offset_start, row_count /*结果限定*/
简单查询
基础查询
select column1,column2,column3 from table;
select * from table;
select后面可以跟多个字段
起别名as
select name as '用户名' from stu;#单引号双引号都可以
select name '用户名' from stu;
可以写as或者加空格就OK了,注意字符要加引号的,单引号双引号都可以
将多列拼为一列concat
select concat(id,'-',name) as name from stu;
concat可以将多列拼在一起,加个-就是在两列之间加个-,最后返回为一个数据
去除重复元素distinct
select distinct id from stu;
将返回的id去除重复元素之后再返回
查看表的结构desc
desc stu;
/*或者*/
show columns from stu;
处理null值ifnull
select ifnull(name,'无名氏') from stu;
如果name是null则返回无名氏
条件查询where
select 字段
from 表明
where 筛选条件
执行顺序:from、where、select
关系运算符
> 、<、>=、<=、=、!=、<>
select name from stu where id=10;
select name from stu where id>=10;
逻辑运算符
and、or、not、&&、||、!
select name from stu where id>=10 and id<=100;
模糊查询
like
一般用于字符串的查询,通常和通配符一起使用
通配符:_
代表任意单个字符,%
代表任意多个字符(大于等于0)
select * from stu where name like '%e';#查询以e结尾的名称
转义字符:可以使用\
,或者自定义转义字符
select * from stu where name like '_$_' escape '$';指定¥为转义字符
in、not in
select * from stu where id in (1,2,3,4,5);
查找符合id在这个集合中的数据
between and 、not between and
select * from stu where id is null;
查询id为空的数据
is只能判断是否为null,写成is 0报错。
=只能判断简单数值,写成=null则为空。
<=>安全等于号技能判断null也能判断数值
排序查询(默认升序)
select 查询列表
from 表名
[where 筛选条件]
order by 排序列表;
执行顺序:表名、筛选条件、查询列表、排序列表
特点:
- 排序列表可以是单个字段、多个字段、表达式、函数、常量(列次序)以及以上的组合
- 升序:通过asc(ascend)
- 降序:通过desc(decrease)
- 也可以通过自己起的别名进行排序
基础用法
# 根据id升序
select * from stu order by id;
# 将返回到的结果根据id升序排列
select * from stu order by length(name);
# 现根据id升序,再根据name降序
select * from stu order by id asc,name desc;
不能在where中使用select的别名
根据sql执行的顺序优先级可以知道,先执行select字句,再执行order by字句,因此,在select字句中起的别名可以在order by字句中使用。但是where的优先级高于select,因此,where字句不能使用
使用列次序排列
select * from stu order by 2;
根据第二列升序排列
常见函数
直介绍常用的,如果感觉不全面可以自行百度
字符函数
函数 | 功能 | 示例 | 示例结果 |
---|---|---|---|
concat | 拼接字符串 | select concat(id,’-’,name) 信息 from stu; | 最后返回的结果是id-name的形式,即:1-帅龙 |
length | 获取字节长度 | select length(‘I love 帅帅龙’); | 返回16=7+3*3,utf-8编码规范中,一个汉字占据3个字节 |
char_length | 获取字符长度 | select char_length(‘I love 帅帅龙’); | 返回10,返回的就是len,一个汉字也是1,一个空格也是1 |
sub_str | 截取指定字串 | sub_str(‘我爱帅帅龙’,2,2) | 返回爱帅,第一个参数是需要处理二点字段,第二个参数是起始的index(从1开始),第三个参数是截取的长度,不写默认到最后 |
left/right: | 截取左/右指定长度字串 | select left(‘我爱帅帅龙’,2); | 返回我爱 |
trim | 去除两端字符 | select trim(’ 我爱帅帅龙 '); | 返回我爱帅龙 |
trim | 去除两端字符 | select trim(‘x’ from ‘xxaa我爱帅帅龙aa’); | 返回aa我爱帅龙aa |
lpad/rpad | 左/右填充指定字符,第一个参数是填充的字段,第二个参数是填充的个数,第三个参数是填充的字符 | select lpad(‘我爱帅帅龙’,10,‘x’); | 返回xxxxxxxxxx我爱帅帅龙 |
upper/lower | 变大写/小写 | select upper(‘love’); | 返回LOVE |
strcmp | 比较字符大小 | select strcmp(‘love’,‘abc’); | 返回love |
instr | 获取字串首次出现的索引 | select instr(‘我爱帅帅龙’,‘帅’); | 返回3 |
数学函数
- abs()取绝对值
- floor()向下取整
- ceil()向上取整
- round(数字,四舍五入保留的位数)
- truncate(数字,截取后剩下的长度)
- %取余
select abs(money) from stu;
日期函数
- now()获取当前日期+时间
- curdate()获取当前日期
- curdtime()获取当前时间
- datediff(a,b)两时间做差,前面减去后面,返回天数
- date_format将日期转为指定格式字符串
select date_format('1998-7-16','%Y年%m月%d日 %H时%i分%s秒');
- str_to_date字符串转为时间
select str_to_date('7/16 1998','%m/%d %Y');
聚合函数
- sum()
- avg()
- max()
- min()
- count(字段)统计该字段非null的有几个
select sum(money) from stu;
聚合函数常常和分组查询连用
流程控制函数
if语句
格式
select if(条件,成立的结果,不成立的结果);
示例
select if(money if null,0,money) from stu;
如果money是null就返回0,不是null就返回原本数值
case语句
格式
case 表达式
when 值1 then 结果1
when 值2 then 结果2
...
else 结果n
end
别忘记最后的end
case组合的类if-else结构
格式
case
when 判断1 then 结果1
when 判断2 then 结果2
...
else 结果n
end
别忘记最后的end
分组查询
格式:
select 列表/分组函数
from 表明
where 条件
group by 分组列表;
示例
计算不用类别学生的金钱总额,会先分组,然后求和
select sum(money) from stu group by `type`;
计算不同类型的人数,会先分组,然后计数
select count(*) from stu group by `type`;
当根据多个字段进行分组的时候,只有当这几个字段都相同的时候,才分为一组,下面代码就是当groupid和type都相同的才分为一组
select count(*) from stu group by `type`,`group_id`;
连接(sql99语法)
内连接(查询交集部分)
等值连接(连接条件是固定值,两值相等筛选出来)
格式:inner可以省略
select 字段
from 表1 别名1
[inner] join 表2 别名2
on 连接条件
where 筛选条件
group by 分组条件
having 分组后筛选
order by 排序条件
示例:首先得到id相同的数据,然后根据city分组
select count(*) 部门个数,l.city
from departent d
join location l
on d.location=l.location
group by l.city
非等值连接(连接条件不是固定值,满足条件的筛选出来)
和等值连接差别不是很大,只不过是连接条件有所改动
select count(*) 个数,grade
from employees e
join sal_grade g
on e.salary between g.min_salary and max_salary
group by g.grade
自连接(自己和自己连接)
员工和领导的名字一一对应
select e.name,m.name
from employees e
join employees m
on e.manange_id=m.employees.id
外连接(一般查A表有B表没有)
左外连接(左连接)、右外连接(右连接)
大家想一下,什么时候用内连接呢?是表a和表b的数据都存在的时候才可以,那现在有如下需求,查出表a中没有女朋友的个数,此时就需要使用到外连接了
外连接分主表和从表,查询结果是主表的所有记录,用where进行筛选结果,如果从表中有和主表对应的数据则返回该数据,否则返回null,但如果是内连接的话就不会返回null
- 在左外连接中,left join左边的是主表
- 在右外连接中,right join右边的是主表
格式:
select count(*)
from 表1 别名1
left/right outer join 表2 别名2
on 连接条件
where 筛选条件
如果写left则表1为主表,如果写right则表2为主表,通常写left,即主表在上
全外连接(MySQL不支持)
全外连接 = 内连接的结果 + 表1中有但表2没有的 + 表2中有但表1没有的
交叉连接(求了个笛卡尔乘积)
就是相当于求了个笛卡尔乘积,4*11 = 44
select b.*,bo.*
form beauty b
cross join boys bo
子查询(其他语句中的se1ect语句)
出现在其他语句(不仅仅是select语句)中的se1ect语句,称为子查询或内查询。一个语句中嵌套了完整的select语句,被嵌套的成为子查询或内查询,外面的为主查询或外查询
根据子查询的位置可以分为这几种:
- select后面:要求结果为单行单列,用的不多
- from后面:可以为多行多列,也就是咱们平时的数据表格式
- where或having后面:用的最多,子查询结果必须为单列
- exists后面:相关子查询,结果为单列
子查询特点:
- 放在条件右侧,大于小于右侧
- 子查询一般放在括号里
- 单行子查询配合单行操作符符号:>、<、=、>=、<=
- 多行子查询配合多行子查询符号:any/some、all、in
单行子查询
查询和zrl相同部门的员工姓名和工资
select name,salary
from employees
where department_id=(
select department_id
from employees
where name='zrl'
);
多行子查询
- in:在…中
- any/some:满足大于或小于其中一个即可
- all:要大于或小于全部数值
在employee中找到薪水大于stu表中任意一人的薪水,即可以优化为大于其中的最小值
select *
from employees
where maoney>any(
select money
from stu
);
分页查询
我以前以为只有使用分页工具才可以返回Page对象的,原来可以直接查啊,真滴舒服
格式:
select
from
join
on
where
group by
having
order by
limit 起始索引(从0开始,不写的话默认为0),需要显示的条目数
顺序是:from、join、on、where、group by、having、select、limit
联合查询(列拼接在一起)
联合查询可以理解为一种简化的查询方式,下面两条SQL等价
SELECT FROM employees WHERE email LIKE '%a%' OR department_id>90;
SELECT* FROM employees WHERE email LIKE
UNION
SELECT FROM employees WHERE department_id>90;
当查询的结果来自多张表的时候,并且多张表无关联,需要使用联合查询把几列竖向拼接在一起,注意多条多列数据的列数必须匹配,谁写在第一个最后显示的字段名就是什么,使用union会自动去重,如果想保留重复数据可以使用union all
select id,cname,csex from t_ca where csex='男'
union
select t_id,t_name,t_gender from t_ua where t_gender='male';
DML:增删改数据
insert插入数据
插入一条数据
#当插入一条数据的时候可以使用value,但是为了好记就记成values吧,因为插入多条数据使用calues
insert into stu(字段1,字段2,字段3...) values(值1,值2,值3...);
插入多条数据
insert into stu(字段1,字段2,字段3...) values
(值1,值2,值3...),(值1,值2,值3...),(值1,值2,值3...);
特点
- 如果写了字段,那么顺序没有要求,但是字段和值要一一对应,同时值要满足约束要求
- 如果不写字段,那么数据就和表结构的字段顺序一一对应,格式如下
insert into stu values(值1,值2,值3...);
- 数值型不用引号,但是非数值型需要引号,例如字符、时间等
- 插入可空约束数据,但是没数据,要么不写这个字段,要么字段对应的值写null
- 插入有默认数值约束数据,要么不写这个字段,要么字段对应的值写default
- 插入有递增约束数据,要么不写这个字段,要么字段对应的值写null
delete删除数据
两种方式
delete from 表名 where 条件;#写了where就只删除一条,否则全部删除
truncate table 表名;#删除全部数据
delete与truncate的区别:
- delete可以写where条件
- delete可以返回受影响行数
- delete可以支持事务回滚
- delete删除数据后,自增约束的字段从断点继续自增,truncate删除数据后,自增约束的字段从0开始自增
- truncate效率高,但是更象DDL,管理数据表的语言
updates更新数据
updates 表名 set name='张三' where id=1;
多表修改也是可以的,但是挺麻烦,也不常用,等遇到了再补充吧,现在先不写了
DDL:操作数据库、表
库的管理
创建库
creat database test;
creat database if not exists test;#写这个容错性好一点
删除库
drop database test;
drop database if exists test;#这样写容错性好一点
表的管理
常见约束
- PRIMARY KEY主键
- AUTO_INCREMENT自增
- NOT NULL非空
- DEFAULT默认值
- UNIQUE唯一
- FOREIGN KEY外键
- CHECK检查,mysql不支持
注:
- 设置了自增,要么插入数据时候不操作这个字符段,要么写null,如果填入具体数值则不能自增
- 主键按只能有一个,设置了很多的时候视为一组,只有这几条数据同时存在于一条已存放的数据的时候才算主键重复
- 唯一键约束可以有多个
- 如果设置外键必须满足两个要求:主表关联列必须为主键;两列的数据类型相同
创建表
creat table if not exists stuinfo(
stuid int primary key,
stuname varchar(20) unique not null,
gender char default '男',
email varchar(20) not null,
age int check(age between 0 and 90),#mysql就算写了也不给你检查
major_id int,
#外键约束要放在最后单独写
foreign key (major_id) references major(id)#major表的id字段
);
修改表
alter table 表名 add|modify|change|drop column 字段;
功能 | 示例 |
---|---|
修改表名 | alter table stu rename to studata; |
添加字段 | alter table stu add column id int primary key; |
修改字段名 | alter table stu change brithday birthday_data date; |
修改字段类型 | alter table stu modify column birthday timestamp; |
删除字段 | alter table stu drop column birthday; |
复制表
仅复制表的结构
creat table new_table like old_table;
复制表的结构和数据
creat table new_table select * from old_table;
主键
什么类型适合做主键
不建议使用 varchar 来做主键,因为MYSQL数据库,因为主键默认有个排序,varchar类型会严重影响效率,主键值一般都是数字或定长的字符
主键的分类
主键除了单一主键和复合主键之外,还可以分为自然主键和业务主键:
- 自然主键:主键值是一个自然数,和业务没关系
- 业务主键:主键值和业务紧密关联,例如拿银行卡账号做主键值。这就是业务主键!
在实际开发中使用业务主键多,自然主键使用比较多,因为主键只要做到不重复就行,不需要有意义
业务主键不好,因为主键一旦和业务挂钩,那么当业务发生变动的时候,可能会影响到主键值,所以业务主键不建议使用,尽量使用自然主键
外键
涉及到的相关术语
外键约束涉及到的相关术语:
- 外键约束:一种约束( foreign key)
- 外键字段:该字段上添加了外键约束
- 外键值:外键字段当中的每一个值
设置外键的要求
如果设置外键必须满足两个要求:
- 主表关联列必须为主键
- 两列的数据类型相同
创建一个外键
为了保证表引用(子表)的数据id是有效的,因此要添加外键约束,如果不加这个约束的话。这个值可能会瞎写,不能保证正确性,加上了只能引用指定外键的数据
creat table if not exists stuinfo(
stuid int primary key,
stuname varchar(20) unique not null,
gender char default '男',
email varchar(20) not null,
age int check(age between 0 and 90),#mysql就算写了也不给你检查
major_id int,
#外键约束要放在最后单独写
foreign key (major_id) references major(id)#major表的id字段
);
操作父、子表的顺序
删除表的顺序:先删子,再删父
创建表的顺序:先创建父,再创建子
删除数据的顺序:先删子,再删父
插入数据的顺序:先插入父,再插入子
存储引擎
InnoDB存储引擎
这是mysql默认的存储引擎,同时也是一个重量级的存储引擎。
InnoDB支持事务,支持数据库崩溃后自动恢复机制。
InnoDB存储引擎最主要的特点是:非常安全。
它管理的表具有下列主要特征:
- 每个 InnoDB 表在数据库目录中以.frm 格式文件表示
- InnoDB 表空间 tablespace 被用于存储表的内容(表空间是一个逻辑名称。表空间存储数据+索引。)
- 提供一组用来记录事务性活动的日志文件
- 用 COMMIT(提交)、SAVEPOINT 及ROLLBACK(回滚)支持事务处理
- 提供全 ACID 兼容
- 在 MySQL 服务器崩溃后提供自动恢复
- 多版本(MVCC)和行级锁定
- 支持外键及引用的完整性,包括级联删除和更新
InnoDB最大的特点就是支持事务,以保证数据的安全。
效率不是很高,并且也不能压缩,不能转换为只读,不能很好的节省存储空间。
MEMORY存储引擎
MEMORY 存储引擎以前被称为HEAP 引擎。使用 MEMORY 存储引擎的表,其数据存储在内存中,且行的长度固定,这两个特点使得 MEMORY 存储引擎非常快。
MEMORY 存储引擎管理的表具有下列特征:
- 在数据库目录内,每个表均以.frm 格式的文件表示。
- 表数据及索引被存储在内存中。(目的就是快,查询快!)
- 表级锁机制。
- 不能包含 TEXT 或 BLOB 字段。
MEMORY引擎优点:查询效率是最高的。不需要和硬盘交互。
MEMORY引擎缺点:不安全,关机之后数据消失。因为数据和索引都是在内存当中。
事务
什么是事务
事务对应的英语单词是:transaction,只有DML语句(增删改)才会有事务这一说,其它语句和事务无关!!!
一个事务其实就是一个完整的业务逻辑,即一件事,是一个最小的工作单元,不可再分。一个事务由一个或多个sql组成,要么所有sql全部执行成功,要么全部都执行不成功。如果一个事务只有一条DML语句,那事务没有存在的必要
事务的分类
- 隐式事务
例如update、delete、insert语句 - 显式事务
分为五步,具体参看下面操作
提交事务、回滚事务
-
提交事务:commit; 语句
-
回滚事务:rollback; 语句(回滚永远都是只能回滚到上一次的提交点!)
---------------------------------回滚事务----------------------------------------
# 取消隐式事务自动开启,可有可无
mysql> set autocommit=0;
mysql> start transaction;
...
mysql> rollback;
# 恢复默认设置,可有可无
mysql> set autocommit=1;
---------------------------------提交事务----------------------------------------
# 取消隐式事务自动开启,可有可无
mysql> set autocommit=0;
mysql> start transaction;
...
mysql> commit;
mysql> rollback;
# 恢复默认设置,可有可无
mysql> set autocommit=1;
事务的四大特性(ACID)
- 原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。
- 一致性(Consistency):事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
- 隔离性(Isolation):隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。
- 持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。
事务的隔离性
A教室和B教室中间有一道墙,这道墙可以很厚,也可以很薄。这就是事务的隔离级别,这道墙越厚,表示隔离级别就越高。
事务和事务之间有四个隔离级别:
-
读未提交:read uncommitted(最低的隔离级别)《没有提交就读到了》
- 事务A可以读取到事务B未提交的数据。这种隔离级别存在的问题就是脏读现象!(Dirty Read),我们称读到了脏数据。这种隔离级别一般都是理论上的,大多数的数据库隔离级别都是二档起步!
-
读已提交:read committed《提交之后才能读到》
- 事务A只能读取到事务B提交之后的数据,这种隔离级别解决了解决了脏读的现象。这种隔离级别存在的问题是不可重复读取数据。
- 什么是不可重复读取数据呢?
在事务开启之后,第一次读到的数据是3条,当前事务还没有结束,可能第二次再读取的时候,读到的数据是4条,3不等于4称为不可重复读取。这种隔离级别是比较真实的数据,每一次读到的数据是绝对的真实。oracle数据库默认的隔离级别是:read committed
-
可重复读:repeatable read《提交之后也读不到,永远读取的都是刚开启事务时的数据》
-
事务A开启之后,不管是多久,每一次在事务A中读取到的数据都是一致的。即使事务B将数据已经修改,并且提交了,事务A读取到的数据还是没有发生改变,这就是可重复读。可重复读解决了解决了不可重复读取数据,但可重复读可能会出现幻影读,每一次读取到的数据都是幻象。不够真实!例如早晨9点开始开启了事务,只要事务不结束,到晚上9点,读到的数据还是那样!读到的是假象,不够绝对的真实。
mysql中默认的事务隔离级别就是这个!!!!!!!!!!!
-
-
序列化/串行化:serializable(最高的隔离级别)
- 这是最高隔离级别,效率最低。解决了所有的问题。这种隔离级别表示事务排队,不能并发synchronized,线程同步(事务同步)每一次读取到的数据都是最真实的,并且效率是最低的。
事务的使用
Spring Boot实现事务特别特别简单,没有多余操作,类上添加一个注解@Transactional搞定
索引
什么是索引
索引是在数据库表的字段上添加的,是为了提高查询效率存在的一种机制。一张表的一个字段可以添加一个索引,当然,多个字段联合起来也可以添加索引。索引相当于一本书的目录,是为了缩小扫描范围而存在的一种机制。
索引的实现原理
- 提醒1:在任何数据库当中主键上都会自动添加索引对象,id字段上自动有索引,
因为id是PK。另外在mysql当中,一个字段上如果有unique约束的话,也会自动
创建索引对象。 - 提醒2:在任何数据库当中,任何一张表的任何一条记录在硬盘存储上都有
一个硬盘的物理存储编号。 - 提醒3:在mysql当中,索引是一个单独的对象,不同的存储引擎以不同的形式
存在,在MyISAM存储引擎中,索引存储在一个.MYI文件中。在InnoDB存储引擎中
索引存储在一个逻辑名称叫做tablespace的当中。在MEMORY存储引擎当中索引
被存储在内存当中。不管索引存储在哪里,索引在mysql当中都是一个树的形式
存在。(自平衡二叉树:B-Tree)
什么条件下会给字段添加索引呢
在mysql当中,主键上,以及unique字段上都会自动添加索引的!!!!
- 条件1:数据量庞大(到底有多么庞大算庞大,这个需要测试,因为每一个硬件环境不同)
- 条件2:该字段经常出现在where的后面,以条件的形式存在,也就是说这个字段总是被扫描。
- 条件3:该字段很少的DML(insert delete update)操作。(因为DML之后,索引需要重新排序。)
建议不要随意添加索引,因为索引也是需要维护的,太多的话反而会降低系统的性能。建议通过主键查询,建议通过unique约束的字段进行查询,效率是比较高的。
注意:唯一性比较弱的字段上添加索引用处不大。
索引创建与删除
创建索引:给emp表的ename字段添加索引,起名:emp_ename_index
create index emp_ename_index on emp(ename);
删除索引:将emp表上的emp_ename_index索引对象删除。
drop index emp_ename_index on emp;
索引失效
- 查询语句中使用LIKE关键字时,%在第一个位置
- 查询语句中使用多列索引(复合索引),在表的多个字段上创建一个索引,只有查询条件中使用了这些字段中的第一个字段,索引才会被使用
- 查询语句只有 OR 关键字时,如果 OR 前后的两个条件的列都是索引,那么查询中将使用索引。如果 OR 前后有一个条件的列不是索引,那么查询中将不使用索引。
- 在where当中索引列参加了运算,索引失效。
- 在where当中索引列使用了函数
- 后面深入学习MySQL的时候再补充哈…
数据库三种范式
https://www.bilibili.com/video/BV1Vy4y1z7EX?p=127
- 第一范式(最重要):要求任何一张表必须有主键,每字段原子性不可再分
- 第二范式:建立在第一范式的基础之上,要求所有非主键字段完全依赖主键,不要产生部分依赖(例如老师编号和学生编号是复合主键,老师依赖老师编号、学生依赖学生编号),这是多对多的情况,可以用三张表表示两者关系(学生表、教师表、学生教师关系),但是一对多就没事,只需要判断和主键的依赖关系即可。多对多,三张表,关系表加两个外键
- 第三范式:建立在第二范式的基础之上,要求所有非主键字段直接依赖主键,不要产生传递依赖(一年一班依赖01,01依赖1001,拆分成两张表:学生表、班级表)。一对多,两张表,
对多
的表加外键
注意:三范式是面试官经常问的,所以一定要熟记在心!
设计数据库表的时候,按照以上的范式进行,可以避免表中数据的冗余,空间的浪费
视图
http://c.biancheng.net/mysql/80/
- 视图是一张虚拟表,将复杂的SQL封装,让其可重用同时可以简化开发
- 索引是一种特殊的数据库结构,由数据表中的一列或多列组合而成,可以用来快速查询数据表中有某一特定值的记录。
存储过程、游标、触发器
http://c.biancheng.net/mysql/85/
- 存储过程是数据库中的一个重要功能,存储过程可以用来转换数据、数据迁移、制作报表,它类似于编程语言,一次执行成功,就可以随时被调用,完成指定的功能操作。
- 在 MySQL 中,存储过程或函数中的查询有时会返回多条记录,而使用简单的 SELECT 语句,没有办法得到第一行、下一行或前十行的数据,这时可以使用游标来逐条读取查询结果集中的记录。游标在部分资料中也被称为光标。
- MySQL 的触发器和存储过程一样,都是嵌入到 MySQL 中的一段程序,是 MySQL 中管理数据的有力工具。不同的是执行存储过程要使用 CALL 语句来调用,而触发器的执行不需要使用 CALL 语句来调用,也不需要手工启动,而是通过对数据表的相关操作来触发、激活从而实现执行。比如当对 student 表进行操作(INSERT,DELETE 或 UPDATE)时就会激活它执行。
全文检索
MySQL全文检索是利用查询关键字和查询列内容之间的相关度进行检索,可以利用全文索引来提高匹配的速度。
innodb不支持全文检索