从SQL到mysql学习笔记查漏补缺

简单的 通用的 常写的 均省略,以下仅作查漏补缺,不适合初学者

基础

DDL 数据定义语言
DML 数据操纵语言
DQL 数据查询语言
DCL	数据控制语言
1 数据库创建
我们需要指定字符集防止乱码
比如
create database xxx数据库 default charset="utf8"

查询所有数据库
show databases

2 查看表的结构
比如
desc stu表名

3 查询指定表的建表语句
比如
show create table stu表名

4 常用的数据类型
tinyint 常用于人的年龄(0~255)
其中char为定长字符串
varchar为可变长字符串
date YYYY-MM-DD
time HH:MM:SS
datetime YYYY-MM-DD HH:MM:SS

5 表操作
设置主键自增在建表语句中加入 auto_increment
create table xxx(
id int auto_increment primary key comment "ID",
)
添加字段
注意表名不要加引号!!!
alter table stu ADD sss INT(1) comment "是否18岁";

修改数据类型
alter table stu modify sss VARCHAR(2)

修改字段名(可以同时修改数据类型)
alter table stu change sss aaa int(2)

删除字段
alter table stu drop aaa

修改表名
alter table stu rename stus

删除表
drop table if exists stus

删除并重建表
truncate table stus

批量数据插入
注意字段名不要加引号!!
insert into stu(sa) values("aa"),("bb")

修改数据
where中是单等号!!
update stu set sa="dd" where id=1

6数据查询

这是我们书写关键字的顺序!
SELECT
字段列表
FROM
表名列表
WHERE
条件列表
GROUP BY
分组字段列表
HAVING
分组后条件列表
ORDER BY
排序字段列表
LIMIT
分页参数

分组查询
辨析!
where与having区别
执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组
之后对结果进行过滤。
判断条件不同:where不能对聚合函数进行判断,而having可以

排序查询

ASC : 升序(默认值)
DESC: 降序
例子
按name降序
select name from emp where age>30 order by name desc

分页查询

起始索引从0开始,起始索引 = (查询页码 - 1)* 每页显示记录数。
例子
从第二页查询4条数据,如果第二页不足4条数据,会从弟1页中拿出一下数据补全
SELECT name from emp where age<30 limit 2,4

6 用户操作
查看所有用户
select * from mysql.user;
创建用户
注意事项,@前后不能加空格
create user "dada"@"localhost" identified by "1111"
修改用户密码
alter user "dada"@"localhost" identified with mysql_native_password by "2222"

7 权限控制
常见权限

ALL, ALL PRIVILEGES 所有权限
SELECT 查询数据
INSERT 插入数据
UPDATE 修改数据
DELETE 删除数据
ALTER 修改表
DROP 删除数据库/表/视图
CREATE 创建数据库/表

查询用户的权限
show grants for "dada"@"localhost"
授予权限
注意事项
多个权限之间,使用逗号分隔
授权时, 数据库名和表名可以使用 * 进行通配,代表所有。
grant all on students.stu to "dada"@"localhost"
撤销权限
revoke all on students.stu from "dada"@"localhost"

函数

CONCAT(S1,S2,...Sn) 字符串拼接,将S1,S2,... Sn拼接成一个字符串
LOWER(str) 将字符串str全部转为小写
UPPER(str) 将字符串str全部转为大写
LPAD(str,n,pad)

左填充,用字符串pad对str的左边进行填充,达到n个字符
串长度
RPAD(str,n,pad)
右填充,用字符串pad对str的右边进行填充,达到n个字符
串长度
TRIM(str) 去掉字符串头部和尾部的空格
SUBSTRING(str,start,len) 返回从字符串str从start位置起的len个长度的字符串

例子
由于业务需求变更,企业员工的工号,统一为5位数,目前不足5位数的全部在前面补0。比如: 1号员
工的工号应该为00001。
update emp set workno = lpad(workno, 9, '0')


日期函数(常用)
curdate() 返回当前日期
curtime() 返回当前时间
now() 返回当前日期和时间
year(date) 获取指定date的年份
month(date) 获取指定date的月份
day(date) 获取指定date的日期
date_add(date, INTERVAL exprtype)
返回一个日期/时间值加上一个时间间隔expr后的时间值

