常用的sql分类
DDL:数据定义语言
DCL:数据控制语言
DML:数据操作语言
DQL:数据的查询语言
数值类型
tinyint : -128~127
int :-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.999999
TIMESTAMP
1970-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个字节,支持emoji
utf8mb4_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列前加一个新列num
ALTER 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和C
select 列
from 表1
join 表2
on 表1条件 = 表2条件
join 表3
on 表2条件 = 表3条件
where 条件 group by 条件 having 条件 order by 条件 limit
--统计zhang3,学习了几门课
select student.name,count(sc.cno)
from student join sc
on student.sno = sc.sno
where student.name="zhang3";
--查询zhang3,学习的课程名称有哪些?
select student.name,group_concat(course.cname)
from student join sc
on student.sno=sc.sno
join course
on course.cno=sc.cno
where student.name="zhang3"
group by student.name;
--查询oldguo老师教的学生名和个数
select teacher.name,group_concat(student.name),count(student.name)
from teacher join course
on teacher.tno = course.tno
join sc
on sc.cno = course.cno
join student
on student.sno = sc.sno
where teacher.name="oldguo"
group by teacher.name;
--查询o1dguo所教课程的平均分数
select teacher.name,AVG(sc.score)
from teacher join course
on course.tno = teacher.tno
join sc
on sc.cno = course.cno
where teacher.name='oldguo'
group by sc.cno;
--每位老师所教课程的平均分,并按平均分排序
select teacher.name,course.name,AVG(sc.score)
from teacher join course
on course.tno = teacher.tno
join sc
on sc.cno = course.cno
group by teacher.name,course.name;
--查询o1dguo所教的不及格的学生姓名
select teacher.name,student.name,sc.score
from teacher join course
on teacher.tno = course.tno
join sc
on sc.cno = course.cno
join student
on student.sno = sc.sno
where teacher.name="oldguo" and sc.score < 60;
--查询所有老师所教学生不及格的信息
select teacher.name,group_concat(concat(student.name,": ",sc.score)) as "不及格的"
from teacher join course
on teacher.tno = course.tno
join sc
on sc.cno = course.cno
join student
on student.sno = sc.sno
where sc.score < 60
group 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 t
join course as c
on t.tno = c.tno
join sc
on sc.cno = c.cno
join student as st
on st.sno = sc.sno
where sc.score < 60
group by t.name;
--列别名
select t.name as “老师”,group_concat(concat(st.name,": ",sc.score)) as "不及格的"
from teacher as t
join course as c
on t.tno = c.tno
join sc
on sc.cno = c.cno
join student as st
on st.sno = sc.sno
where sc.score < 60
group 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 kb
from information_schema.tables
GROUP BY table_schema
ORDER BY kb desc;
--concat拼接做数据库分库分表备份语句生成
select
concat("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=1
log-slow-queries=/data/3306/slow.log
log_queries_not_using_indexes