常用的sql分类
DDL:数据定义语言DCL:数据控制语言DML:数据操作语言DQL:数据的查询语言
数值类型
tinyint : -128~127int :-2^31~2^31-1(10位长度,超过的一般都放在字符类型了)说明:手机号是无法存储到int的。一般是使用char类型来存储收集号

字符类型
char(11) 立即分配11个字符长度的存储空间,如果存不满,空格填充。varchar(11) 在存储字符串时,自动判断字符长度,按需分配存储空间,最大字符长度11个varchar会单独申请一个字符长度的空间存字符的长度(255以上会占用2个字符空间)enum('bj','tj','sh') 枚举类型,存放的是下标,适合已知的固定值列表,可以很大程度的优化我们的索引结构。

时间类型
DATETIME范围为从 1000-01-01 00:00:00.000000 至 9999-12-31 23:59:59.999999TIMESTAMP1970-01-01 00:00:00.000000 至 2038-01-19 03:14:07.999999(时间戳)

列属性
约束(一般建表时添加):primary key 主键约束,设置为主键的列,此列的值必须非空且唯一,主键在一个表中只能有一个,但是可以有多个列一起构成。not null 非空约束,列值不能为空,也是表设计的规范,尽可能将所有的列设置为非空。可以设置默认值为0。unique key 唯一键,列值不能重复。unsigned 无符号,针对数字列,非负数。其他属性:key 索引,可以在某列上建立索引,来优化查询,一般是根据需要后添加。default 默认值,列中,没有录入值时,会自动使用default的值填充。auto_increment 自增长,针对数字列,顺序的自动填充数据(默认是从1开始,将来可以设定起始点和偏移量)。comment 注释。
字符集
utf8 占用3个字节utf8mb4 一般常用的,占用4个字节,支持emojiutf8mb4_general_ci 大小写不敏感utf8mb4_bin 大小写敏感
DDL应用(数据定义语言)
创建数据库
create database school;create schema sch;show charset;show collation;CREATE DATABASE test CHARSET utf8;create database xyz charset utf8mb4 collate utf8mb4_bin;建库规范:1.库名不能有大写字母2.建库要加字符集3.库名不能有数字开头4.库名不能是数据库内部的关键字
删除数据库(生产禁用)
mysql> drop database oldboy;
修改数据库
SHOW CREATE DATABASE school;ALTER DATABASE school CHARSET utf8;注意:修改字符集,修改后的字符集一定是原字符集的严格超集
查询数据库
show databases;show create database oldboy;
创建表
use 库名;create table stu(列1 属性(数据类型、约束、其他属性) ,列2 属性,列3 属性)use school;CREATE TABLE stu(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '学号',sname VARCHAR(255) NOT NULL COMMENT '姓名',sage TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '年龄',sgender ENUM('m','f','n') NOT NULL DEFAULT 'n' COMMENT '性别' ,sfz CHAR(18) NOT NULL UNIQUE COMMENT '身份证',intime TIMESTAMP NOT NULL DEFAULT NOW() COMMENT '入学时间') ENGINE=INNODB CHARSET=utf8 COMMENT '学生表';建表规范:1. 表名小写2. 不能是数字开头3. 注意字符集和存储引擎4. 表名和业务有关5. 选择合适的数据类型6. 每个列都要有注释7. 每个列设置为非空,无法保证非空,用0来填充。
删除表(生产禁用)
drop table t1;
修改表
生产中 alter 的话,数据量大的情况下会锁表,所以需要借助 ps-osc 工具 或者手动 copy 一个表 在copy表做完操作给替换掉原来的表
在stu表中添加qq列DESC stu;ALTER TABLE stu ADD qq VARCHAR(20) NOT NULL UNIQUE COMMENT 'qq号';在sname后加微信列ALTER TABLE stu ADD wechat VARCHAR(64) NOT NULL UNIQUE COMMENT '微信号' AFTER sname ;在id列前加一个新列numALTER TABLE stu ADD num INT NOT NULL COMMENT '数字' FIRST;DESC stu;删掉列(危险)ALTER TABLE stu DROP num;修改sname数据类型的属性ALTER TABLE stu MODIFY sname VARCHAR(128) NOT NULL ;将sgender 改为 sg 数据类型改为 CHAR 类型ALTER TABLE stu CHANGE sgender sg CHAR(1) NOT NULL DEFAULT 'n' ;DESC stu;
创建一个表结构一样的表
create table test like stu;
DQL应用(查询表)
--快速构建数据库多表逻辑关系:ER图--查询表结构:desc city;--查询建表信息:show create table name;--单独使用:select variables like '%server%'; #模糊查询关键字的命令有哪些select @@port;select @@server_id;select @@basedir;--跟函数:select now();select databases();
select 单表
查询数据内容
单表语法:select 列 from 表 where 条件 group by 条件 having 条件 order by 条件 limit 行数;group by 常用函数:MAX() 列的最大值MIN() 列的最小值AVG() 列的平均值COUNT() 列的总行数SUM() 列值之和GROUP_CONCAT() 聚合函数,将列转成行,多个值转换到一行上CONCAT() 将列的值拼接,拼接字符串group by 条件 #用来把条件值唯一化,过滤掉重复的having 条件 #等同于where,必须在group by之后order by 条件 #将条件列从小到大排序,条件后边加上desc是从大到小排序limit 行数 #用于限制查询结果的行数,limit 3,5 跳过前三行,从第四行开始,显示出来5行
--查询limit表的前5列select * from city limit 5;##select 配合 where--具体查询select name from city where countrycode='CHN';select name from city where countrycode='CHN' and population > 1000;--模糊查询select * from city where countrycode like 'ch%';前后后加 % 极大影响性能,因为不走索引,如果数据业务中有大量需求的,用ElasticSearch来替代##select 配合 group by + 聚合应用--统计每个国家,城市的个数select countrycode,count(id) from city group by countrycode;--统计每个国家的总人口数select countrycode,sum(population) from city group by coutrycode;--统计每个国家 省的个数select coutrycode,count(distinct district) from city group by countrycode;--统计中国 每个省的总人口数select district,sum(population) from city where coutrycode='CHN' group by district;--统计中国 每个省份下的城市名字列表select district,group_concat(name) from city where countrycode='CHN' group by district;select concat(district,":",group_concat(name)) from city where countrycode='CHN' group by district;##select 配合 having--统计所有国家总人口数量,将总人口大于1亿的过滤出来select countrycode,sum(population) from city group by coutrycode hving sum(population)>100000000;##select 配合 order by(默认从小到大,从大到小后边加 desc)--统计所有国家总人口数量,将总人口大于50w的排序过滤出来select countrycode,sum(population) from city group by coutrycode hving sum(population)>500000 order by sum(population) desc;##select 配合 limit##limit 3,4 跳过前三行,从第四行开始,显示出来4行--统计所有国家总人口数量,将总人口大于50w的排序过滤出来,只显示前三行select countrycode,sum(population) from city group by coutrycode hving sum(population)>500000 order by sum(population) desc limit 3;--统计所有国家总人口数量,将总人口大于50w的排序过滤出来,显示第4到6行select countrycode,sum(population) from city group by coutrycode hving sum(population)>500000 order by sum(population) desc limit 3,3;##union 和 union all(多个结果集合并)union 会做去重union all 不会做去重select * from city where countrycode='CHN' union all select * from city where countrycode='USA';
select 多表
查询多表数据内容
最重要的是找到多张表之间的关联条件列
列书写格式:表名.列名
小技巧:先找好涉及到的所有表 from join on 列出来以后,再写开头select查询信息,最后拼接过滤条件
注意:为性能考虑,驱动表(from后的表)一定要选择数据行最少的表,后续的所有关联列尽量是主键或者唯一键(一般表设计的时候考虑的),至少要建立一个索引
多表语法: 多表查询中join 和on 是成对出现的 而且不能跨表只能通过关联表 A和B B和C 不能A和Cselect 列from 表1join 表2on 表1条件 = 表2条件join 表3on 表2条件 = 表3条件where 条件 group by 条件 having 条件 order by 条件 limit
--统计zhang3,学习了几门课select student.name,count(sc.cno)from student join scon student.sno = sc.snowhere student.name="zhang3";--查询zhang3,学习的课程名称有哪些?select student.name,group_concat(course.cname)from student join scon student.sno=sc.snojoin courseon course.cno=sc.cnowhere student.name="zhang3"group by student.name;--查询oldguo老师教的学生名和个数select teacher.name,group_concat(student.name),count(student.name)from teacher join courseon teacher.tno = course.tnojoin scon sc.cno = course.cnojoin studenton student.sno = sc.snowhere teacher.name="oldguo"group by teacher.name;--查询o1dguo所教课程的平均分数select teacher.name,AVG(sc.score)from teacher join courseon course.tno = teacher.tnojoin scon sc.cno = course.cnowhere teacher.name='oldguo'group by sc.cno;--每位老师所教课程的平均分,并按平均分排序select teacher.name,course.name,AVG(sc.score)from teacher join courseon course.tno = teacher.tnojoin scon sc.cno = course.cnogroup by teacher.name,course.name;--查询o1dguo所教的不及格的学生姓名select teacher.name,student.name,sc.scorefrom teacher join courseon teacher.tno = course.tnojoin scon sc.cno = course.cnojoin studenton student.sno = sc.snowhere teacher.name="oldguo" and sc.score < 60;--查询所有老师所教学生不及格的信息select teacher.name,group_concat(concat(student.name,": ",sc.score)) as "不及格的"from teacher join courseon teacher.tno = course.tnojoin scon sc.cno = course.cnojoin studenton student.sno = sc.snowhere sc.score < 60group by teacher.name;
查询表后拼接生成sql语句,保存sql文件
into outfile 的使用mysql> select concat("alter table ",table_schema," ",table_name," discard tablespace;") from information_schema.tables where table_schema='world' into outfile "/tmp/discard.sql"#整库导出一般是csv格式,也就是能用excel直接解析看的导出的路径需要在 my.cnf 指定安全数据限制secure-file-priv=
as 别名
表别名:将from或者join的表名可以定义一个值,在查询语句中涉及到该表名的可以用定义的值代替
列别名:将列名定义一个值,主要用于结果展示列名,在 order by和 having中可以调用
--表别名select t.name,group_concat(concat(st.name,": ",sc.score))from teacher as tjoin course as con t.tno = c.tnojoin scon sc.cno = c.cnojoin student as ston st.sno = sc.snowhere sc.score < 60group by t.name;--列别名select t.name as “老师”,group_concat(concat(st.name,": ",sc.score)) as "不及格的"from teacher as tjoin course as con t.tno = c.tnojoin scon sc.cno = c.cnojoin student as ston st.sno = sc.snowhere sc.score < 60group by t.name;
元数据获取(information_schema)
元数据是存储在“基表”中的
通过专用的DDL或者DCL语句进行元数据查询
show 是封装好的查询命令,提供元数据的基础查询
inofrmation_schema中保存了大量的元数据查询的视图
information_schema下table视图:TABLE_SCHEMA 表所在的行TABLE_NAME 表名ENGINE 存储引擎TABLE_ROWS 数据行AVG_ROW_LENGTH 平均行长度INDEX_LENGTH 索引长度表的数据量=平均行长度*数据行+索引长度(默认是字节,/1024是KB)
--查询所有的库和表的信息select table_schema,table_name from information_schema.tables;--对table_schema做过滤,并展示出所有的对应结果;group by 的使用select table_schema,group_concat(table_name) from information_schema.tables group by table_schema;--查询所有innodb引擎的表select table_schema,table_name from information_schema.tables where ENGINE="innodb";--统计world库中city表的数据量总大小(默认是字节,/1024是KB)select table_schema,TABLE_ROWS*AVG_ROW_LENGTH+INDEX_LENGTH from information_schema.tables where table_schema="world" and table_name="city";--表的数据量=平均行长度*行数+索引长度--统计每个库的数据量大小,并按从大到小排序select table_schema,(sum(TABLE_ROWS*AVG_ROW_LENGTH+INDEX_LENGTH))/1024 as kbfrom information_schema.tablesGROUP BY table_schemaORDER BY kb desc;--concat拼接做数据库分库分表备份语句生成selectconcat("mysqldump -uroot -p123 ",table_schema," ",table_name," > /bak/",table_schema,"_",table_name,".sql")from information_schema.tables;
show
show databases; 查看数据库名show tables; 查看表名show create database xx; 查看建库语句show create table xx; 查看建表语句show processlist; 查看所有用户连接情况show charset; 查看支持的字符集show collation; 查看支持的校队规则show grants for xx; 查看用户的权限信息show variables like '%xx%'; 查看参数信息show engines; 查看所支持的存储引擎类型show index from xxx; 查看表的索引信息show engine innodb status \G; 查看innod引擎的详细状态信息show binary logs; 查看二进制日志的列表信息show binlog events in 'xx'; 查看二进制日志的事件信息show master status; 查看mysql当前使用的二进制日志信息show slave status \G; 查看从库的状态信息show relaylog events in 'xx'; 查看中继日志的事件信息show status like 'xx'; 查看数据库整体状态信息
常见问题
--group by 操作中 sql_mode 报错 only_full_group_by##出现原因:1、在mysql 5.7 版本中 sql_mode 自带的严谨模式,在5.6 8.0版本中没有2、在有 group by 的 select 语句中,select后的条件列(非主键列),要么是group by后的列,要么是在group_concat()函数中包裹##解决办法:查询sql_mode默认值 mysql> select @@sql_mode;在mysql主配置文件中(/etc/my.cnf)将mysqld服务器端的配置里定义sql_mode的默认值sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
mysql的日志及增量恢复
二进制日志(binary log)
主要是用来记录Mysql内部的增删改等对数据库有更新的记录。
日志存放位置:/application/mysql/data/
查询binlog操作记录:mysqlbinlog mysql-bin.00020
配置文件:/etc/my.cnf下mysqld区间里面加入:log-bin=mysql.bin主要参数:mysql> show variables like '%log_bin%';+---------------------------------+------------------------------------------+| Variable_name | Value |+---------------------------------+------------------------------------------+| log_bin | ON 记录binlog || sql_log_bin | ON 临时不记录binlog |+---------------------------------+------------------------------------------+6 rows in set (0.00 sec)语法:mysqlbinlog 日志文件名 > all.sql拆库:mysqlbinlog -d cao 日志文件名 > cao.sql查询有什么操作:less cao.sql
##增量恢复--指定位置mysqlbinlog mysql-bin.000020 --start-position=365 --stop-position=456 -r pos.sql--指定开始时间和结束时间的mysqlbinlog mysql-bin.00021 --start-datetime='2021-03-19 02:32:50' --stop-datetime='2021-03-19 04:32:50' -t time.sql
错误日志(error log)
记录mysql再启动或者关闭或者运行中遇到的错误信息
配置文件:/etc/my.cnf下mysqld_safe区间里面加入:log-error=/data/3306/mysql_3306.err
查询日志(query log)
##普通查询日志(general query log):记录客户端连接信息和执行sql语句的信息(一般不启用)mysql> show variables like 'general_log%';+------------------+--------------------------------------------+| Variable_name | Value |+------------------+--------------------------------------------+| general_log | OFF || general_log_file | /usr/local/mysql-5.7.24/data/localhost.log |+------------------+--------------------------------------------+2 rows in set (0.00 sec)mysql> set global general_log=on;Query OK, 0 rows affected (0.00 sec)##慢查询日志(slow query log):记录查询时间超出指定值(long_query_time)的sql语句long_query_time=1log-slow-queries=/data/3306/slow.loglog_queries_not_using_indexes
