1. DDL应用
1.1 数据定义语言
1.2 库定义
1.2.1 创建数据库
create database school charset utf8mb4; #指定字符集
create database school charset utf8mb4 collate utf8mb4_bin; #指定校对规则(默认大小写不敏感)
show charset; #查看数据库中支持的字符集
show cllocation; #查看校对规则
建库规范:
1.库名不能有大写字母
2.建库要加字符集
3.库名不能有数字开头
4. 库名要和业务相关
建库标准语句
damao[(none)]>create database test charset utf8mb4;
Query OK, 1 row affected (0.01 sec)
damao[(none)]>show create database test;
+----------+------------------------------------------------------------------+
| Database | Create Database |
+----------+------------------------------------------------------------------+
| test | CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+------------------------------------------------------------------+
1 row in set (0.00 sec)
damao[(none)]>
1.2.2 删除数据库(生产中禁止使用)
damao[(none)]>drop database test;
1.2.3 查询及修改数据库
show create database test; #查看数据库的字符集及较对规则
alter database test charset utf8;
注意:修改字符集不会使数据库中原有的数据字符集发生改变,只会改变新数据的字符集,所以要将原有的数据导出更改字符集再进行导入。
注意:修改字符集,修改后的字符集一定是原字符集的严格超集
1.3 表定义
1.3.1 创建表
create table stu(
列1 属性(数据类型、约束、其他属性) ,
列2 属性,
列3 属性
) 存储引擎,字符集编码,注释;
1.3.2 建表
use school; #首先要进入到相应的库中
CREATE TABLE stu(
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '学号',
sname VARCHAR(64) 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 DATETIME NOT NULL DEFAULT NOW() COMMENT '入学时间'
) ENGINE=INNODB CHARSET=utf8mb4 COMMENT '学生表';
建表规范
1. 表名小写
2. 不能是数字开头
3. 注意字符集和存储引擎
4. 表名和业务有关
5. 选择合适的数据类型
6. 每个列都要有注释
7. 每个列设置为非空,无法保证非空,用0来填充。
1.3.3 删除表(生产中禁用命令)
drop table stu; *删除整个表(表结构+数据行)
truncate table stu; *只会删除表中的数据行,不会删除表结构
1.3.4 修改表
1.在school库的stu表中添加qq列
alter table stu add qq varchar(20) not null unique comment 'QQ号';
2.在sname后加入地址列
alter table stu add addr varchar(64) not null commit '地址' after sname;
3.在id列前加入新列 num
alter table stu add num int not null comment '数字' first;
4.
alter table stu drop num;
alter table stu drop addr;
alter table stu drop qq;
5.修改sname列的数据类型属性
alter table stu modify sname varchar(32) not null;
6.将sgender列改为sg列,将数据类型改为char类型
alter table stu change sgender sg tinyint not null default 0 comment '0是女生,1是男生';
desc stu;
7.修改表名
alter table stu reanme to xuesheng;
说明:归档表,日志表
作为一个企业或者DBA,我们通常会有这种想法,数据是一个公司的核心命脉,应该需要永久保存,很多时候DBA和开发沟通的时候,开发人员也会这么告诉我们,这份数据非常重要,数据需要永久保存。然而,如果将数据库的数据永久保存,那么迟早有一天,你会拥有一个非常大的数据库。作为一个DBA,通常为了业务对数据库的操作性能考虑和存储容量的考虑。我们会建议对数据库里大表进行数据归档,例如将使用的高频数据保留在当前表,对低频数据保留在归档表中,或定期对数据进行归档,或当数据达到一定量时对数据表进行归档处理;
归档表原理操作(类似于日志切割)
1.方式一
alter table stu rename to stu_2019_11; *将旧表改名
create table stu like stu_2019_11; *创建新表
2.方式二
Oracle 物化视图 (了解)
面试题:若开发要紧急上线DDL SQL,如何进行评估,请写审核SQL要点
答:SQL语句是数据DDL操作,是属于列的添加操作
直接执行时会产生表锁,对业务的影响较大,数据量大,业务量大时,对于业务影响较大。
所以我们推荐
(1)最好业务不繁忙做
(2)使用 pt-osc(percona-toolkit) 工具来进行online DDL,减少对业务的影响
https://www.percona.com/software/database-tools/percona-toolkit
(3)对于归档表,可以使用pt-archiver 自己扩展.
1.3.5 表属性查询
use school *进入到指定库
show tables; *查看表
desc stu; *查看表结构
show create table stu; *查看表(列)属性
2. DCL 数据控制语言
grant 权限 on 库表 to 用户名@'白名单' identified by '密码';
revoke 权限 on 库表 from 用户名@'白名单' identified by '密码';
3. DML 数据操纵语言
主要对表中数据行操作
3.1 insert 数据插入
-----标准写法
use database school;
desc stu;
INSERT INTO stu(id,sname,sage,sg,sfz,intime)
VALUES
(1,'zs',18,'m','123456',NOW());
-----省事写法
INSERT INTO stu
VALUES
(2,'ls',18,'m','1234567',NOW());
--- 针对性的录入数据
INSERT INTO stu(sname,sfz)
VALUES ('w5','34445788');
--- 同时录入多行数据
INSERT INTO stu(sname,sfz)
VALUES
('w55','3444578d8'),
('m6','1212313'),
('aa','123213123123');
SELECT * FROM stu;
3.2 数据修改(更新)
update stu set age=18 where name='zs';
注意:update语句必须要加where。
3.3 delete 数据删除
-----删除id为4的数据行
delete from stu where id=4;
------若不跟条件,则删除所有数据行,类似于 truncate table stu
delete from stu ;
说明:
DELETE 语句数据逻辑删除,磁盘空间不会立即释放,会产生碎片.
truncate会立即释放磁盘空间
思考: 2亿行的大表,批量删除5000w(按时间条件)
3.4 伪删除
删除id=5的行,伪删除实现
ALTER TABLE stu ADD state TINYINT NOT NULL DEFAULT 1;
SELECT * FROM stu;
原语句:
DELETE FROM stu WHERE id=5;
替换为:
UPDATE stu SET state=0 WHERE id=5;
原业务语句:
SELECT * FROM stu;
替换为:
SELECT * FROM stu WHERE state=1;
4. DQL 数据查询语言 ********
4.1 select ******
4.1.1 单独使用
(1)查询参数
SELECT @@datadir;
SELECT @@port;
SELECT @@socket;
SELECT @@basedir;
SELECT @@innodb_flush_log_at_trx_commit;
SHOW VARIABLES ; **配置文件中的所有参数
(2)简易计算
select 1024*1024;
select 1+1;
(3)函数查询
SELECT NOW();
SELECT DATABASE();
SELECT USER();
SELECT CONCAT("hello world");
SELECT CONCAT(USER,"@",HOST) FROM mysql.user;
SELECT GROUP_CONCAT(USER,"@",HOST) FROM mysql.user;
https://dev.mysql.com/doc/refman/5.7/en/func-op-summary-ref.html?tdsourcetag=s_pcqq_aiomsg
4.1.2 配合多子句(单表查询标准用法)
多子句应用顺序: *****
(1) FROM 必须使用的
(2) WHERE
(3) GROUP BY
(5) HAVING
(6) ORDER BY
(7) LIMIT
(1)单表子句 ---from
SELECT 列1,列2 FROM 表
SELECT * FROM 表
例:
--- 1. 查询city表中的所有数据(不要对大表进行操作)
SELECT * FROM city;
--- 2. 查询city表中所有的name和population
SELECT NAME,population FROM city;
(2)单表子句----where
SELECT 列1,列2 FROM TABLE WHERE 条件;
1.where 配合等值查询
--- 查询中国所有城市的信息
SELECT * FROM city WHERE countrycode='CHN';
-- 查询北京市的信息
SELECT * FROM city WHERE NAME='peking';
-- 查询甘肃省所有城市信息
SELECT * FROM city WHERE district='gansu';
2.where 的不等值查询(> < >= <= !=)
--- 1. 城市人口小于100人的城市
SELECT * FROM city WHERE population<100;
--- 2. 不是中国的城市信息
SELECT * FROM city WHERE countrycode <> 'CHN';
3.where 配合 like语句使用(模糊查询)
--- 1. 查询国家代号是CH开头的城市信息.
SELECT * FROM city WHERE countrycode LIKE 'CH%';
注意: LIKE 语句 百分号不要出现在查询条件前,因为查询不走索引
4.where 配合逻辑连接符(and or)
--- 1. 中国城市人口大于500w的城市
SELECT * FROM city WHERE countrycode='CHN' AND population>5000000 ;
--- 2. 中国或者美国城市信息
SELECT * FROM city WHERE countrycode='CHN' OR countrycode='USA';
5.where配合in语句(or)
--- 中国或者美国城市信息
SELECT * FROM city WHERE countrycode IN ('CHN','USA');
6.where 配合 between ...and....(and)
--- 查询 人口数量在100w-200w之间的城市
SELECT * FROM city WHERE population >= 1000000 AND population <= 2000000;
SELECT * FROM city WHERE population BETWEEN 1000000 AND 2000000;
(3)group by (分组)+ 聚合函数应用
常用聚合函数
MAX() 最大值
MIN() 最小值
AVG() 平均值
COUNT() 数量
SUM() 求和
GROUP_CONCAT() 列转行
说明:
有 GROUP by子句,必然会有聚合函数
在业务查询需求中,需要对于表中数据按照数据特点进行分别统计时,GROUP BY + 聚合函数来实现
--- 1. 统计世界的所有人口总和
SELECT SUM(population) FROM city ;
--- 2. 统计国家的总人口数量
SELECT countrycode, SUM(population) FROM city GROUP BY countrycode ;
--- 3. 统计中国每个省的总人口数
SELECT countrycode,district , SUM(population) FROM city GROUP BY district;
--- 5. 统计中国每个省的城市名列表.
SELECT district,GROUP_CONCAT(NAME) FROM city WHERE countrycode='CHN' GROUP BY district;
关于 GROUP BY 的限制
group by的工作原理,先将group by之后的所写之列进行排序,然后去重,再将函数中包含的列进行函数运算;
damao[(none)]>select countrycode,district,sum(population) from world.city group by district;
ERROR 1055 (42000): Expression
-- #1 of SELECT list is not in GROUP BY clause and contains nonaggregated
-- column 'world.city.CountryCode' which is not functionally dependent
-- on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
--- sql_mode=only_full_group_by
1. 在 SELECT 后的条件,不在 GROUP BY 后
2. 在 SELECT 后的条件,不在函数里包裹
3. 如果select后列是唯一值时候,就不会报错
5. GROUP BY 的条件列是主键或者唯一键时.
总结: sql_mode=only_full_group_by 为了防止出现结果集1对多的关系.
(4)having
作用:用于进一步过滤,在group by 之后执行
where | group by |having #使用顺序
例:统计中国每个省的总人口数,只打印总人口数小于100万
select district,sum(population) from city
where countrycode='CHN'
group by district
having sum(population) <1000000;
(5)order by + limit
作用:用于将将指定列数据进行排序
----1.查看中国所有的城市,并按人口数进行排序(从大到小)
select name,population from city
where countrycode='CHN'
order by population desc;
注:加上desc表示逆序(从大到小),不加为升序(从小到大)
----2.统计中国各个省的总人口数量,按照总人口从大到小排序
SELECT district AS 省 ,SUM(Population) AS 总人口
FROM city
WHERE countrycode='chn'
GROUP BY district
ORDER BY 总人口 DESC ;
----3.统计中国,每个省的总人口,找出总人口大于500w的,并按总人口从大到小排序,只显示前三名
SELECT district, SUM(population) FROM city
WHERE countrycode='CHN'
GROUP BY district
HAVING SUM(population)>5000000
ORDER BY SUM(population) DESC
LIMIT 3 ; 注:此时相当于为limit 0,3. 跳过0行,显示3行
注:LIMIT N ,M --->跳过N,显示一共M行
LIMIT 5,5 跳过五行,一共显示5行。显示6-10行
SELECT district, SUM(population) FROM city
WHERE countrycode='CHN'
GROUP BY district
HAVING SUM(population)>5000000
ORDER BY SUM(population) DESC
LIMIT 5,5;
4.1.3 distinct:去重复
----从city表中查出国家名称
SELECT countrycode FROM city ;
SELECT DISTINCT(countrycode) FROM city ;
4.1.4 联合查询- union all 将多个select的数据合并(纵向合并)显示
-- 中国或美国城市信息
SELECT * FROM city
WHERE countrycode IN ('CHN' ,'USA');
SELECT * FROM city WHERE countrycode='CHN'
UNION ALL
SELECT * FROM city WHERE countrycode='USA'
说明:一般情况下,我们会将 IN 或者 OR 语句 改写成 UNION ALL,来提高性能
UNION 去重复
UNION ALL 不去重复
4.1.5 join 多表连接查询
案例准备,按需创建表
CREATE DATABASE school CHARSET utf8mb4;
USE school
CREATE TABLE student(
sno INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '学号',
sname VARCHAR(20) NOT NULL COMMENT '姓名',
sage TINYINT UNSIGNED NOT NULL COMMENT '年龄',
ssex ENUM('f','m') NOT NULL DEFAULT 'm' COMMENT '性别'
)ENGINE=INNODB CHARSET=utf8;
CREATE TABLE course(
cno INT NOT NULL PRIMARY KEY COMMENT '课程编号',
cname VARCHAR(20) NOT NULL COMMENT '课程名字',
tno INT NOT NULL COMMENT '教师编号'
)ENGINE=INNODB CHARSET utf8;
CREATE TABLE sc (
sno INT NOT NULL COMMENT '学号',
cno INT NOT NULL COMMENT '课程编号',
score INT NOT NULL DEFAULT 0 COMMENT '成绩'
)ENGINE=INNODB CHARSET=utf8;
CREATE TABLE teacher(
tno INT NOT NULL PRIMARY KEY COMMENT '教师编号',
tname VARCHAR(20) NOT NULL COMMENT '教师名字'
)ENGINE=INNODB CHARSET utf8;
INSERT INTO student(sno,sname,sage,ssex)
VALUES
(1,'zhang3',18,'m'),
(2,'zhang4',18,'m'),
(3,'li4',18,'m'),
(4,'wang5',19,'f'),
(5,'zh4',18,'m'),
(6,'zhao4',18,'m'),
(7,'ma6',19,'f'),
(8,'oldboy',20,'m'),
(9,'oldgirl',20,'f'),
(10,'oldp',25,'m');
INSERT INTO teacher(tno,tname) VALUES
(101,'oldboy'),
(102,'hesw'),
(103,'oldguo');
INSERT INTO course(cno,cname,tno)
VALUES
(1001,'linux',101),
(1002,'python',102),
(1003,'mysql',103);
INSERT INTO sc(sno,cno,score)
VALUES
(1,1001,80),
(1,1002,59),
(2,1002,90),
(2,1003,100),
(3,1001,99),
(3,1003,40),
(4,1001,79),
(4,1002,61),
(4,1003,99),
(5,1003,40),
(6,1001,89),
(6,1003,77),
(7,1001,67),
(7,1003,82),
(8,1001,70),
(9,1003,80),
(10,1003,96);
语法
查询张三的家庭住址
SELECT A.name,B.address FROM
A JOIN B
ON A.id=B.id
WHERE A.name='zhangsan';
多表练习SQL题
-- 1. 每位老师讲的课程名称
SELECT teacher.tno,teacher.tname,GROUP_CONCAT(course.cname)
FROM teacher
JOIN course
ON teacher.tno=course.tno
GROUP BY teacher.tno;
思考: 如果老师名重名,或者老师讲多门课,怎么办?
-- 2. 每位学员学习了几门课?
SELECT student.sno,student.sname,COUNT(sc.cno)
FROM student
JOIN sc
ON student.sno=sc.sno
GROUP BY student.sno;
-- 3. 每位学员学习了几门课及课程名称列表?
SELECT
student.sno,
student.sname,
COUNT(sc.cno),
GROUP_CONCAT(course.cname)
FROM student
JOIN sc
ON student.sno=sc.sno
JOIN course
ON sc.cno=course.cno
GROUP BY student.sno;
** case when ...then.. end 语句**
5. 写多表连接技巧
1. 相关表
2. 找相关表关联条件
E-R 图 (自己扩展) ----> 开发DBA要做的事情
外连接
A left join B
A 表所有的数据+B表满足关联条件的数据
A right join B
B表所有的数据+A 满足关联条件的数据
实现外连接原生功能,需要把where的条件改为and/
mysql> select city.name,city.population ,country.name from city left join country on city.countrycode=country.code and city.population<100 order by population desc ;
结论: left join 应用场景,强制驱动表(关联查询中结果集小的)
- where 条件
- 原始表大小
6. 别名的应用
表别名: 给表设计的别名,在任何子句中调用
列别名: 给select 后的列设定别名,在having 和 order by子句中调用
表别名:
select a.tname AS "老师姓名" ,group_concat(d.sname) AS "不及格的学生"
from teacher AS a
join course AS b
on a.tno = b.tno
join sc AS c
on c.cno = b.cno
join student AS d
on d.sno = c.sno
where c.score < 60
group by a.tno;
列别名:
select
student.sno AS 学生学号 ,
student.sname AS 学生姓名,
avg(sc.score) AS 平均成绩
from student
join sc
on student.sno=sc.sno
group by sutdent.sno
having 平均成绩 >85
==================
子查询 : (自己了解)
高级SQL编程: 内置函数,存储过程,函数,视图,事件,触发器,游标,Json开发 (自己了解)
==================
7. show 语句
show databases ; 查看所有库名
show tables; 查看当前库下的所有表名.
show tables from world; 查看world库下的所有表
show create database world; 查看建库语句
show create tables city; 查看建表语句
show [global] variables like '%trx%'; 查看参数信息
show grants for root@'localhost'; 查看用户权限信息
show [full] processlist; 查看会话连接情况
show engines; 查看当前数据库支持的引擎.
show charset; 查看当前数据库支持的字符集.
show collation; 查看当前数据库支持的排序规则.
show [global] status; 查看当前数据库的状态信息.
show status like '%lock%'\G 模糊查询数据库状态.
show master status; 查看当前使用的二进制日志信息.
show binary logs; 查看所有二进制日志信息.
show binlog evnets in 'xxxx' 查看二进制日志事件信息.
show relaylog events in 'xxx' 查看中继日志事件信息.
show slave status \G 查看从库复制状态信息.
show engine innodb status \G 查看InnoDB引擎相关状态信息.
======================
8. 元数据获取
8.1 什么是元数据?
库,表 : 属性(字符集,校对规则,数据类型,存储引擎,约束,其他数据)
权限 :
状态信息:
等.
8.2 元数据获取方法
show语句 : 封装好的基础功能,可以实现大部分的元数据查询需求.
information_schema<视图>库: mysql 给我们定义好的元数据查询的方法.
8.3 information_schema<视图>库
应用场景: 做数据库资产统计.
tables :
TABLE_SCHEMA : 表所在的库
TABLE_NAME : 表名
ENGINE : 引擎
TABLE_ROWS : 表的行数
AVG_ROW_LENGTH: 平均行长度
INDEX_LENGTH : 索引长度
TABLE_COMMENT : 表的注释
create view v_xxx as
select a.tname AS "老师姓名" ,group_concat(d.sname) AS "不及格的学生"
from teacher AS a
join course AS b
on a.tno = b.tno
join sc AS c
on c.cno = b.cno
join student AS d
on d.sno = c.sno
where c.score < 60
group by a.tno;
select * from v_xxx ;
例子:
----- 1. 统计所有库下的表的个数
select table_schema,count(table_name) from information_schema.tables group by table_schema;
----- 2. 统计不同存储引擎的表名
select engine,group_concat(table_name) from information_schema.tables group by engine;
-----3. 统计所有非系统表,非InnoDB的表
mysql
information_schema
performace_schema
sys
SELECT table_schema,table_name ,ENGINE
FROM information_schema.tables
WHERE table_schema NOT IN ('mysql','information_schema','performance_schema','sys')
HAVING ENGINE != 'innodb';
作业:
-- 5. 统计总数据量(不包含系统表)
-- 6. 统计每个库的数据量(不包含系统表)
SELECT
table_schema,
SUM( TABLE_ROWS * AVG_ROW_LENGTH + index_length)/1024/1024 AS "total_mb"
FROM information_schema.tables
WHERE table_schema NOT IN ('mysql','information_schema','performance_schema','sys')
GROUP BY table_schema
ORDER BY total_mb DESC;
扩展题
-- 7. 将school库下所有的数据字典信息(列名,数据类型,注释信息)进行统计
例如:
id int 城市id
name varchar 城市名
SELECT column_name,column_type,column_comment
FROM information_schema.columns
WHERE table_schema='school';
.....
-- 8. 模仿以下语句,生成数据库下单表的备份语句(不包含系统表),并保存至/backup/sh/bak.sh
例子语句:
mysqldump -uroot -p123 world city >/backup/world_city.sql
mysqldump -uroot -p123 world city >/backup/world_city.sql
mysqldump -uroot -p123 world city >/backup/world_city.sql
mysqldump -uroot -p123 world city >/backup/world_city.sql
mysqldump -uroot -p123 world city >/backup/world_city.sql
mysqldump -uroot -p123 world city >/backup/world_city.sql
mysqldump -uroot -p123 world city >/backup/world_city.sql
mysqldump -uroot -p123 world city >/backup/world_city.sql
mysqldump -uroot -p123 world city >/backup/world_city.sql
mysqldump -uroot -p123 world city >/backup/world_city.sql
select concat('mysqldump -uroot -p123 ' ,table_schema, ' ' ,table_name ', >/backup/',table_schema,'_',table_name,'.sql' )
from information_schema.tables
where table_schema not in ('mysql','information_schema','performance_schema','sys')
into outfile '/backup/sh/bak.sh';