Mysql-的基础应用

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

时间


image.png

常用的: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;

image.png

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:成绩

image.png

多表连接例子

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;

image.png

3查询所有innodb引擎的表

select table_schema,table_name,engine from information_schema.tables
where engine='innodb';

4统计world库下的city表占用空间大小
公式:表的数据量=平均行长度行数+索引长度
avg_row_length
table_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';

字节


image.png

kb

SELECT table_name,(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024
FROM information_schema.TABLES
WHERE table_schema='world' AND table_name='city';
image.png

5统计world库数据量总大小

SELECT table_schema,SUM((AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH))/1024
FROM information_schema.TABLES
WHERE table_schema='world';
image.png

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;
image.png

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;
image.png

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

你可能感兴趣的:(Mysql-的基础应用)