三十一、使用revoke进行权限的收回,将上面用户的授权分别收回,同时查看收回后的结果
①REVOKE INSERT ON *.* FROM 'jeffrey'@'localhost';
②REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...
三十二、select最简单常用语法
1、全表查询
select * from tbl_name;
2、某些行查询
select * from tbl_name where ……;
3、某些列查询
select clm_name from tbl_name;
4、某些行的某些列查询
select clm_name from tbl_name where ……;
5、列别名
select clm_name as new_name from tbl_name;
6、列运算
select clm_name+123 from tbl_name;
三十三、concat函数的使用
1、concat函数:将多个字符串参数首尾相连后返回
2、concat_ws函数:将多个字符串参数以给定的分隔符,首尾相连后返回
3、group_concat:函数的值等于属于一个组的指定列的所有值,以逗号隔开,并且以字符串表示
三十四、演示打开和关闭管道符号“|”的连接功能
PIPES_AS_CONCAT:将“||”视为字符串的连接操作符而非或运算符
|| 管道连接符:
mysql> select 列名1 || 列名2 || 列名3 from 表名;
在mysql中,进行上式连接查询之后,会将查询结果集在一列中显示,列名是‘列名1 || 列名2 || 列名3’
mysql> select s_no || s_name || s_age -> from student; +-------------------------+ | s_no || s_name || s_age | +-------------------------+ | 1001张三23 | | 1002李四19 | +-------------------------+
如果不显示结果,是因为sql_mode参数中没有PIPES_AS_CONCAT,只要给sql_mode参数加入PIPES_AS_CONCAT,就可以实现像CONCAT一样的功能;
如果不给sql_mode参数加入PIPES_AS_CONCAT的话,|| 默认是or的意思,查询结果是一列显示是1。
三十五、使用mysql> help functions; 学习MySQL各类函数
三十六、常见功能函数
1、upper(……)、lower(……)大小写变换
2、user()查看登录用户、current_user()查看当前用户
3、database()查看使用的数据库
三十七、使用help来学习下面的数据类型(建立对应类型的列、插入数据、显示数据)
1、整数:int
2、非负数:unsigned无符号即非负数---e.g:int unsigned
3、小数:dec
4、浮点数以及科学计数法:float、double
如果FLOAT数据在插入的时候,要使用NeM(科学计数法)的方式插入时:
比如
5e2 就是5*10的2次方
5e-2就是5*10 的-2次方
4e-1+5.1e2 就是510.4
5、字符串:varchar
6、布尔:bool、boolean---synonyms(同义词):TINYINT(1)
7、位:bit
如何使用16进制常量:hex()
如何使用2进制常量:bin()
date类型以及STR_TO_DATE函数
time类型以及STR_TO_DATE函数
dateime数据类型以及标准写法、STR_TO_DATE函数
date和time显示方式以及date_format函数
三十八、时区
1、查看操作系统时区、数据库时区
查看操作系统时区:
shell> cat /etc/sysconfig/clock
ZONE="Asia/Shanghai"
shell> ls /usr/share/zoneinfo
……
mysql> show variables like 'system_time%'; #查看MySQL系统时区
mysql> show variables like 'time_zone%'; #查看数据库时区
2、修改数据库时区为东八区,去掉数据库时区对os时区的依赖(查看官方文档)
加载系统时区:将Linux时区导入到数据库中
shell> mysql_tzinfo_to_sql /usr/share/zoneinfo |mysql -uroot -p123 mysql
mysql> set @@global.time_zone='Asia/Shanghai';
修改数据库时区为东八区,同时在参数文件中进行修改,永久保存
3、时区在什么时候有用:
如果数据库里面没有timestamp这个数据类型,那么时区参数没有意义!
你如何确认你的数据库里面是否有timestamp类型的列?
mysql> select table_name,column_name,data_type -> from information_schema.columns -> where data_type='timestamp';
……
时区原理描述:insert过程和select过程的描述:相对应的0时区的转换
4、时区的正确实践(timestamp)
insert以前:你的values对应的时间到底是哪个时区,然后设置set @@session.time_zone为对应的时区
select获取以前:你想得到什么时区的时间,就设置set @@session.time_zone为对应的时区
三十九、字符集
1、查看服务器的字符集
mysql> show variables like 'character_set_server';
2、查看数据库字符集
mysql> show variables like 'character_set_database';
一般在数据库实现字符集即可,表和列都默认采用数据库的字符集
gbk
utf8
3、查看表的字符集、查看列的字符集
mysql> show create table tbl_name;
4、字符集原理描述、字符集正确实践
对于insert过程描述、对于select过程描述
①对于insert来说,character_set_client、character_set_connection相同,而且正确反映客户端使用的字符集
②对于select来说,character_set_results正确反映客户端字符集
③数据库字符集取决于我们要存储的字符类型
④字符集转换最多发生一次,这就要求character_set_client、character_set_connection相同
⑤所有的字符集转换都发生在数据库端
总述:
1)建立数据库的时候注意字符集(gbk、utf8)
2)连接数据库以后,无论是执行dml还是select,只要涉及到varchar、char列,就需要设置正确的字符集参数:
character_set_client、character_set_connection、character_set_results
5、客户端字符集如何来理解?
取决于客户端工具
shell> mysql -uroot -p123456 -hserver_host -P3306
mysql工具本身没有字符集,因此客户端字符集取决于工具所在的os的字符集(windows:gbk、linux:utf8)
sqlyog工具本身带字符集,此时客户端os字符集就没有意义
6、如何判断字符集出现了问题?
所有设置都正确,但是查询到的还是乱码,这就是出现问题了
四十、如何识别变量参数、状态参数status var
show variables……
show status……
识别判断都是查看官方文档System Var、Status Var
四十一、如何识别动态参数、静态参数
动态参数dynamic:Yes
静态参数dynamic:No
四十二、对于动态参数如何设置,如何判断动态参数是否可以在全局级别或者会话级别修改
1、set
2、修改参数文件/etc/my.cnf:弊端是需要重启才能生效(很少用)
判断:参考官方文档Option/Variable Summary,通过Var scope来进行判断动态参数的全局global、both
四十三、对于静态参数如何修改
静态参数,在整个实例声明周期内都不得进行更改,就好似是只读的;
一般静态参数都是在配置文件中修改/etc/my.cnf,当然静态参数能否写入配置文件还要看官方文档对该参数的Option File的描述Yes与否。
四十四、掌握@@、@的区别
1、@@var_name表示的系统变量
根据系统变量的作用域可分:全局变量、会话变量
2、@var_name表示的用户变量
①用户变量和数据库连接有关,连接后声明变量,连接断开后,自动消失;
②select一个没有赋值的用户变量,返回NULL,也就是没有值;
Mysql的变量类似于动态语言,变量的值随所要赋的值的类型而改变。
四十五、set @@session.和set @@global.的生效时间
对于一个新建立的连接,只有全局变量,会话变量还不存在,这个时候会从全局变量拷贝过来。
1、set @@session.:只对当前连接起作用
2、set @@global.:对全局变量的修改会影响到整个服务器
注意:set系统变量时,不带作用域修饰,默认是指会话作用域;
(特别注意,有些系统变量不带作用域修饰,无法设置,因此最好都带上作用域设置系统变量)。
四十六、动态参数最佳实践
1、尽量先进行会话级别的设置set @@session,确认生效而且效果不错以后,再进行全局设置,如果需要马上生效,杀掉所有的会话:
mysql> select concat('kill ',conn_id,';') from sys.session;
2、确认没有问题以后,修改参数文件,下次系统启动一直生效。
四十七、select书写技巧
1、确认需要访问数据来自于哪几张表
from来自某张表或者某几张表
join添加某张表
on表连接条件
记住一点:每关联一个表就需要加上对应的on条件(on条件就是主外键条件)
2、通过where条件来过滤数据
3、确认需求里面是否有分组聚合的含义
分组:group by
聚合:聚合函数
聚合条件过滤:having
4、是否需要排序
order by
四十八、MySQL内置函数(将列出的常见的一些函数熟悉过一遍)
1、内置函数的多少是一个数据库是否成熟的标志
2、学会使用help Functions学习和使用函数(重点!!!!!!!!!!!)
3、常用函数要过一遍
①日期时间相关的函数
CURDATE、DATEDIFF、DATE_FORMAT、DAYOFWEEK、LAST_DAY、EXTRACT、STR_TO_DATE
②比较操作符要求都过一遍,help Comparison operators;
③流程控制行数help Control flow functions;
④加密函数help Encryption Functions;
只需要看看decode、password两个函数即可
⑤信息获取函数help Information Functions;
通过这些函数可以知道一些信息,过一遍即可
⑥逻辑操作符help Logical operators;
!、and、or,这些常用的要过一遍
⑦杂项函数help Miscellaneous Functions;
简单浏览一下里面的函数,对于名字有个印象即可
⑧数值函数help Numeric Functions;
使用数据库来进行数学运算的情况不多,常用的加减乘除、TRUNCATE、ROUND
⑨字符串函数help String Functions;
CONCAT、CONCAT_WS、CAST、FORMAT、LIKE、REGEXP、STRCMP、TRIM、SUBSTRING、UPPER,其它函数名字过一遍
4、聚合分组函数的使用了解
①select后面得列或者出现在group by中,或者加上聚合函数
select c1,c2,sum(c3),count(c4) from t1 group by c1,c2;
②help contents;
查看聚合函数help Functions and Modifiers for Use with GROUP BY;
AVG、MAX、MIN、SUM、COUNT、COUNT DISTINCT、GROUP_CONCAT、BIT_AND、BIT_OR、BIT_XOR
四十九、隐式类型转换,要避免隐式类型转换
1、最常用的几个数据类型:数字、字符串、日期时间
2、字符串里面可以存放数字和日期,但是在设计表的时候,要注意不要将日期和数字列设计成字符串列
3、对于字符串列的比较,一定要加上引号:
mysql> select * from t where name_phone='1301110001';
五十、limit使用很频繁,注意其使用方法
1、limit使用的场合
从结果集中选取最前面或最后面的几行
2、limit配合order by使用
3、MySQL5.7 doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
五十一、in、not in、exists、not exists、left join、distinct join互相转换
1、in和exists可以互相转换
select * from players a where a.teamno in (select teamno from team where teamname='骑士队'); select * from players a where exists (select 1 from team b where a.teamno=b.teamno and b.teamname='骑士队');
2、not in和not exists可以互相转换
3、not in、not exists可以转换成left join
select * from 学生信息 a where a.stuno not in (select stuno from 选课信息表); select * from 学生信息 a left join 选课信息 b on a.stuno=b.stuno where b.成绩 is null;
4、in、exists可以转换成distinct join
select * from 学生信息 a where a.stuno in (select stuno from 选课信息表 b); select * from 学生信息 a where exists (select 1 from 选课信息 b where a.stuno=b.stuno); select distinct a.* from 学生信息 join 选课信息 b on a.stuno=b.stuno;
五十二、连接的具体使用含义
1、理解为什么会出现表连接:查询的列来自于多个表
select 列 from .. where 列 group by 列 having 列 order by 列 limit x
2、理解表连接的书写方式
join一个表、on一个条件
3、理解表连接的注意条件
①两个表要连接一定要存在主外键关系(有可能需要第三张表协助关联)
实际上存在外键约束
存在外键列,但是没有外键约束
②防止扇形陷阱(两个表需要关联,但是没有直接主外键,借助第三个表进行关联,但是存在扇形问题,此时不能借助第三个表进行关联)
示例:学院表、专业表、学生表
学院实体和专业实体之间是一对多的联系;
学院实体和学生实体之间也是一对多的联系;
而学生和专业之间没有联系;
如果学生和专业通过学院表进行关联,就会出现扇形问题。
4、外连接:左外连接、右外连接
外连接是为了防止出现某一个表的数据被遗漏
开发人员非常喜欢使用外连接.
五十三、子查询
1、子查询可能出现的位置
①select from之间可能会出现子查询
②from后面
③join后面可能会出现子查询
④where后面可能会出现子查询
⑤having后面可能会出现子查询
2、尽最大程度的不要使用子查询
3、相关子查询、无关子查询
相关子查询特别容易出现在select from之间、where后面
相关子查询不能独立执行,子查询执行次数取决于父查询返回的行数
无关子查询可以独立执行,子查询执行一次
五十四、子查询出现的场合
1、where中出现的子查询,一般可使用表连接进行改写
①select 列(涉及到A表,没有涉及到B表)
②where 条件(涉及到B表)
2、from后面的子查询
①对于取出来的数据再次进行复杂的处理
例如分组聚合、having条件、where条件等
②对一个结果集再次进行复杂的查询
意味着我们取数据的这个过程中,对数据进行处理的力度很复杂
3、select from之间的子查询
对于返回的每一行数据,select和from之间的子查询都要执行一次
select后面的列要进行复杂的处理,如果这个处理涉及到另外一个表,若这个表很可能没有出现在from和join里面,则进行子查询:
示例:将每一个同学的成绩列出来,同时计算他的成绩和本组平均成绩的差距
select 学生成绩, 学生成绩-(select avg(成绩) from 选课表 a where a.组ID=b.组ID) from 选课表 b;
五十五、select执行的顺序
select ... from ... join ... on ... where ... group by .. having ... order by ...
1、先从表中取数据,访问innodb buffer pool
from ...
join ...
on ...
where
2、分组、聚合,数据已经进入用户工作空间
group by ...
having ...
3、select ....:取列数据
4、order by:排序输出
五十六、集合操作
union:结果集去重
union all:结果集不去重
五十七、insert增
1、insert values一条数据
表的名字后面最好加上列的名字
2、insert values多条数据
3、insert into select
select可以非常复杂,语法完全就是select
五十八、update改
基本格式:update 一个表 set 列 where 列条件;
1、一定要带上where条件
2、update分为下面的几个步骤操作
①找到需要update的数据,此操作取决于where条件
where条件可以是一个复杂的where条件,比如是一个子查询
示例:将平均成绩75分以上的学生的级别设置为优等生
update 学生信息表 a set grade=‘优等生’ where a.stuno in (select b.stuno from 成绩表 b group by b.stuno having avg(成绩)>=75);
②set后面的列,也可以很复杂,比如是一个相对子查询
UPDATE players_data pd SET number_mat = ( SELECT count(*) FROM matches m WHERE m.playerno = pd.playerno), sum_penalties = ( SELECT sum(amount) FROM penalties pen WHERE pen.playerno = pd.playerno);
3、update可以改写成一个select语句
把1和2改写成一个select语句,不要对一个update在生产里面直接进行优化
4、update可以使用order by,数据按照顺序进行更新
5、update可以使用limit,限制每次更新的行数
五十九、replace替代已有的行
使用场合insert+update,两个表数据合并到一起
六十、delete删
1、绝大多数情况下需要加上where条件
2、where条件可以很复杂,例如是一个子查询
3、理解delete和truncate的区别
truncate:清空全部数据、速度快、释放空间(不删表)
delete:全部或者部分删除数据、速度慢、不释放空间
六十一、临时表
1、只是针对当前会话有效,临时表和数据都存储在用户工作空间
2、临时表的使用很消耗资源
①create、insert、drop,因此在非常频繁的查询环境下,不宜使用临时表;
②临时表需要使用用户工作空间,临时表中存在的数据不易过多,否则容易出现磁盘临时表;
3、临时表的使用场合
需要暂存结果集数据,后面的操作需要访问这些暂存结果集,主要是为了可读性。
4、有一种误区一定要注意,一定不要将普通表作为临时表来使用
原因:普通表当做临时表来使用,下面的操作需要手工去做
①create、insert、truncate或者drop
②对于普通表的所有操作都会产生redo(事务),非常消耗资源
六十二、关于约束
1、非空
2、default约束
3、主键约束
4、外键约束
5、SET、ENUM约束
约束注意点:
①尽量选择列都为非空
②对于bool、时间列经常会出现default约束
③每一个表尽最大程度要有主键
④唯一键可以有多个,唯一键可以有空值
⑤外键列一般会有,但是外键约束不建议使用,在应用层面保证主表和外表的一致性
⑥合理使用set和enum约束,提升数据的质量
⑦外键约束中on delete、update,尽量不要设置级联删除操作(很危险!!!)
六十三、表的DDL
1、极其严肃的一个动作
2、使用help书写DDL语句
3、ddl动作的后遗症和危险性
①影响I、D、U、S
②长时间锁表、产生海量IO
4、测试DDL的影响范围---优化对象
①锁表时间
②IO情况
③具体测试要求
示例:产生一个500万行的表(写一个存储过程实现),对表进行增加列、删除列、修改列的名字、将列的长度变长、将列的长度变短
mysql> delimiter $$ mysql> create procedure do_big(x int) -> begin -> declare v int; -> set v=x; -> create table test(test_num int auto_increment not null primary key); -> while v>0 do -> insert into test values(null); -> set v=v-1; -> end while; -> end $$ mysql> delimiter ; mysql> call do_big(5000000); …… mysql> select count(*) from test; +----------+ | count(*) | +----------+ | 5000000 | +----------+
看一下上面的这些操作,哪些操作时间长、哪些操作时间短,并对其进行初步的原理分析
mysql> insert into test values(123456789); mysql> delete from test where test_num=123; mysql> alter table test CHANGE COLUMN -> test_num -> test_id int(10) not null auto_increment; mysql> alter table test modify test_id int(100); mysql> alter table test modify test_id int(20);
总结:对于一个大表而言,将列的长度变长时间是最长的,其他的操作处理时间都还挺短。
六十四、视图的最佳实践
1、视图就是select的一个名字
2、不建议使用复杂视图
select语句里面不要带有distinct、group by、聚合函数、union等操作
3、不建议在视图中嵌套视图
4、视图的主要使用场合
统一访问接口(select)---主要的好处
规范访问
隐藏底层表结构、ddl不影响应用访问
5、视图在安全方面的意义
六十五、存储过程(脚本)
1、存储过程使用的场合
①重复性很高的复合操作(dml)
②统一访问接口(dml、事务)
③批量业务(跑批)
2、存储过程结构分析
①存储过程中嵌入了dml、select
②存储过程有参数,参数的不同会产生不同的事务
in、out、inout
③存储过程里面有结构化语句,即流程控制语句:
循环
条件判断
使得在执行dml、select的时候,变得方便
④存储过程可以定义变量
select取出来的结果可以存储到变量中
dml需要的输入值可以通过变量来实现
⑤存储过程里面可以有游标,游标的核心就是可以对一个结果集进行处理
1)定义游标(游标和一个select关联)
2)打开游标(将select的结果赋给游标,可以是N行列)
3)遍历游标(一行行数据获取,每一行数据赋给N个变量)
4)关闭游标
⑥存储过程有异常处理部分
1)异常处理是一个存储过程是否可以产品化、商业化很重要的一个标志
2)异常处理只关心SQL语句的异常
每一个存储过程都要对着三类SQLWARNING、NOT FOUND、SQLEXCEPTION进行处理;
存储过程异常处理通常只是进行错误的记录,或者空处理。
⑦存储过程书写过程
1)定义一个结构
存储过程基本结构
参数
异常处理
2)书写涉及到SQL语句
3)考虑使用变量、游标、条件判断、循环将SQL语句组合起来
4)经常使用begin end来将一组SQL语句或者语句组合起来,作为一个语句来出现
3、存储过程安全方面的意义:防止对底层表直接进行dml
六十六、自定义函数
1、自定义函数和存储过程的区别
①有一个返回值
CREATE FUNCTION SimpleCompare(n INT, m INT) RETURNS VARCHAR(20) ……
②调用的时候必须放在=的右边
set @ax = SimpleCompare(1,2);
2、整理笔记,将函数定义和函数调用整理一个例子出来
六十七、触发器
1、尽量少使用触发器,不建议使用
2、触发器是一个begin end结构体
3、触发器和存储过程的唯一区别就是在于被执行方式上的区别
存储过程需要手工去执行
触发器被DML自动触发
4、触发器被触发的条件
①for each row(每一行都被触发一次,这就决定了频繁dml的表上面不要有触发器)
②增删改都可以定义触发器
③before、after可以定义触发的时机
5、触发器中经常使用new、old
insert里面可以有new
delete里面可以有old
update里面可以有new、old
6、使用触发器的场合
一般用来进行审计使用:产品价格表里面的价格这个列,只要是有人对这个表的这个列进行更新,就要保存修改前和修改后的值,将这个信息记录到一个单独的表中(审计表)
7、要求你将触发器的例子保存到笔记中
①insert触发器(new)
②delete触发器(old)
③update触发器(new、old)
④before、after
六十八、event
1、周期性执行
①linux里面的at、crontab
②MySQL里面的event
2、event的核心知识点
①执行一次
CREATE EVENT myevent ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 MINUTE DO begin UPDATE t1 SET mycol = mycol + 1; end
②周期性执行
CREATE EVENT myevent ON SCHEDULE EVERY 1 DAY STARTS STR_TO_DATE(‘2017-05-01 20:00:00’,'yyyy-mm-dd hh24:mi:ss') DO begin UPDATE t1 SET mycol = mycol + 1; end