SQL介绍
结构化的查询语言,关系型数据库通用的命令,遵循SQL92的标准(SQL_MODE)
SQL常用种类
DDL:数据定义语言
DCL:数据控制语言
DML:数据操作语言
DQL:数据查询语言
SQL引入
数据库的逻辑结构
库:
库名:不能数字,不能内置函数
库属性:字符集,排序规则
表:
表名:
表属性:存储引擎类型,字符集,排序规则
列名:
列属性:数据类型,约束,其他属性
数据行(记录):
字符集(charset)
相当于MySQL的密码本(编码表)
show charset;
utf8 :3个字节
utf8mb4(建议):4个字节,支持emoji
排序规则(校对规则)(collation)
show collation;
对于英文字符串的,大小写的敏感
utf8mb4_bin 什么都可以存
_ci的都是不明感的
数据类型介绍
数字:
整数:
tinyint 极小整数数据类型(0-255) 适合存放年龄
smallint 较小整数数据类型(-215到215-1)
int 常规(平均)大小的整数数据类型(-231到231-1)
浮点数:
略
字符串:
char:定长字符串类型 char(100) 不管字符串长度多长,都立即分配100个字符长度空间,未占满的空间使用空格占位
varchar: 变长字符串类型,每次存储数据之前,都要先判断一下长度,按需分配磁盘空间。会单独申请一个字符长度的空间存储字符长度(少于255,如果超过255以上,会占用两个存储空间)
如果选择两个数据类型:
1.少于255个字符串长度,定长的列值,选择char
2.多于255个字符长度,变长的字符串,选择varchar
enum:枚举数据类型
adress enum('sz','bj','sh'...)
1 2 3
时间
常用的:datetime timestamp
二进制:
略
DDL--库定义
数据定义语言
创建库
CREATE DATABASE zabbix CHARSET utf8mb4 COLLATE utf8mb4_bin;
查看库
SHOW DATABASES;
查看建库时的详细语句
SHOW CREATE DATABASE zabbix;
删除库
DROP DATABASE wordpress;
修改数据库字符集
注意:一定是从小往大了该,比如UTF8-->UTF8mb4
目标字符集一定是源字符集的严格超级
CREATE DATABASE sky;
SHOW CREATE DATABASE sky;
CREATE DATABASE `sky` /*!40100 DEFAULT CHARACTER SET latin1 */ <---- latin 1
修改
ALTER DATABASE sky CHARSET utf8mb4;
SHOW CREATE DATABASE sky;
CREATE DATABASE `sky` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ <-----utf8mb4
库的定义规范
1.库名使用小写字符
2.库名不能使用数字开头
3.不能是数据库内部关键字
4.必须设置字符集
DDL-表定义
列属性
PRIMARY KEY: 主键约束,表中只能有一个,非空且唯一
NOT NULL :非空约束,不允许空值
UNIQUE KEY :唯一键约束,不允许重复值
DEFAULT: 默认值,一般配合非空一起使用(NOT NULL)
UNSIGNED: 无符号,一般是配合数字列,非负数
COMMENT: 注释
AUTO_INCREMENT: 自增长的列,一般id列
创建表
CREATE TABLE stu (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '学号',
sname VARCHAR(255) NOT NULL COMMENT '姓名',
age TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '年龄',
gender ENUM('m','f','n') NOT NULL DEFAULT 'n' COMMENT '性别',
intime DATETIME NOT NULL DEFAULT NOW() COMMENT '入学时间'
)ENGINE INNODB CHARSET utf8mb4;
建表规范
1.表名小写字母,不能数字开头,不能是保留字符,尽量和业务有关
2.选择合适的数据类型以及长度
3.每隔列设置NOT NULL+DEFAUTL ,对于数据0填充,对于字符使用有效字符NULL
4.每个列必须加注释
5.表必须设置存储类型和字符集
6.主键列尽量是无关列数字列,最好自增长
7.ENUM类型不要保存数字,只能设置字符串类型
查询建表信息
SHOW TABLES;
SHOW CREATE TABLE stu;
创建一个表结构一样的表
CREATE TABLE test LIKE stu;
删除表
DROP TABLE test;
修改表
在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 UNIQUE COMMENT '身份证' FIRST ;
删除刚才添加的列删除
ALTER TABLE stu DROP num;
修改sname修改数据类型的属性
ALTER TABLE stu MODIFY sname VARCHAR(64) NOT NULL COMMENT '姓名';
将gender 改为sex 数据类型改为char类型
ALTER TABLE stu CHANGE gender sex VAR(4) NOT NULL COMMENT '性别';
如果业务量较大,还是紧急更表
方法一:
创建临时表,在临时表中修改,在rename回去
方法二:
pt-osc :percona-toolkits Online SCHEMA change
8.0貌似就不用了
DCL授权 回收权限
grant
grant all on *.* to root@'10.0.0.%' identified by '123456';
revoke
revoke delete on *.* from sky@'10.0.0.%';
DML
insert update delete
insert
DESC stu;
INSERT INTO stu values(1,'sky',18,'m',NOW());
查看
SELECT * FROM stu;
最规范
INSERT INTO stu(id,sname,age,sex,intime) VALUES(2,'lis',19,'f',NOW());
针对性录入
INSERT INTO stu(sname,age,sex) VALUES('wangwu',20,'m');
一次性录入多行数据
INSERT INTO stu(sname,age,sex)
VALUES ('aa',21,'n'),('bb',22,'f'),('cc',32,'m');
DQL介绍
select
show
select语句的应用
1.select单独使用的情况
select @@basedir;
select @@port;
select @@innodb_flush_log_at_trx_commint;
show variables like 'innodb%'; 模糊查询
select database(); 查看当前在哪个库
select now(); 查看当前时间
select 通用语法(单表)
select 列
from 表
where 条件
group by 条件
having 条件
order by 条件
limit
环境配置world.sql 网上可以找一下
desc city;
+-------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(32) | NO | | NULL | |
| CountryCode | char(3) | NO | | NULL | |
| District | char(20) | NO | | NULL | |
| Population | int(11) | NO | | 0 | |
+-------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
name 城市
countrycode 国家代码
district 区域
population 人口数
select * from city limit 5;
+----+----------------+-------------+---------------+------------+
| id | Name | CountryCode | District | Population |
+----+----------------+-------------+---------------+------------+
| 1 | kabul | AFG | Kabol | 1780000 |
| 2 | Qandahar | AFG | Qandahar | 237500 |
| 3 | Herat | AFG | Herat | 186800 |
| 4 | Mazar-e-sharif | AFG | balkh | 127800 |
| 5 | Amsterdam | NLD | Noord-Holland | 731200 |
+----+----------------+-------------+---------------+------------+
5 rows in set (0.00 sec)
select配合from子句使用
select 列, 列,列 from 表
查询表中所有信息
select * from city; (会降低性能)
查询表中 name和population的值
select name,population from city;
select配合 where使用
select 列,列,列 from 表 where 过滤条件
where等值条件查询
查询中国所有的城市名和人口数
SELECT name,population FROM city
WHERE countrycode='CHN';
where配合比较判断符查询(范围查询<> >= <=)
查询世界上小于100人的城市名和人口数
select name,population from city
where popluation<100;
where配合逻辑连接符(and or)
查询中国人口数量大于800w的城市名和人口数
select name,population from city
where countrycode='CHN' and popluation<8000000;
查询中国或美国的城市名和人口数
select name,population from city
where countrycode='CHN' or countrycode='USA';
查询世界上所有人口数量在500w到600w之间的
select name,population from city
where popluation > 5000000 and popluation < 6000000;
或者
select name,population from city
where population between 5000000 and 6000000;
where配合like子句 实现模糊查询
查询contrycode中有C开头的城市信息
SELECT NAME,population FROM city
WHERE countrycode LIKE 'C%';
注意 不要出现类似于%CH%前后都有百分号的语句,因为不走索引,性能极差
如果业务中有大量需求,我们使用‘ES’来代替
where 配合in语句
查询中国或美国的城市信息
select name,population from city
where countrycode in ('CHN','USA');
select 配合 GROUP BY + 聚合函数应用
常用聚合函数介绍
max() 最大值
min() 最小值
avg()平均值
count()计数
sum() 求和
group_concat()
group by的使用
将某列中有共同条件的数据行,分成一组,然后在进行聚合函数操作
关于group by的sql_mode
only_full_group_by
说明:
1、在5.7版本中mysql sql_mode参数中自带,5.6和5.8都没有
2、在带有group by 子句中的select中,select后的条件列(非主键列),要么是group by后的列,要么是group by 后的列,要么需要在函数中包裹
禁用:配置文件中
[mysqld] sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
统计每个国家,城市的个数
select countrycode, count(id) from city
group by countrycode ;
统计每个国家的总人口数
SELECT countrycode,SUM(population) FROM city
GROUP BY countrycode;
统计每个 国家 省 的个数
SELECT countrycode, COUNT(DISTINCT district) FROM city
GROUP BY countrycode;
DISTINCT去重
统计中国每个省的总人口数
SELECT district,SUM(population) FROM city
WHERE countrycode='CHN'
GROUP BY district;
统计中国 每个省城市的名字列表
SELECT district,GROUP_CONCAT(NAME) FROM city
WHERE countrycode='CHN'
GROUP BY district;
group_concat() 列转行
将名字改成: (beijing:shijingshan,haidian...)
SELECT CONCAT(district,":",GROUP_CONCAT(NAME)) FROM city
WHERE countrycode='CHN'
GROUP BY district;
SELECT 配合having应用
在group by执行之后在计算
统计所有国家的总人口数量,将总人口数大于1亿的过滤出来
SELECT countrycode,SUM(population) FROM city
GROUP BY countrycode
HAVING SUM(population)>100000000;
having 不走索引
SELECT 配合 ORDER BY
给最后的结果集进行排序
统计所有国家的总人口数量
将总人口数量大于5000w的过滤出来
并且安装从大到小顺序排列
SELECT countrycode,SUM(population) FROM city
GROUP BY countrycode
HAVING SUM(population)>50000000
ORDER BY SUM(population);
如果想从大到小 DESC
SELECT countrycode,SUM(population) FROM city
GROUP BY countrycode
HAVING SUM(population)>50000000
ORDER BY SUM(population)DESC;
SELECT 配合 LIMIT
显示多少行
LIMIT M,N 跳过m行,显示一共n行
LIMIT Y OFFSET X 跳过y行,显示一共y行
统计所有国家的总人口数量
将总人口数量大于5000w的过滤出来
并且安装从大到小顺序排列,只显示前3名
SELECT countrycode,SUM(population) FROM city
GROUP BY countrycode
HAVING SUM(population)>50000000
ORDER BY SUM(population)DESC
LIMIT 3;
显示4-6名
SELECT countrycode,SUM(population) FROM city
GROUP BY countrycode
HAVING SUM(population)>50000000
ORDER BY SUM(population)DESC
LIMIT 3,3; 跳过三行,显示三行
方法二
SELECT countrycode,SUM(population) FROM city
GROUP BY countrycode
HAVING SUM(population)>50000000
ORDER BY SUM(population)DESC
LIMIT 3 OFFSET 3;
unio和 union all
作用:多个结果集合并查询的功能
需求:查询中国或者美国的城信息
SELECT * FROM city WHERE countrycode='CHN' OR countrycode='USA';
改写为
性能比较好
SELECT * FROM city WHERE countrycode='CHN'
UNION ALL
SELECT * FROM city WHERE countrycode='USA';
union和union all的区别
union all 不做去重
union 会做去重
多表连接查询(内连接)
作用 单表数据不能满足查询需求时
多表连接基本语法要求
1.最核心的就是,找到多张表之前的关联条件
2.列书写时,必须是:表名.列明
3.所有涉及到的查询列,都放在select后
4.将所有的过滤,分组,排序等条件按照顺序写在on的后面
5.多张表
A
JOIN B
ON A.x=B.y
JOIN C
ON B.m=C.n
查询世界上小于100人的城市,所在的国家名,国土面积,城市名,人口数
SELECT
country.name,
country.SurfaceArea,
city.name,
city.Population
FROM city
JOIN country
ON city.CountryCode = country.Code
WHERE city.Population <100;
构建测试库以及表
构建
drop database school;
CREATE DATABASE school CHARSET utf8;
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');
INSERT INTO student(sno,sname,sage,ssex)
VALUES
(2,'zhang4',18,'m'),
(3,'li4',18,'m'),
(4,'wang5',19,'f');
INSERT INTO student
VALUES
(5,'zh4',18,'m'),
(6,'zhao4',18,'m'),
(7,'ma6',19,'f');
INSERT INTO student(sname,sage,ssex)
VALUES
('oldboy',20,'m'),
('oldgirl',20,'f'),
('oldp',25,'m');
INSERT INTO teacher(tno,tname) VALUES
(101,'oldboy'),
(102,'hesw'),
(103,'oldguo');
DESC course;
INSERT INTO course(cno,cname,tno)
VALUES
(1001,'linux',101),
(1002,'python',102),
(1003,'mysql',103);
DESC sc;
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 * FROM student;
SELECT * FROM teacher;
SELECT * FROM course;
SELECT * FROM sc;
他们之间的关系
student :学生表
sno: 学号
sname:学生姓名
sage: 学生年龄
ssex: 学生性别
==================
teacher :教师表
tno: 教师编号
tname:教师名字
==================
course :课程表
cno: 课程编号
cname:课程名字
tno: 教师编号
===================
score :成绩表
sno: 学号
cno: 课程编号
score:成绩
多表连接例子
1.统计zhang3,学习了几门课
SELECT student.sname,COUNT(sc.cno)
FROM student JOIN sc
ON student.sno=sc.sno
WHERE student.sname='zhang3';
2.查询zhang3,学习的课程名称有哪些
SELECT student.sname,GROUP_CONCAT(course.cname)
FROM student
JOIN sc
ON student.sno=sc.sno
JOIN course
ON sc.cno=course.cno
WHERE student.sname='zhang3'
GROUP BY student.sname;
3.查询oldguo老师教的学生名和个数
SELECT teacher.tname,GROUP_CONCAT(student.sname),COUNT(student.sname)
FROM teacher
JOIN course
ON teacher.tno=course.tno
JOIN sc
ON course.cno = sc.cno
JOIN student
ON sc.sno=student.sno
WHERE teacher.tname='oldguo'
GROUP BY teacher.tname;
4.查询oldguo所教课程的平均分
SELECT teacher.tname,AVG(sc.score)
FROM teacher
JOIN course
ON teacher.tno=course.tno
JOIN sc
ON course.cno=sc.cno
WHERE teacher.tname='oldguo'
GROUP BY sc.cno;
5.每位老师所教课程的平均分,并按照平均分排序
SELECT teacher.tname,course.cname,AVG(sc.score)
FROM teacher
JOIN course
ON teacher.tno=course.tno
JOIN sc
ON course.cno=sc.cno
GROUP BY teacher.tname,course.cname
ORDER BY AVG(sc.score)
6查询oldguo所教的不及格的学生姓名
SELECT teacher.tname,student.sname,sc.score
FROM teacher
JOIN course
ON teacher.tno=course.tno
JOIN sc
ON course.cno=sc.cno
JOIN student
ON sc.sno=student.sno
WHERE teacher.tname='oldguo' AND sc.score<60;
7查询所有老师所教学生不及格的信息
SELECT teacher.tname,GROUP_CONCAT(CONCAT(student.sname,":",sc.score))
FROM teacher
JOIN course
ON teacher.tno=course.tno
JOIN sc
ON course.cno=sc.cno
JOIN student
ON sc.sno=student.sno
WHERE sc.score<60
GROUP BY teacher.tno
别名的应用
表别名
SELECT t.tname,GROUP_CONCAT(CONCAT(st.sname,":",sc.score))
FROM teacher as t
JOIN course as c
ON t.tno=c.tno
JOIN sc
ON c.cno=sc.cno
JOIN student as st
ON sc.sno=st.sno
WHERE sc.score<60
GROUP BY t.tno
表别名是全局调用的
列别名
SELECT t.tname as 讲师,GROUP_CONCAT(CONCAT(st.sname,":",sc.score)) as 不及格
FROM teacher as t
JOIN course as c
ON t.tno=c.tno
JOIN sc
ON c.cno=sc.cno
JOIN student as st
ON sc.sno=st.sno
WHERE sc.score<60
GROUP BY t.tno
列别名可以被having和order调用
concat的应用 拼接
mysql> select concat(user,'@',host) from mysql.user;
+-------------------------+
| concat(user,'@',host) |
+-------------------------+
| [email protected].% |
| [email protected].% |
| [email protected].% |
| mysql.session@localhost |
| mysql.sys@localhost |
| root@localhost |
+-------------------------+
6 rows in set (0.00 sec)
元数据获取
元数据介绍
元数据是存储在'基表中'
通过专用的DDL语句,DCL语句进行修改
通过专用的视图进行元数据的查询
information_schema中保存了大量元数据查询的视图
show 命令是封装好功能,提供元数据查询基础功能
information_schema的基本应用(就是好多好多视图,提供很多方法)
视图的列子
mysql> create view aa as select teacher.tname,group_concat(concat(student.sname,":",sc.score))
from teacher
join course
on teacher.tno=course.tno
join sc
on course.cno=sc.cno
join student on sc.sno=student.sno
where sc.score<60
group by teacher.tno;
select * from aa;
+--------+--------------------------------------------------+
| tname | group_concat(concat(student.sname,":",sc.score)) |
+--------+--------------------------------------------------+
| hesw | zhang3:59 |
| oldguo | zh4:40,li4:40 |
+--------+--------------------------------------------------+
2 rows in set (0.00 sec)
tables视图
use information_schema;
desc tables;
TABLE_SCHEMA 表所在的库名
TABLE_NAME 表名
ENGINE 存储引擎信息
TABLE_ROWS 数据行
AVG_ROW_LENGTH 平均行长度
INDEX_LENGTH 索引的长度
例子说明
1显示所有的库和表的信息
mysql> select table_schema,table_name from information_schema.tables;
2显示所有的库和表的信息
select table_schema,group_concat(table_name)
from information_schema.tables
group by table_schema;
3查询所有innodb引擎的表
select table_schema,table_name,engine from information_schema.tables
where engine='innodb';
4统计world库下的city表占用空间大小
公式:表的数据量=平均行长度行数+索引长度
avg_row_lengthtable_rows+index_length
SELECT table_name,AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH
FROM information_schema.TABLES
WHERE table_schema='world' AND table_name='city';
字节
kb
SELECT table_name,(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024
FROM information_schema.TABLES
WHERE table_schema='world' AND table_name='city';
5统计world库数据量总大小
SELECT table_schema,SUM((AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH))/1024
FROM information_schema.TABLES
WHERE table_schema='world';
6统计每个库的数据量大小
SELECT table_schema,SUM((AVG_ROW_LENGTH*table_rows+INDEX_LENGTH))/1024 AS total_kb
FROM information_schema.TABLES
GROUP BY table_schema
ORDER BY total_kb DESC;
7配合concat() 函数拼接语句或命令
7.1 模仿一下语句,进行数据库的分库分表备份
mysqldump -ruoot -p123 world city>/bak/world_city.sql
SELECT
CONCAT("mysqldump -uroot -p123 ",table_schema," ",table_name
,">/bak/",table_schema,"_",table_name,".sql")
FROM information_schema.tables;
7.2模仿一下语句,进行批量生产world库所有表操作
ALTER TABLE world.city DISCARD TABLESPACE;
SELECT
CONCAT("ALTER TABLE ",table_schema,".",table_name,"DISCARD TABLESPACE")
FROM information_schema.tables
WHERE TABLE_SCHEMA='world';
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 lik '%xx%' 查看参数信息
show engines; 查看所有支持引擎类型
show index from xxx 查看表索引信息
show engine innodb status\G 查看innodb引擎详细状态信息
show binary logs 查看二进制日志的列表信息
show binlog events in ' 文件名' 查看二进制日志的事件信息
show master status; 查看mysql当前使用二进制日志信息
show slave status \G 查看从库状态
show relaylog events in ' ' 查看中继日志事件信息
show status like '' 查看数据库整体状态信息
导出数据
想要导出concat拼接的表
首先要在配置文件里添加 安全导出,要不然会报错
secure-file-priv=
空表示所有目录
mysql> select concat("alter table ",table_schema," ",table_name," discard tablespace;") from information_schema.tables where table_schema='world';
+---------------------------------------------------------------------------+
| concat("alter table ",table_schema," ",table_name," discard tablespace;") |
+---------------------------------------------------------------------------+
| alter table world city discard tablespace; |
| alter table world country discard tablespace; |
| alter table world countrylanguage discard tablespace; |
+---------------------------------------------------------------------------+
3 rows in set (0.01 sec)
导出
select concat("alter table ",table_schema," ",table_name," discard tablespace;") from information_schema.tables where table_schema='world' into outfile '/tmp/discard.sql';
cd /tmp
vim discard.sql
alter table world city discard tablespace;
alter table world country discard tablespace;
alter table world countrylanguage discard tablespace;
导入
sourec /tmp/discard.sql
只导出数据行
select * from city into outfile '/tmp/city.xlsx'
导出后就是ex