datediff(date1,date2)
返回起始时间date1 和 结束时间date2之间的天
数
例子
查询所有员工的入职天数,并根据入职天数倒序排序。
select name,datediff(day1,curdate()) as "divday" from empss order by divday desc

流程函数
IF(value , t , f)
如果value为true,则返回t,否则返回f

IFNULL(value1 , value2)
如果value1不为空,返回value1,否则返回value2

CASE WHEN [ val1 ] THEN [res1] ...
ELSE [ default ] END
如果val1为true,返回res1,... 否则返回default默认值

CASE [ expr ] WHEN [ val1 ] THEN
[res1] ... ELSE [ default ] END
如果expr的值等于val1,返回res1,... 否则返回default默认值(常用)

例子
查询emp表的员工姓名和工作地址 (北京/上海 ----> 一线城市 , 其他 ----> 二线城市)
select name,(case workaddress when "北京" then "一线城市" when "上海" then "一下城市" else "二线城市" end) as "所在城市" from emp

约束
空约束 限制该字段的数据不能为null NOT NULL
唯一约束 保证该字段的所有数据都是唯一、不重复的 UNIQUE
主键约束 主键是一行数据的唯一标识,要求非空且唯一 PRIMARY KEY
默认约束 保存数据时,如果未指定该字段的值,则采用默认值 DEFAULT
检查约束(8.0.16版本
之后)
保证字段值满足某一个条件 CHECK
外键约束
用来让两张表的数据之间建立连接,保证数据的一致 性和完整性 FOREIGN KEY
添加外键
新建表时
其中外键名称是用来标识外键的,不写的话数据库会自动生成
CREATE TABLE 表名(
字段名 数据类型,
...
[CONSTRAINT] [外键名称] FOREIGN KEY (外键字段名) REFERENCES 主表 (主表列名)
);
修改表时
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名)
REFERENCES 主表 (主表列名) ;

删除外键
alter table 表名 drop foreign key 外键名称(唯一的)

约束行为
NO ACTION
当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不
允许删除/更新。 (与 RESTRICT 一致) 默认行为
RESTRICT
当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不
允许删除/更新。 (与 NO ACTION 一致) 默认行为
CASCADE
当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有,则
也删除/更新外键在子表中的记录。
SET NULL
当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表
中该外键值为null(这就要求该外键允许取null)。
SET DEFAULT
父表有变更时,子表将外键列设置成一个默认的值 (Innodb不支持)
添加约束行为
alter table 表名 add constraint 外键名称 foreign key(外键字段) references
主表名 (主表字段名) ON UPDATE CASCADE ON DELETE CASCADE;


多表查询
其原理为笛卡尔积:就是交叉相乘,进行数据的组合
select * from emp , dept where emp.dept_id = dept.id;

内连接
就是就是查两表的重叠部分(画图)
左/右外连接(左/右表的全部,包括左右表的交叉部分(即包括内连接的结果))

例子
查询emp表的所有数据, 和对应的部门信息
 由于需求中提到,要查询emp的所有数据,所以是不能内连接查询的,需要考虑使用外连接查询。
 表结构: emp, dept
 连接条件: emp.dept_id = dept.id
select e.*, d.name from emp e left outer join dept d on e.dept_id = d.id;
select e.*, d.name from emp e left join dept d on e.dept_id = d.id;
(outer 可以省略,on换为where也不错,但是不规范)

联合查询
注意事项
对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。
union all 会将全部的数据直接合并在一起,union 会对合并之后的数据去重。
例子
将薪资低于 5000 的员工 , 和 年龄大于 50 岁的员工全部查询出来.
当前对于这个需求,我们可以直接使用多条件查询,使用逻辑运算符 or 连接即可。 那这里呢,我们
也可以通过union/union all来联合查询.
select * from emp where salary < 5000 union all select * from emp where age > 50;

子查询
简单略

事务
事务的4大特性
1 原子性 A
2 完整性 C
3 持久性 D
4 隔离性 I
查看事务
如果为1 的话说明是处于开启自动提交的状态(mysql的默认状态)
select @@autocommit
设置事务不自动提交
set @@autocommit=0

开始事务
begin
提交事务
commit
回滚
rollback

事务隔离级别
注意:事务隔离级别越高,数据越安全,但是性能越低。
隔离级别 					脏读 不可重复读 幻读
Read uncommitted 		√			 	√			 √
Read committed 			× 			√			 √
Repeatable Read(默认) ×			×			 √
Serializable 				×				×			 ×

查看事务隔离级别
SELECT @@TRANSACTION_ISOLATION;
设置事务隔离级别
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED |
READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

进阶

1 mysql架构
连接层
服务层
引擎层 -》是基于表的——》是mysql的核心
存储层

2 查询数据库所支持的引擎
show engines
通过查询建表语句查看表的引擎
默认为Innodb
show create table emp

3 建表时指定引擎
注意最后一个字段不能加逗号
create table `xydaz`(
id int auto_increment primary key,
name varchar(50) comment "姓名"
)engine=INNODB;

4 索引
索引结构
B+Tree索引 最常见的索引类型,大部分引擎都支持 B+ 树索引
Hash索引 底层数据结构是用哈希表实现的, 只有精确匹配索引列的查询才有效, 
不支持范围查询R-tree(空间索引) 空间索引是MyISAM引擎的一个特殊索引类型,主要用于
地理空间数据类型,通常使用较少Full-text(全文索引) 是一种通过建立倒排索引,快速匹配
文档的方式。类似于 Lucene,Solr,ES

索引 InnoDB MyISAM Memory
B+tree索引 支持 支持 支持
Hash 索引 不支持 不支持 支持
R-tree 索引 不支持 支持 不支持
Full-text 5.6版本之后支持 支持 不支持
B+,B-树索引
最终我们看到,B+Tree 与 B-Tree相比,主要有以下三点区别:
所有的数据都会出现在叶子节点。
叶子节点形成一个单向链表。
非叶子节点仅仅起到索引数据作用,具体的数据都是在叶子节点存放的。
分,是数据存储部分,在其叶子节点中要存储具体的数据。
其中 我们可以通过一个数据结构可视化的网站来简单演示一下。 
https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html

思考题为什么mysql的Innodb要使用B+索引?
A. 相对于二叉树,层级更少,搜索效率高;
B. 对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储
的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低;
C. 相对Hash索引,B+tree支持范围匹配及排序操作;

分类 含义 特点
聚集索引(Clustered Index) 将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据
必须有,而且只有一个

二级索引(Secondary Index) 将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键
可以存在多个

聚集索引选取规则:
如果存在主键,主键索引就是聚集索引。
如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。
如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引。

回表查询: 这种先到二级索引中查找数据,找到主键值,然后再到聚集索引中根据主键值,获取
数据的方式,就称之为回表查询。
例子
以下两条SQL语句,那个执行效率高? 为什么?
A. select * from user where id = 10 ;
B. select * from user where name = 'Arm' ;
备注: id为主键,name字段创建的有索引;
解答:
A 语句的执行性能要高于B 语句。
因为A语句直接走聚集索引,直接返回数据。 而B语句需要先查询name字段的二级索引,然
后再查询聚集索引,也就是需要进行回表查询。

索引的建立
为可能重复的键建索引
create index idx_user_name on tb_user(name);
为唯一的键建立索引
create unique indxe idx_user_phone on tb_user(phone);
建立联合索引
create index idx_user_pro_age_sta on tb_user(profession,age,status);

索引的查看
show index from tb_user;
索引的删除
drop index idx_user_age on tb_user;
drop index idx_email on tb_user;

查看数据库的插入,更新,查询,删除次数
SHOW GLOBAL STATUS LIKE 'Com_______'
查看当前会话
SHOW Session STATUS LIKE 'Com_______'

通过上述指令,我们可以查看到当前数据库到底是以查询为主,还是以增删改为主,从而为数据
库优化提供参考依据。 如果是以增删改为主,我们可以考虑不对其进行索引的优化。 如果是以
查询为主,那么就要考虑对数据库的索引进行优化了。

慢查询日志
超过一定时间的查询会被视为慢查询,并计入慢查询日志中,但是mysql默认是关闭慢查询日志的
查看慢查询是否开启
show variables like "slow_query_log"
如果Value为ON说明是开启的(咯咯,不知道为什么我的默认为ON开启状态)

手动开启
暂时没有解决....

使用profiles
show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。
查看当前数据库是否支持profiles
SELECT @@have_profiling

开启profiles开关(默认好像是开启的)
 SET profiling = 1;
 
 使用profiles
 我们先执行查询sql语句
 select * from emp
 然后打印日志
 show profiles
 我的结果如下
128	0.0002515	select * from emp
129	0.001133	SHOW STATUS
130	0.0012115	SELECT QUERY_ID, SUM(DURATION) AS SUM_DURATION FROM INFORMATION_SCHEMA.PROFILING GROUP BY QUERY_ID
131	0.000832	SELECT STATE AS `Status`, ROUND(SUM(DURATION),7) AS `Duration`, CONCAT(ROUND(SUM(DURATION)/0.001250*100,3), '') AS `Percentage` FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID=116 GROUP BY SEQ, STATE ORDER BY SEQ
132	0.000125	SET PROFILING = 1
133	0.0009065	SHOW STATUS
134	0.0024485	SHOW STATUS

查看指定query_id的SQL语句各个阶段的耗时情况
show profile for query query_id;
show profile for query 128;
我的结果如下
starting	0.000049
checking permissions	0.000004
Opening tables	0.000020
init	0.000012
System lock	0.000014
optimizing	0.000003
statistics	0.000009
preparing	0.000007
executing	0.000008
Sending data	0.000056
end	0.000002
query end	0.000006
closing tables	0.000005
freeing items	0.000045
cleaning up	0.000012

查看指定query_id的SQL语句CPU的使用情况
show profile cpu for query query_id;
show profile cpu for query 128;
我的结果为
空!!!妈呀,没用CPU????

获取/查看sql语句的执行顺序
explain SQL语句
例子
explain select * from emp
我的结果
1	SIMPLE	emp		ALL					16	100.00	
提示
当type字段的值为 rel时说明该查询走了索引

其具体字段含义如下
id select查询的序列号,表示查询中执行select子句或者是操作表的顺序
(id相同,执行顺序从上到下;id不同,值越大,越先执行)。
select_type 表示 SELECT 的类型,常见的取值有 SIMPLE(简单表,即不使用表连接
或者子查询)、PRIMARY(主查询,即外层的查询)、UNION(UNION 中的第二个或者后
面的查询语句)、SUBQUERY(SELECT/WHERE之后包含了子查询)等type 表示连接类型,
性能由好到差的连接类型为NULL、system、const、eq_ref、ref、range、 index、
all 。possible_key 显示可能应用在这张表上的索引,一个或多个。
key 实际使用的索引,如果为NULL,则没有使用索引。
key_len 表示索引中使用的字节数, 该值为索引字段最大可能长度,并非实际使用长度,
在不损失精确性的前提下, 长度越短越好 。rows MySQL认为必须要执行查询的行数,在
innodb引擎的表中,是一个估计值,可能并不总是准确的。filtered 表示返回结果的行数
占需读取行数的百分比, filtered 的值越大越好。


最左前缀法则
最左前缀法则指的是查询从索引的最左列开始,
并且不跳过索引中的列。如果跳跃某一列,
索引将会部分失效(后面的字段索引失效)。

解释举例,当联合查询是联合了3个字段A,B,C时
我们对这些字段进行查询
当A不存在时,此次的联合索引失效(B,C都不会走索引了,
就是会去走全表查询查B,C字段)
当A存在B不存在时,此次联合索引失效(C不会走索引,会
去走全表查询)

在 tb_user 表中,有一个联合索引,这个联合索引涉及到三个字段,
顺序分别为:profession,age,status。
当执行SQL语句: explain select * from tb_user where age = 31 and
status = '0' and profession = '软件工程'时,是否满足最左前缀法则,
走不走上述的联合索引,索引长度?
答:
是完全满足最左前缀法则的,索引长度54,联合索引是生效的。最左
前缀法则指的是在建立索引的最左边的字段(profession)与后续查询
语句的字段的摆放顺序是无关的

范围查询
联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效。
但是出现(>=,<=)时的范围查询时,列索引不会失效
explain select * from tb_user where profession = '软件工程' and 
age > 30 and status= '0';
索引只会走到第第二个字段(age)后就失效了
explain select * from tb_user where profession = '软件工程' and 
age >= 30 and status= '0';
索引会全部正常走完

其他索引失效的情况
1在索引列上进行运算操作 
在索引列上进行任何运算操作, 索引都将失效。
2字符串加引号 
当字符串类型字段使用时,不加引号,索引也将失效。
3 模糊匹配
如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。
例子
explain select * from tb_user where profession like '软件%';
走索引
explain select * from tb_user where profession like '%工程'
不走索引
4 or连接条件
当or连接的条件,左右两侧字段都有索引时,索引才会生效。
但是and却不用,索引都会生效!!
5 数据分布影响
在MySQL在查询时,会评估使用索引的效率与走全表扫描的效率,如果走全表扫描更快,
则放弃索引,走全表扫描。 因为索引是用来索引少量数据的,如果通过索引查询返回
大批量的数据,则还不如走全表扫描来的快,此时索引就会失效。
6 使用is null 、is not null有时会走有时不会走,主要看5!!

指定索引(SQL提示)
当同一个字段有很多索引是=时,我们就要用到SQL提示来指定特定的索引。
它是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优
化操作的目的。

1. use index : 建议MySQL使用哪一个索引完成此次查询(仅仅是建议,mysql内部还会再次进
行评估)。
2. ignore index : 忽略指定的索引。
3. force index : 强制使用索引。
例子
explain select * from tb_user use index(idx_user_pro) where profession = '软件工程';
explain select * from tb_user ignore index(idx_user_pro) where profession = '软件工程';
explain select * from tb_user force index(idx_user_pro) where profession = '软件工程';

覆盖索引
尽量使用覆盖索引,减少select *。 那么什么是覆盖索引呢? 覆盖索引是指
查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到 。
其中SQL执行中的
Extra 含义
Using where; Using Index
查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据

Using index condition
查找使用了索引,但是需要回表查询数据
具体看截图

前缀索引
当字段类型为字符串(varchar,text,longtext等)时,有时候需要索引很长的字符串,这会让
索引变得很大,查询时,浪费大量的磁盘IO, 影响查询效率。此时可以只将字符串的一部分前缀,建
立索引,这样可以大大节约索引空间,从而提高索引效率。
语法
create index 索引名 on 表名(字段名(字符串长度(从左到右)))
例子
create index idx_email_5 on tb_user(email(5));
索引设计原则
1 针对于数据量较大,且查询比较频繁的表建立索引。
2. 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索
引。
3 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
4 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
5 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,
避免回表,提高查询效率。
6 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增
删改的效率。
7 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含
NULL值时,它可以更好地确定哪个索引最有效地用于查询。

SQL优化
插入
如果我们需要一次性往数据库表中插入多条记录,可以从以下三个方面进行优化。
1 批量插入
2 手动事务提交
3 插入时,主键按照顺序插入

大批量插入数据(百万条左右)
可以执行如下指令,将数据脚本文件中的数据加载到表结构中:
-- 客户端连接服务端时,加上参数 -–local-infile
mysql –-local-infile -u root -p

-- 设置全局参数local_infile为1,开启从本地加载文件导入数据的开关
set global local_infile = 1;

-- 执行load指令将准备好的数据,加载到表结构中
load data local infile '/root/sql1.log' into table tb_user fields
terminated by ',' lines terminated by '\n

例子
1 我们先建立对应的表结构
2 前两步省略(可以直接粘代码)
3 load data local infile '/root/load_user_100w_sort.sql' into table tb_user
fields terminated by ',' lines terminated by '\n' ;

易错辨析

覆盖索引?回表查寻? 

从SQL到mysql学习笔记查漏补缺_第1张图片

 从SQL到mysql学习笔记查漏补缺_第2张图片

从SQL到mysql学习笔记查漏补缺_第3张图片 从SQL到mysql学习笔记查漏补缺_第4张图片

你可能感兴趣的:(数据库,数据库,sql,mysql)