基础章节-01-MySQL数据库服务中级课程

1.00 课程知识章节说明

目前在互联网的实际应用中,各个企业都会比较关注自身网站的数据信息,既要保证数据信息的安全性,同时也要保证数据存储读取效率 并且在特殊的场景下,还要对存储的数据信息进行检索和分析;因此数据库服务业务已经在各行各业应用非常的广泛 对于互联网领域的技术人员,对于数据库服务知识的掌握,也将是在求职时必备的技能,有些时候还会绝对入职的定级和薪资水平。

1.06 数据库服务语句应用(实践)

1.6.1 操作管理语言获取帮助

在数据库服务中,SQL语句涉及到的语句非常的多,在实际应用过程中也未必都能记住,因此就需要掌握获取帮助的方法;

1.6.2 操作管理语句应用实践(DDL)

利用数据定于语言(DDL),负责管理数据库的基础数据(不会对表的内容修改),比如增删库、增删表、增删索引、增删用户等;

01 数据定义语言对数据库定义

数据库中的库是数据库服务结构中的重要组成部分,一个库就像是一个excel文档,库里含有表,一个表就是一个excel的sheet; 因此,对于数据库管理操作SQL语句命令,属于比较基础的数据库操作能力,需要重点关注; 创建数据库信息:

查看数据库信息: 数据库安装完毕后,默认的数据库说明:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 获取帮助信息_基本帮助信息
mysql > \h
# 获取帮助信息_语句分类帮助
mysql > help contents
mysql > ? contents
# 获取帮助信息_具体语句帮助
mysql > ? create
mysql > ? create database
mysql > create database oldboy;
mysql > create schema oldboy;
-- 创建新的数据库
mysql > create database oldboy character set utf8mb4;
mysql > create database oldboy charset utf8 collate utf8_general_mysql500_ci;
-- 创建新的数据库,并修改调整默认的字符编码
mysql > show databases;
-- 查看是否已经创建好
mysql > show create database oldboy;
-- 查看创建库的语句信息
mysql > show databases;
-- 查看所有数据库信息
mysql > show databases like '%xiao%';
-- 检索查看指定的数据库信息
mysql > show create database oldboy;
-- 查看创建库的语句信息

| 序号 | 数据库名称 | 作用说明 |

|—|—|—|

1
2
3
| 01 | information_schema | 系统运行状态,性能等的库 |
| 02 | mysql | 授权权限、用户管理的库 |
| 03 | performance_schema | 系统运行状态,性能等的库 |

说明:以上三个是数据库系统中默认的数据库,可以用于管理应用。

修改数据库信息:

删除数据库信息:

切换数据库信息:

数据定义语句定义数据库规范说明: 创建数据库名称规范:要和业务有关,不要有大写字母(为了多平台兼容),不要数字开头,不要含有系统关键字信息; 创建数据库明确字符:创建数据库时明确(显示)的设置字符集信息,为了避免跨平台兼容性与不同版本兼容性问题; 删除数据库操作慎用:在对数据库进行删除操作时,一定要经过严格审计后再进行操作,并且数据库普通用户不能有drop权限;

02 数据定义语言对数据表定义

数据库中的表也是数据库服务结构中的重要组成部分; 创建数据表信息: 通过数据库服务管理工具,图形操作创建数据库表信息:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
mysql > alter database test charset utf8mb4;
mysql > alter database test charset utf8 collate utf8_general_mysql500_ci;
-- 修改数据库服务字符集编码信息与字符编码排序规则信息
mysql > drop database test;
mysql > drop schema test;
-- 删除数据库信息(在生产环境一定慎用)
mysql > use xiaoq
Database changed
-- 在已有数据库之间进行切换
mysql > select database();
+--------------+
| database()   |
+--------------+
| xiaoq        |
+--------------+
1 row in set (0.00 sec)
-- 查看当前所在数据库信息

点击apply 后,会将图形操作的配置信息转换为相应的建表语句:

完整建表语句参考:

创建表的基本语法格式: 以上是创建表的具体格式信息,其中create table是关键字,不能更改,但是大小写可以变化。

1
CREATE TABLE `student` (

id int NOT NULL COMMENT ‘学号信息’, name varchar(45) NOT NULL COMMENT ‘学生名’, age tinyint unsigned NOT NULL COMMENT ‘学生年龄’, gender enum(‘M’,‘F’,‘N’) NOT NULL DEFAULT ‘N’ COMMENT ‘学生性别’, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=‘学生表’

1
create table <表名> (

<字段名1> <类型1> , … <字段名n> <类型n>);

实战情况:需要创建一个学生信息表:

查看数据表信息:

修改数据表信息: 修改数据表属性信息:

修改数据表结构信息:

1
2
3
4
5
6
# 切换数据库环境
mysql > use xiaoq;
mysql > select database();
-- 查看是否切换数据库成功
# 创建数据表信息
mysql > create table stu1(

id int(10) not null, name varchar(20) not null, age tinyint(2)  NOT NULL default ‘0’, dept varchar(16)  default NULL );

1
2
3
4
5
# 查看数据表信息
mysql > show tables
mysql > desc stu1;
# 获取创建表语句
mysql > show create table stu1\G;

*************************** 1. row *************************** Table: stu1

1
Create Table: CREATE TABLE `stu1` (

id int(10) NOT NULL, name varchar(20) NOT NULL, age tinyint(2) NOT NULL DEFAULT ‘0’, dept varchar(16) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
1 row in set (0.00 sec)
mysql >  use mysql;
-- 切换到指定数据库中
mysql >  show tables;
-- 查看数据库中所有表信息
mysql > desc stu1;
-- 查看数据库中指定表数据结构信息
mysql > show create table stu1;
-- 查看数据库中指定表创建语句信息
# 修改数据表名称信息
mysql > rename table stu1 to stu2;

或者

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
mysql > alter table stu2 rename stu3;
-- 利用上面种方式均可修改表名称信息
mysql > show tables;
-- 查看表名称信息是否修改
# 修改数据表编码信息
mysql > alter table stu1 charset utf8mb4;
-- 修改表结构中字符集编码信息
mysql > show create table stu1;
-- 查看表字符编码信息情况
# 数据表结构调整命令语法
mysql > alter table <表名> add column <字段名称> <数据类型> <约束与属性> [comment '注释'] [选项参数];
-- 利用alter在数据表中添加新的表结构字段
mysql > alter table <表名> drop column <字段名称>;
-- 利用alter在数据表中删除已有表结构字段
mysql > alter table <表名> modify column <字段名称> <数据类型> <约束与属性> [comment '注释'] [选项参数];
-- 利用alter在数据表中修改已有表结构字段(数据类型 约束与属性)
mysql > alter table <表名> change column <旧字段名称> <新字段名称> <数据类型> <约束与属性> [comment '注释'] [选项参数];
-- 利用alter在数据表中修改已有表结构字段(字段名称 数据类型 约束与属性)
mysql > alter table <表名> drop index <字段名称> ;

删除数据表信息:

数据定义语句定义数据表规范说明: 创建数据表名称规范:要和业务有关(含库前缀),不要有大写字母,不要数字开头,不要含有系统关键字信息,名称不要太长; 创建数据表属性规范:属性信息显示设置,引擎选择InnoDB,字符集选择utf8/utf8mb4,表信息添加注释; 创建数据列属性规范:名称要有意义,不要含有系统关键字信息,名称不要太长; 创建数据类型的规范:数据类型选择合适的、足够的、简短的; 创建数据约束的规范:每个表中必须都要有主键,最好是和业务无关列,实现自增功能,建议每个列都非空(避免索引失效)/加注释 删除数据表操作规范:对于普通用户不能具有删表操作,需要操作删表时需要严格审核 修改数据表结构规范:在数据库8.0之前,修改数据表结构需要在业务不繁忙时进行,否则会产生严重的锁 如果出现紧急修改表结构信息需求时,可以使用工具进行调整,比如使用:pt-osc、gh-ost,从而降低对业务影响

企业数据库面试题目分析练习:

01 请查看以下建表语句给出规范和优化建议:(物流公司日常工作表信息)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
-- 利用alter在数据表中删除已有表结构字段(约束与属性)
# 具体实际操作过程(添加新的表结构字段)
mysql > alter table stu add column telno char(11) not null unique key comment '手机号';
-- 在学生表中,添加新的表结构字段列(追加字段列-单列操作)
mysql > alter table stu add column wechat varchar(64) not null unique key comment '微信号' after age;
-- 在学生表中,添加新的表结构字段列(插入字段列-单列操作)
mysql > alter table stu add column sid int not null unique key comment '微信号' first;
-- 在学生表中,添加新的表结构字段列(插入首行列-单列操作)
mysql > desc stu
-- 查看表结构字段信息变化
# 具体实际操作过程(删除已有表结构字段)
mysql > alter table stu drop column sid;
-- 在学生表中,删除已有表结构字段列(删除指定字段列-单列操作)
# 具体实际操作过程(修改已有表结构字段)
mysql > alter table stu modify name varchar(64);
-- 在学生表中,修改已有表结构字段列(修改表结构数据类型)
mysql > alter table stu modify name varchar(64) not null comment '学生名';
-- 在学生表中,修改已有表结构字段列,最后带有保持原有配置的属性信息,否则其他属性信息会被还原为默认
mysql > alter table stu change name stuname varchar(64) not null comment '学生名';

或者

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
mysql > alter table stu change column name stuname varchar(64) not null comment '学生名';
-- 在学生表中,修改已有表结构字段列(修改表结构字段名称)
mysql > alter table stu modify name varchar(64) not null unique comment '学生名称';
-- 在学生表中,修改已有表结构字段列(修改表结构属性信息)了解即可
mysql > alter table stu drop index `name`;
-- 在学生表中,修改已有表结构字段列(删除表结构属性信息)了解即可
mysql > desc stu
-- 查看表结构字段信息变化
# 数据表删除命令语法
mysql > drop table <表名>
# 具体实际操作过程
mysql > drop table stu1;
-- 删除操作过程,会将定义的表结构和表中数据内容一并删除
mysql > truncate table stu1;
-- 删除操作过程,只是清空表中数据内容,但保留定义的表结构信息
create table 't_area_distribution_cost' (

‘id’ bigint(20) not null auto_increment comment ‘主键’, ‘city_id’ varchar(200), ‘city_name’ varchar(200), ‘warehouse_id’ varchar(200), ‘warehouse_name’ varchar(200)  , ‘station_region_id’ varchar(200), ‘station_region_name’ varchar(200), ‘replenish_type’ varchar(200), ‘distribution_cost’ varchar(200), ‘c_t’ varchar(200) default ‘0’ comment ‘创建时间’, ‘create_user’ varchar(200) default ‘0’ comment ‘创建人ID’, ‘creater’ varchar(200) comment ‘创建人’, ‘u_t’ varchar(200) default ‘0’ comment ‘修改时间’, ‘update_user’ varchar(200) default ‘0’ comment ‘修改人ID’, ‘updater’ varchar(200),

问题解答分析:

02 研发同学需要紧急上线,需要DBA审核SQL,请问以下语句需要如何评估后上线执行,请写审核SQL要点

问题解答分析: 本身语句是没有任何问题的,但需要说明,尽量业务繁忙时不要进行发布,选择夜里业务不繁忙时进行发布; 在进行SQL语句信息审核时,需要了解SQL语句的含义和作用: 通过对以上SQL语句信息解读,可以看出语句操作属于DDL操作,线上操作DDL语句可能会产生比较严重的锁进制等待(死锁问题); 可以结合企业的数据业务存储的负载压力(TPS),可能当前时间段的TPS数值较高,原则上不建议进行线上操作; 但是考虑到业务需求的紧急情况,建议使用PT-osc工具进行数据库线上操作,减少对线上业务的影响,但不能提高操作效率;

1.6.3 操作管理语句应用实践(DML)

数据操作语言(DML),主要针对数据库里的表里的数据进行操作,用来定义数据内容信息(数据);

01 数据操作语言对数据信息调整

增加数据内容信息(insert) 添加命令语法格式: 实际操作命令演示: ‘is_deleted’ varchar(200) comment ‘删除标记(1 ,删除;0,不删除,有效)’, primar y key (‘id’), key ‘i_abc_city_id’ (‘city_id’) comment ‘城市ID索引’, key ‘i_abc_warehouse_id’ (‘warehouse_id’), key ‘i_abc_station_region_id’ (‘station_region_id’) ) ENGINE=innodb default charset=utf8 comment=‘区域配送运费设置’;

1
2
3
# 修改建议01:表明信息略长可以进行调整
create table 't_area_distribution_cost'
# 修改建议02:数据类型信息设定尽量合适

‘city_id’ varchar(200), ‘city_name’ varchar(200),

1
# 修改建议03:定义索引信息没有设置非空

‘city_id’ varchar(200), ‘warehouse_id’ varchar(200), ‘station_region_id’ varchar(200),

1
# 修改建议04:表中字段列信息可以加注释

‘city_id’ varchar(200), ‘city_name’ varchar(200), ‘warehouse_id’ varchar(200), ‘warehouse_name’ varchar(200)  , ‘station_region_id’ varchar(200),

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
alter table t_enter_cooperate_info add account_day  INT not null default 0 comment '账期天数',
alter table t_enter_cooperate_info add account_detay_day INT not null default 0 comment '账期付款天数',
alter table t_pop_basic add account_day INT not null default 0 comment '账期天数',
alter table t_pop_basic add account_detay_day INT not null default 0 comment '账期付款天数'
alter table t_enter_cooperate_info add account_day  INT not null default 0 comment '账期天数',
alter table t_enter_cooperate_info add account_detay_day INT not null default 0 comment '账期付款天数',
-- 表示在t_enter_cooperate_info表中 添加两列信息 并设置相应属性和注释信息
alter table t_pop_basic add account_day INT not null default 0 comment '账期天数',
alter table t_pop_basic add account_detay_day INT not null default 0 comment '账期付款天数'
-- 表示在t_pop_basic add表中 添加两列信息 并设置相应属性和注释信息
# 数据表数据插入命令语法
mysql> insert into <表名> [( <字段名1>[,..<字段名n > ])] values ( 1 )[, ( n )]
-- 属于表内容信息变更操作,需要按照表结构预先定义好的字段信息插入
# 具体实际操作过程
mysql> desc stu1;
mysql> insert into stu1(id,name,age,dept) values(1,'oldboy',35,'net sec');
-- 插入单行信息标准方法(信息输入不要重复,且特定信息不要为空)
mysql> insert into stu1(id,name,age,dept) values(0,'oldboy',35,'net sec');
mysql> insert into stu1(id,name,age,dept) values(null,'oldboy',35,'net sec');
-- 插入单行信息标准方法(自增列信息可以填入0或null,表示默认实现自增效果)
mysql> insert into stu1 values(2,'oldgirl',25,'linux');

修改数据内容信息(update) 修改命令语法格式: 实际操作命令演示:

知识扩展:禁止修改命令不加条件信息执行命令: 服务端禁止不带where条件操作数据库表有两种方法: 利用sql_safe_updates配置参数,表示在delete,update操作中: 没有where条件,当where条件中列没有索引可用,且无limit限制时会拒绝更新。

客户端禁止不带where条件操作数据库表有两种方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-- 插入单行信息可以不含有表字段信息
mysql> insert into stu1 values(03,'littlegirl',2,'net sec'),(04,'littleboy',1,'Linux');
-- 插入多行信息可以不含有表字段信息
mysql> insert into stu1(name,age) values('oldboy',35);
-- 插入当行信息可以只含部分字段信息,但是省略字段信息必须具有自增特性 或 可以为空 或有默认值输入
mysql> insert into stu1 values(6,'老男孩',32,'python,linux,net sec');
-- 插入中文信息
# 检查信息是否插入成功
mysql> select * from stu1;
# 数据表数据修改命令语法
mysql> update 表名 set 字段=新值, where 条件;
-- 属于表内容信息变更操作,需要按照表结构预先定义好的字段信息修改,并且按照条件修改,默认全表修改
# 具体实际操作过程
mysql> update stu1 set name="zhangsan" where id=6;
-- 修改表数据内容标准方式,修改时一定要加条件信息(条件信息建议为主键或具有唯一性信息)
# 检查信息是否修改成功
mysql> select * from stu1;
# 方法1:临时执行
mysql> set global sql_safe_updates=1;
-- 退出重新登陆生效
mysql> update stu set sname='oldboy';
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.
-- 配置效果展示
# 方法2:永久生效
[root@db01 ~]# vi /etc/my.cnf
[mysqld]

init-file=/opt/ init.sql

1
2
3
-- 新建脚本
echo 'set global sql_safe_updates=1;' >/opt/ init.sql
chmod +x /opt/ init.sql

/etc/ init.d/mysqld restart

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[root@db01 ~]# mysql -uroot -poldboy123 -e "select @@global.sql_safe_updates"
+-------------------------------------+
| @@global.sql_safe_updates           |
+-------------------------------------+
| 1                                   |
+-------------------------------------+
# 方法一:把safe_updates=1加入到my.cnf的client标签下
[root@db01 ~]# vim /etc/my.cnf
[mysql]
socket=/tmp/mysql.sock

safe_updates=1

1
2
3
4
5
-- 客户端配置信息
mysql> update stu set sname='oldboy01';
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.
-- 配置效果展示
# 方法2:设置数据库别名操作方式

alias mysql=‘mysql -U’ -U, –safe-updates Only allow UPDATE and DELETE that uses keys

1
2
3
-- 表示以安全更新模式登录数据库,并放入/etc/profile永久生效。
mysql> update stu set sname='oldboy03';
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.

区别分析

1
drop table stu;

truncate table stu;

1
delete from stu;

功能效果 删除表结构+数据 删除表数据(释放空间) 删除表数据(标记删除) 删除逻辑 彻底删除 物理删除(段区页层面删除) 逻辑删除(逐行删除) 删除效率 效率快(和数据量无关) 效率快(和数据量无关) 效率慢(和数据量有关) 自增影响 新增自增序列 重置自增序列(释放高水位线) 延续自增序列 数据恢复? 利用日志文件恢复 利用备份恢复/延时从库恢复 利用日志文件恢复(快速)

删除数据库中数据信息: 删除命令语法格式: 实际操作命令演示:

删除数据库信息扩展:伪删除操作 由于执行删除语句信息时,有可能会对一些业务数据造成影响,甚至可能会将表中所有数据清空,虽然可以通过日志信息恢复(闪回) 但是整体操作过程还是比较危险的,因此在进行数据信息删除操作时,可以利用伪删除操作代替真实删除操作; 一般在数据库中删除数据信息,是因为从业务层面有些数据不想被查询获取到,伪删除就是不让查询时可以获取想要删除的数据; 伪删除的本质:利用update替代delete 可以在相应表中添加状态列信息,可以将状态列设置为:1表示存在 0表示不存在 在进行伪删除操作时,只是将状态列信息改为0,但是并没有把相应行的数据信息删除,但是在查询时可以忽略状态列为0的信息; 这样可以有效规避误删除操作对业务数据的影响,万一伪删除操作有问题,可以再将状态列信息0改为1即可

企业数据库面试题目分析练习:

01 请解释说明以下语句之间的区别?

问题解答分析: 知识扩展:自增列信息值调整方法:

1.6.4 操作管理语句应用实战(DQL)

数据查询语言(DQL),主要用来查询记录(数据),在实际应用过程中也会有多种查询使用方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- 配置效果展示
# 数据表数据删除命令语法
mysql> delete from 表名 where 表达式;
-- 属于表内容信息变更操作,需要按照表结构预先定义好的字段信息删除,并且按照条件删除,默认全表删除
# 具体实际操作过程
mysql> delete from stu1 where id=6;
mysql> delete from stu1 where id<3;
mysql> delete from stu1 where age=2 or age=1;
mysql> delete from stu1;
-- 删除表信息时,如果不加条件会进行逐行删除全表信息(效率比较慢)
# 检查信息是否删除成功
mysql> select * from stu1;
# 真实删除数据信息操作举例
mysql> delete from stu1 where id=6;
# 伪删除数据信息操作举例
mysql> alter table stu1 add state tinyint not null default 1;
-- 在原有表中添加新的状态列
mysql> update stu1 set state=0 where id=6;
-- 将原本删除列信息的状态改为0,实现伪删除效果
mysql> select * from stu1 where state=1;
-- 实现查询时不要获取状态为0的信息,即不查看获取伪删除数据信息
drop table stu;

truncate table stu;

1
2
delete from stu;
mysql> alter table stu auto_increment=10;

01 查询获取服务配置信息

在利用select语句获取查询数据库服务的配置信息,可以理解为select命令单独使用; 查询命令语法格式: 实际操作命令演示:获取系统配置信息 数据库服务在线调整配置参数方法:

说明:数据库服务配置参数在线调整参数,只是临时生效,数据库服务重启后配置会失效,想要永久生效需要修改配置文件信息

实际操作命令演示:获取函数输出信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 查询获取信息命令语法
mysql> select @@配置参数信息;
mysql> show variables like '检索的配置信息';
# 查询获取参数配置信息
mysql> select @@port;
+-----------+
| @@port    |
+-----------+
| 3306      |
+-----------+
1 row in set (0.00 sec)
-- 查询数据库服务端口配置信息
mysql> select @@socket;
+-----------------+
| @@socket        |
+-----------------+
| /tmp/mysql.sock |
+-----------------+
1 row in set (0.00 sec)
-- 查询数据库服务套接字文件信息
mysql> select @@innodb_flush_log_at_trx_commit;
+----------------------------------------------+
| @@innodb_flush_log_at_trx_commit             |
+----------------------------------------------+
| 1                                            |
+----------------------------------------------+
1 row in set (0.00 sec)
-- 查询数据库服务比较长的配置参数信息
# 查询获取参数配置信息(模糊查找)
mysql> show variables;
-- 查看数据库服务所有配置参数信息
mysql> show variables like 'po%';
-- 查看数据库服务配置信息模糊查找(查找po开头的信息)
mysql> show variables like '%po';
-- 查看数据库服务配置信息模糊查找(查找po结尾的信息)
mysql> show variables like '%po%';
-- 查看数据库服务配置信息模糊查找(查找含有po的信息)
# 数据库配置参数在线调整
mysql > set session innodb_flush_log_at_trx_commit=1
mysql > set sql_log_bin=0;
-- 表示在线临时调整配置参数,并且只是当前会话生效(session是默认方式,不是所有配置都可以调整)
mysql > set global innodb_flush_log_at_trx_commit=1
-- 表示在线临时调整配置参数,并且将会影响所有连接(global是全局方式,可以进行所有配置调整)
# 查询获取函数输出信息
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.26    |
+-----------+
1 row in set (0.00 sec)
-- 查询数据库服务函数输出信息,获取服务版本信息
mysql> select now();
+--------------------------+
| now()                    |
+--------------------------+
| 2022-11-04 09:13:27      |
+--------------------------+
1 row in set (0.00 sec)

02 查询获取服务数据信息(单表查询)

在利用select语句获取查询数据库服务的数据信息,可以理解为select命令与from where 等其它子句结合使用; 查询命令语法格式:

上传加载测试环境: 官方数据库测试样例文件下载:https://dev.mysql.com/doc/ index-other.html

实际操作命令演示:select+from 结合使用情况

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
-- 查询数据库服务函数输出信息,获取当前日期时间
mysql> select concat(123);
+-----------------+
| concat(123)     |
+-----------------+
| 123             |
+-----------------+
1 row in set (0.00 sec)
-- 查询数据库服务函数输出信息,获取拼接函数信息
mysql> select concat(user,"@","'",host,"'") from mysql.user ;
+-------------------------------------+
| concat(user,"@","'",host,"'")       |
+-------------------------------------+
| user02@'%'                          |
| blog@'192.168.30.%'                 |
+-------------------------------------+
-- 拼接函数应用演示
# 数据表数据查询命令语法
mysql> select <字段1,字段2...> from <表名> [WHERE 条件] group by <字段1,字段2...> having 条件 order by 字段 limit 限制信息;
-- 属于表内容信息查询操作,可以获取表中数据行信息(子句信息需要按顺序书写)
mysql> source ~/world-db/world.sql
-- 将world.sql数据库文件上传到数据库服务器中,根据存储路径进行加载恢复数据库数据
# 查看数据库信息和数据表信息
mysql> show databases
-- 可以查看到world数据库信息
mysql> use world;
mysql> show tables
-- 查看数据库中表信息
mysql> desc city;
-- 查看数据库中表结构信息
# 查询数据库表的前几行记录信息
mysql> select * from city limit 5;

| 序号 | 符号 | 解释说明 |

|—|—|—|

1
2
3
4
5
6
| 01 | < | 表示小于指定数值的信息作为条件 |
| 02 | > | 表示大于指定数值的信息作为条件 |
| 03 | <= | 表示小于等于指定数值的信息作为条件 |
| 04 | >= | 表示大于等于指定数值的信息作为条件 |
| 05 | != / <> | 表示不等于指定数值的信息作为条件 |
| 序号 | 逻辑判断符号 | 解释说明 |

|—|—|—|

1
2
3
| 01 | and(并且)/ && | 表示多个条件均都满足才能被查找出来 |
| 02 | or(或者)/ || | 表示多个条件之一满足就能被查找出来 |
| 03 | not (取反) / ! | 表示查找除过滤查找的信息以外的内容 |

实际操作命令演示:select+from+where 结合使用情况

方式一:定义等值条件信息进行数据查询

方式二:定义区间条件信息进行数据查询

可使用区间条件表示方法:

方式三:定义逻辑条件信息进行数据查询

可以使用逻辑判断符号,进行条件设定查找相应数据信息:

方式四:定义模糊条件信息进行数据查询(like )

方式五:特殊查询条件组合进行数据查询(配合in, not in, between and )

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
use world;
select * from city;          -- > 等价于 cat a.txt
select id,name,countr ycode,district,population from city;
-- 进入world数据库中,查询数据库中city表所有内容信息(企业应用不要对大表查看所有数据)
select name,population from city;     -- > 等价于 awk $1 $2
-- 查询city表中的部分字段信息,显示查看城市名称和人口数量
# 查询中国的所有城市信息,中国代码信息 CHN
mysql > SELECT * FROM city WHERE countr ycode='CHN';
# 查询中国的所有城市信息,只关注城市名称和人口数量列信息
mysql > SELECT NAME,population FROM city WHERE countr ycode='CHN';
# 查询大于700万人的所有城市信息
mysql > SELECT * FROM city WHERE population>7000000;
# 查询小于等于1000人的所有城市信息
mysql > SELECT * FROM city WHERE population<=1000;
# 查询中国境内,大于520万人口的城市信息
mysql> SELECT * FROM city WHERE countr ycode='CHN' AND population>5200000;
# 查询中国和美国的所有城市
mysql> SELECT * FROM city WHERE countr ycode='chn' OR countr ycode='USA';
# 查询人口数在100w到200w之间的城市信息
mysql> SELECT * FROM city WHERE population>=1000000 AND population<=2000000;
# 查询国家代号是CH开头的城市信息
mysql> SELECT * FROM city WHERE countr ycode LIKE 'CH%';
# 查询国家代号含US内容的城市信息
mysql> SELECT * FROM city WHERE countr ycode LIKE '%US%';
-- 在模糊查询时,%符号在前面进行检索数据时,是不会走索引信息进行检索的,查询性能较慢

| 序号 | 函数信息 | 解释说明 |

|—|—|—|

1
2
3
4
5
6
7
| 01 | count() | 此函数表示对数量信息进行统计 |
| 02 | sum() | 此函数表示对数值信息进行求和 |
| 03 | avg() | 此函数表示对数值信息进行求平均值 |
| 04 | min() | 此函数表示对数值信息进行取最小值 |
| 05 | max() | 此函数表示对数值信息进行取最大值 |
| 06 | group_concat() | 此函数表示输出信息无法匹配分组和聚合函数时,进行拼接整合显示 |
| 07 | distinct | 此指令表示作用是对表中的单个字段或多个字段去重操作 |

方式六:查询数据信息取消重复信息(distinct)

方式七:查询数据信息为空的内容(is null)

实际操作命令演示:select+from+where+group by+聚合函数(统计函数) 结合使用情况 在利用select语句查询数据信息,结合group by子句可以实现分组查询,并且还必须配合聚合函数对分组查询的数据做相应处理; 数据库服务中常用的聚合函数(统计函数):

利用group by进行分组查询的执行逻辑分析: 根据查询语句信息,取出表中关注的列字段信息; 根据查询分组信息,将特定列字段信息进行排序,从而将分组的一致信息整合在一起(形成结果集); 根据分组合并信息,结合使用的聚合函数,进行数值信息运算或统计(生成最终结果); 根据分组聚合要求,分组信息输出时必须和分组信息一一对应,但特殊列无法一一对应输出时,可使用group_concat()拼接输出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 查询中国和美国的所有城市
mysql> SELECT * FROM city WHERE countr ycode in ('CHN','USA');
-- in的查询条件方式表示包含意思,实际应用更广泛
# 查询世界上的所有城市信息,但排除中国和美国的城市不查询
mysql> SELECT * FROM city WHERE countr ycode not in ('CHN','USA');
-- not in的查询条件方式表示排除意思,实际应用比较少见,因为not in不能走索引扫描,查询检索性能较慢
# 查询人口数量在50w-100w之间的城市信息
mysql> SELECT * FROM city WHERE population between 500000 and 10000000;
-- between and的查询条件方式是包含边界取值信息的,即包含50w人口的城市,也包含100w人口的城市
mysql> select Countr yCode from city where Countr yCode='USA';
mysql> select Distinct Countr yCode from city where Countr yCode='USA';
+-----------------+
| Countr yCode    |
+-----------------+
| USA             |
+-----------------+
1 row in set (0.19 sec)
-- 列字段信息必须完全相同内容,才可以实现去重;
mysql> select * from city where Countr yCode is null;
-- 查询国家编码字段为空的信息
mysql> select * from city where Countr yCode not null;
-- 查询国家编码字段为非空的信息

实际操作命令演示:获取分组数据信息进行聚合函数处理实践:

实际操作命令演示:select+from+where+group by+聚合函数+having 在利用select语句查询数据信息,结合分组和聚合函数处理之后,可以将输出的信息再进行过滤处理(having); 实际操作命令演示:对分组聚合后数据进行过滤处理

实际操作命令演示:select+from+where+group by+聚合函数+having+order by 在利用select语句查询数据信息,结合分组和聚合函数处理之后,并且再次经过筛选的数据,按照一定数值规律排序显示信息 实际操作命令演示:

实际操作命令演示:select+from+where+group by+聚合函数+having+order by+limit 在利用select语句查询数据信息,结合分组和聚合函数处理之后经过筛选的数据,按照一定数值规律排序显示信息,并限制输出内容行数 实际操作命令演示:

1
2
3
4
5
6
7
8
# 查询统计每个国家的人口总数
mysql > select countr ycode,sum(population) from world.city group by countr ycode;
-- 根据国家信息分组聚合,在将分组后所有城市的人口数量进行sum求和运算,实现国家信息对应人口总数的1对1关系
# 查询统计每个省份的城市个数
mysql > select district,count(name) from city where countr ycode='chn' group by district;
# 查询统计每个省份的城市个数,以及城市名称信息(经常面试题考到)
mysql> select district,count(name),name from city where countr ycode='chn' group by district;
ERROR 1055 (42000): Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'world.city.Name' which is not functionally

dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
-- 由于数据库sql_mode配置了only_full_group_by,由于输出的name信息不能和district信息实现1对1关系,因此报错
mysql> select district,count(name),group_concat(name) from city where countr ycode='chn' group by district;
-- 利用group_concat()就可以实现没有出现在分组和聚合函数中的字段,采取拼接整合方式显示,满足分组1对1关系
# 查询统计每个国家的人口总数,只显示人口数量超过1个亿的信息
mysql > select countr ycode,sum(population) from world.city group by countr ycode having sum(population)>100000000;
# 查询统计每个国家的人口总数,只显示人口数量超过5千万的信息,并且按照国家人口总数排序显示
mysql > select countr ycode,sum(population) from world.city group by countr ycode having sum(population)>50000000 order by sum(population);
-- 实现了人口数量从小到大排序(升序/正序)
mysql > select countr ycode,sum(population) from world.city group by countr ycode having sum(population)>50000000 order by sum(population) desc;
-- 实现了人口数量从大到小排序(降序/逆序)

03 查询获取服务数据信息(多表查询)

在对数据库中数据信息查询时,有些需求情况要获取的数据信息,是通过多个表的数据信息整合获取到的,就称为多表查询; 查询命令语法格式:

说明:多表查询的最终目的是将多张表的信息整合为一张大表显示,并将显示的结果信息可以做相应单表的操作处理;

上传加载测试环境:

1
2
# 查询统计每个国家的人口总数,只显示人口数量超过5千万的信息,并且按照国家人口总数从大到小排序,只显示前三名
mysql > select countr ycode,sum(population) from world.city group by countr ycode having sum(population)>50000000 order by sum(population) desc limit 3;

或者

1
2
mysql > select countr ycode,sum(population) from world.city group by countr ycode having sum(population)>50000000 order by sum(population) desc limit 0,3;
mysql > select countr ycode,sum(population) from world.city group by countr ycode having sum(population)>50000000 order by sum(population) desc limit 3 offset

0;

1
2
# 查询统计每个国家的人口总数,只显示人口数量超过5千万的信息,并且按照国家人口总数从大到小排序,只显示三~五名
mysql > select countr ycode,sum(population) from world.city group by countr ycode having sum(population)>50000000 order by sum(population) desc limit 2,3;

或者

1
mysql > select countr ycode,sum(population) from world.city group by countr ycode having sum(population)>50000000 order by sum(population) desc limit 3 offset

2;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
-- 跳过前2名,显示后面的三名数据信息
# 笛卡尔乘积连接多表:
select * from t1,t2;
# 内连接查询多表:
select * from t1,t2 where t1.=t2.;
select * from t1 [inner] join t2 on t1.=t2.;
# 外连接查询多表:左外连接
select * from t1 left join t2 on  t1.=t2.;
# 外连接查询多表:右外连接
select * from t1 right join t2 on  t1.=t2.;
# 创建多表查询所需模拟数据库和数据表信息
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;

1
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;

1
CREATE TABLE sc (

sno INT NOT NULL COMMENT ‘学号’, cno INT NOT NULL COMMENT ‘课程编号’, score INT NOT NULL DEFAULT 0 COMMENT ‘成绩’ ) ENGINE=INNODB CHARSET=utf8;

1
CREATE TABLE teacher (

tno INT NOT NULL PRIMARY KEY COMMENT ‘教师编号’, tname VARCHAR(20) NOT NULL COMMENT ‘教师名字’ ) ENGINE=INNODB CHARSET=utf8;

1
2
# 在数据库与数据表中插入模拟数据
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 ‘),

多表查询方式类型:笛卡尔乘积 实现局域teacher表与course表进行多表关联; 多表关联实际操作: (8,‘oldboy’,20,’m’), (9,‘oldgirl’,20,‘f ‘), (10,‘oldp’,25,’m’);

1
INSERT INTO teacher(tno,tname)

VALUES (101,‘oldboy’), (102,‘xiaoQ’), (103,‘xiaoA’), (104,‘xiaoB’);

1
INSERT INTO course(cno,cname,tno)

VALUES (1001,’linux’,101), (1002,‘python’,102), (1003,‘mysql’,103), (1004,‘go’,105);

1
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);

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
SELECT * FROM student;
SELECT * FROM teacher ;
SELECT * FROM course;
SELECT * FROM sc;
# 分别查看单表数据信息:
mysql> select * from teacher ;
+-----+--------+
| tno | tname  |
+-----+--------+
| 101 | oldboy |

多表查询的逻辑思路

多表查询方式类型:内连接(取交集) 可以基于笛卡尔乘积方式的结果集,将有意义的信息进行展示,并且是基于两张表里的相同含义字段,进行比较后输出相等的结果信息; 内连接查询的简单描述:两个表中有关联条件的行显示出来;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| 102 | xiaoQ  |
| 103 | xiaoA  |
| 104 | xiaoB  |
+-----+--------+
4 rows in set (0.01 sec)
mysql> select * from course;
+------+--------+-----+
| cno  | cname  | tno |
+------+--------+-----+
| 1001 | linux  | 101 |
| 1002 | python | 102 |
| 1003 | mysql  | 103 |
| 1004 | go     | 105 |
+------+--------+-----+
4 rows in set (0.00 sec)
# 多表关联查询
mysql> select * from teacher,course;
+-----+--------+------+--------+-----+
| tno | tname  | cno  | cname  | tno |
+-----+--------+------+--------+-----+
| 104 | xiaoB  | 1001 | linux  | 101 |
| 103 | xiaoA  | 1001 | linux  | 101 |
| 102 | xiaoQ  | 1001 | linux  | 101 |

| 101 | oldboy | 1001 | linux | 101 |        – 有意义信息

1
2
| 104 | xiaoB  | 1002 | python | 102 |
| 103 | xiaoA  | 1002 | python | 102 |

| 102 | xiaoQ | 1002 | python | 102 |      – 有意义信息

1
2
| 101 | oldboy | 1002 | python | 102 |
| 104 | xiaoB  | 1003 | mysql  | 103 |

| 103 | xiaoA | 1003 | mysql | 103 |       – 有意义信息

1
2
3
4
5
6
7
8
9
| 102 | xiaoQ  | 1003 | mysql  | 103 |
| 101 | oldboy | 1003 | mysql  | 103 |
| 104 | xiaoB  | 1004 | go     | 105 |
| 103 | xiaoA  | 1004 | go     | 105 |
| 102 | xiaoQ  | 1004 | go     | 105 |
| 101 | oldboy | 1004 | go     | 105 |
+-----+--------+------+--------+-----+
16 rows in set (0.00 sec)
-- 默认方式多表查询时,会出现组合乘积效果(4*4=16)

for each row in a for each row in b 合并成一行 print

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 比较传统的SQL 92的内连接标准方式
mysql> select * from teacher,course where teacher.tno=course.tno;
+-----+--------+------+--------+-----+
| tno | tname  | cno  | cname  | tno |
+-----+--------+------+--------+-----+
| 101 | oldboy | 1001 | linux  | 101 |
| 102 | xiaoQ  | 1002 | python | 102 |
| 103 | xiaoA  | 1003 | mysql  | 103 |
+-----+--------+------+--------+-----+
3 rows in set (0.00 sec)
# 比较新颖的SQL 99的内连接使用方式
mysql> select * from teacher [inner] join course on teacher.tno=course.tno;
+-----+--------+------+--------+-----+
| tno | tname  | cno  | cname  | tno |
+-----+--------+------+--------+-----+
| 101 | oldboy | 1001 | linux  | 101 |
| 102 | xiaoQ  | 1002 | python | 102 |
| 103 | xiaoA  | 1003 | mysql  | 103 |
+-----+--------+------+--------+-----+
3 rows in set (0.00 sec)

多表查询的逻辑思路(内连接)

多表查询方式类型:外连接(应用更广泛) 利用外连接查询时,是可以进行性能优化处理的,因为内连接在底层查询时,是逐行进行比较后输出,整体数据查询检索的效率较低; 外连接可以细分为:左外连接-left join on 左外连接表示查询数据结构包含:左表所有数据行+右表满足关联条件的行; 外连接方式左连接与右连接区别举例:

外连接可以细分为:右外连接-right join on 右外连接表示查询数据结构包含:右表所有数据行+左表满足关联条件的行; for each row in a for each row in b if ax=b.y print row

1
# 左连接查询语法

a left join b on a.x = b.x

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- a表示左表,b表示右表,基于左表a建立关联
# 实际操作演示过程
mysql> select * from teacher left join course on teacher.tno=course.tno;
+-----+--------+------+--------+------+
| tno | tname  | cno  | cname  | tno  |
+-----+--------+------+--------+------+
| 101 | oldboy | 1001 | linux  | 101  |
| 102 | xiaoQ  | 1002 | python | 102  |
| 103 | xiaoA  | 1003 | mysql  | 103  |
| 104 | xiaoB  | NULL | NULL   | NULL |
+-----+--------+------+--------+------+
4 rows in set (0.00 sec)
-- 包含了左表的所有数据行信息(teacher),包含了右表的关联数据行信息(course)
# 显示差集信息:
mysql> select * from teacher left join course on teacher.tno=course.tno where course.cno is null;
+-----+-------+------+-------+------+
| tno | tname | cno  | cname | tno  |
+-----+-------+------+-------+------+
| 104 | xiaoB | NULL | NULL  | NULL |
+-----+-------+------+-------+------+
1 row in set (0.00 sec)
# 会将左表作为驱动表,进行外层循环

for each row in a for each row in b if a.x=b.y print row else print a.x b.null

1
# 右连接查询语法

a right join b on a.x = b.x

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
-- a表示左表,b表示右表,基于右表b建立关联
# 实际操作演示过程
mysql> select * from teacher right join course on teacher.tno=course.tno;
+------+--------+------+--------+-----+
| tno  | tname  | cno  | cname  | tno |
+------+--------+------+--------+-----+
| 101  | oldboy | 1001 | linux  | 101 |
| 102  | xiaoQ  | 1002 | python | 102 |
| 103  | xiaoA  | 1003 | mysql  | 103 |
| NULL | NULL   | 1004 | go     | 105 |
+------+--------+------+--------+-----+
4 rows in set (0.00 sec)
-- 包含了右表的所有数据行信息(course),包含了左表的关联数据行信息(teacher)
# 显示差集信息:
mysql> select * from teacher right join course on teacher.tno=course.tno where teacher.tname is null;
+------+-------+------+-------+-----+
| tno  | tname | cno  | cname | tno |
+------+-------+------+-------+-----+
| NULL | NULL  | 1004 | go    | 105 |
+------+-------+------+-------+-----+

外连接方式左连接与右连接区别举例:

多表连接查询的步骤思路: 进行需求分析,根据查询需求找寻所有需要的表信息; 找寻表的关联,根据多张表字段信息获取关联的字段;(也可以查询间接关系) 组合后的需求,根据多张表组合后定义查询条件信息;

多表联合中多个表的结构信息一览:

多表查询信息练习题目分析:

01 统计zhang3,学习了几门课?

1
2
1 row in set (0.01 sec)
# 会将右表作为驱动表,进行外层循环

for each row in b for each row in a if b.y=a.x print row else print b.y a.null

1
# 根据需求所需的表信息

student course sc

1
-- 需要先将student与sc合成一张表,才能在和course建立关联;

student sc

1
2
3
-- 根据题意也可以通过学生的成绩信息,统计学生所学的课程数量;
# 建立表之间关联
select *

from student join sc on student.sno=sc.sno;

1
2
3
# 依据组合后的大表进行处理
mysql>
select student.sname,count(*)

from student join sc on student.sno=sc.sno group by student.sno;

1
mysql> select student.sname,count(*) from student join sc on student.sno=sc.sno group by student.sno having student.sname='zhang3';

02 查询zhang3,学习的课程名称有哪些?

03 查询xiaoA老师教的学生名?

04 查询xiaoA老师教课程的平均分数?

1
2
mysql> select student.sname,count(*) from student join sc on student.sno=sc.sno where student.sname='zhang3' group by student.sno ;
# 根据需求所需的表信息

student course sc

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
-- 需要先将student与sc合成一张表,才能在和course建立关联;
# 建立表之间关联
select * from student join sc on student.sno=sc.sno join course on sc.cno=course.cno;
-- 将三张表建立关联后,形成一张大表
# 依据组合后的大表进行处理
mysql> select * from student join sc on student.sno=sc.sno join course on sc.cno=course.cno where student.sname='zhang3';
mysql> select student.sname,course.cname from student join sc on student.sno=sc.sno join course on sc.cno=course.cno where student.sname='zhang3';
+--------+--------+
| sname  | cname  |
+--------+--------+
| zhang3 | linux  |
| zhang3 | python |
+--------+--------+
2 rows in set (0.00 sec)

或者

1
mysql> 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;

1
2
3
4
5
6
7
8
+--------+----------------------------+
| sname  | group_concat(course.cname) |
+--------+----------------------------+
| zhang3 | linux,python               |
+--------+----------------------------+
1 row in set (0.00 sec)
-- 以上sql语句书写是不严谨的,最好分组的条件为group by student.sno
# 根据需求所需的表信息

teacher course sc student

1
2
3
4
5
6
7
-- 根据题意需要4张表 teacher 与 course 在于 sc 最后关联student
# 建立表之间关联
select * from teacher join course on teacher.tno=course.tno join sc on course.cno=sc.cno join student on sc.sno=student.sno
-- 将四张表建立关联后,形成一张大表
# 依据组合后的大表进行处理
mysql>select * 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='xiaoA'
mysql> select teacher.tname,group_concat(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=‘xiaoA’ group by teacher.tno;

1
2
3
4
5
6
7
+-------+---------------------------------------------+
| tname | group_concat(student.sname)                 |
+-------+---------------------------------------------+
| xiaoA | zhang4,li4,wang5,zh4,zhao4,ma6,oldgirl,oldp |
+-------+---------------------------------------------+
1 row in set (0.00 sec)
# 根据需求所需的表信息

teacher course sc

1
2
3
4
5
6
-- 根据题意需要4张表 teacher 与 course 在于 sc 关联
# 建立表之间关联
select * from teacher join course on teacher.tno=course.tno join sc on course.cno=sc.cno;
# 依据组合后的大表进行处理
select * from teacher join course on teacher.tno=course.tno join sc on course.cno=sc.cno where teacher.tname='xiaoA';
mysql> select teacher.tname,avg(sc.score) from teacher join course on teacher.tno=course.tno join sc on cours

e.cno=sc.cno where teacher.tname=‘xiaoA’;

1
2
3
4
5
6
+-------+---------------+
| tname | avg(sc.score) |
+-------+---------------+
| xiaoA | 76.7500       |
+-------+---------------+
1 row in set (0.00 sec)

05 每位老师所教课程的平均分,并按平均分排序?

06 查询xiaoA老师教的不及格的学生姓名?

07 查询所有老师所教学生不及格的信息?

1
2
-- 以上方式查询其实是不严谨的,因为有可能xiaoA名称可能有重名的,而且xiaoA老师教多门课程,不能算总课程平均分
mysql> 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='xiaoA' group by

teacher.tno,course.cno;

1
2
3
4
5
6
7
8
9
+-------+---------------+
| tname | avg(sc.score) |
+-------+---------------+
| xiaoA | 76.7500       |
+-------+---------------+
1 row in set (0.00 sec)
-- 可以根据teacher.tno进行分组,这样可以将多个xiaoA名字的老师分组显示
-- 在结合课程编号进行分组,可以求出xiaoA老师每门课程的平均分(只有tno和cno均相同的才会分为一组显示)
# 根据需求所需的表信息

teacher course sc

1
2
3
4
5
-- 根据题意需要4张表 teacher 与 course 在于 sc 关联
# 建立表之间关联
select * from teacher join course on teacher.tno=course.tno join sc on course.cno=sc.cno;
# 依据组合后的大表进行处理
mysql>  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.tno,course.cno order by avg(sc.score);

1
2
3
4
5
6
7
8
9
+--------+--------+---------------+
| tname  | cname  | avg(sc.score) |
+--------+--------+---------------+
| xiaoQ  | python | 70.0000       |
| xiaoA  | mysql  | 76.7500       |
| oldboy | linux  | 80.6667       |
+--------+--------+---------------+
3 rows in set (0.00 sec)
# 根据需求所需的表信息

teacher course sc student

1
2
3
4
5
6
-- 根据题意需要4张表 teacher 与 course 在于 sc 最后关联student
# 建立表之间关联
select * from teacher join course on teacher.tno=course.tno join sc on course.cno=sc.cno join student on sc.sno=student.sno
-- 将四张表建立关联后,形成一张大表
# 依据组合后的大表进行处理
mysql> select teacher.tname,group_concat(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=‘xiaoA’ and sc.score<60 group by teacher.tno;

1
2
3
4
5
6
7
+-------+-----------------------------+
| tname | group_concat(student.sname) |
+-------+-----------------------------+
| xiaoA | li4,zh4                     |
+-------+-----------------------------+
1 row in set (0.00 sec)
# 根据需求所需的表信息

teacher course sc student

1
2
3
4
5
-- 根据题意需要4张表 teacher 与 course 在于 sc 最后关联student
# 建立表之间关联
select * from teacher join course on teacher.tno=course.tno join sc on course.cno=sc.cno join student on sc.sno=student.sno
-- 将四张表建立关联后,形成一张大表
mysql> select teacher.tname,group_concat(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 sc.score<60 group by teacher.tno;

1
2
3
4
5
6
7
+-------+-----------------------------+
| tname | group_concat(student.sname) |
+-------+-----------------------------+
| xiaoQ | zhang3                      |
| xiaoA | li4,zh4                     |
+-------+-----------------------------+
2 rows in set (0.00 sec)

多表查询过程别名应用: 在进行数据信息查询时,有些表和有些字段会被经常调用到,而且生成环境中表明和字段名会比较的复杂,在调用时不是很方便; 而且有些时候,查询的SQL语句信息会出现在代码中,在编写代码时也会不太规范,同时也不方便阅读,因此出现了数据库别名概念; 在进行数据库别名应用时,会经常用到两种别名: 表别名:(应用更广泛)

列别名:

1
2
# 举例说明别名作用,在没有使用别名时
select teacher.tname,group_concat(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 sc.score<60 group by teacher.tno;

1
2
# 进行表别名化
select a.tname,group_concat(d.sname)

from teacher as a join course as b on a.tno=b.tno join sc as c on b.cno=c.cno join student as d on c.sno=d.sno where c.score<60 group by a.tno;

1
2
3
4
5
6
7
8
9
+-------+-----------------------+
| tname | group_concat(d.sname) |
+-------+-----------------------+
| xiaoQ | zhang3                |
| xiaoA | li4,zh4               |
+-------+-----------------------+
2 rows in set (0.00 sec)
# 举例说明别名作用,在没有使用别名时
select a.tname,group_concat(d.sname)

from teacher as a join course as b on a.tno=b.tno join sc as c on b.cno=c.cno join student as d on c.sno=d.sno where c.score<60 group by a.tno;

1
2
3
4
5
6
7
8
9
+-------+-----------------------+
| tname | group_concat(d.sname) |
+-------+-----------------------+
| xiaoQ | zhang3                |
| xiaoA | li4,zh4               |
+-------+-----------------------+
2 rows in set (0.00 sec)
# 进行列别名化
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 b.cno=c.cno join student as d on c.sno=d.sno where c.score<60 group by a.tno;

1
2
3
+-----------+--------------------+
| 老师名       | 不及格学生名             |
+-----------+--------------------+

多表联合查询数据-纵向拼接 MySQL UNION 用于把来自多个 SELECT 语句的结果组合到一个结果集合中。语法为: 在多个 SELECT 语句中,对应的列应该具有相同的字段属性,且第一个 SELECT 语句中被使用的字段名称也被用于结果的字段名称。

UNION 与 UNION ALL 的区别 当使用 UNION 时,MySQL 会把结果集中重复的记录删掉,而使用 UNION ALL ,MySQL 会把所有的记录返回,且效率高于 UNION。

04 查询获取服务数据信息(嵌套查询)

在SQL语言中,一个SELECT…FROM…WHERE语句会产生一个新的数据集; 将一个查询语句完全嵌套到另一个查询语句中的的WHERE或HAVING的条件表达式中,这种查询称为嵌套查询; 通常把内部的、被另一个查询语句调用的查询称为"子查询"; 将调用子查询的查询语句称为"父查询",子查询还可以可以调用子查询; SQL语句允许由一系列简单查询构成嵌套结构,从而实现嵌套查询,极大增强了SQL的查询能力,使得用户视图的多样性提升;

不相关子查询: 子查询知识引入: 查询所有比’CLARK’工资高的员工的信息

查询所有全球所有国家中,城市人口数量大于中国北京的城市信息;

一条SQL语句含有多个select,先执行子查询,再执行外查询; 子查询可以独立运行,就称为不相关子查询;根据子查询的结果行数,可以分为单行子查询和多行子查询;

单行子查询: 单行子查询就是子查询输出的结果集为一行信息,可以直接进行比较即可;(< > =) 查询工资高于平均工资的雇员名字和工资; 查询和CLARK同一部门且比他工资低的雇员名字和工资; 查询和CLARK同一职位且比他工资高的雇员信息;

1
2
3
4
5
| xiaoQ     | zhang3             |
| xiaoA     | li4,zh4            |
+-----------+--------------------+
# 进行列别名化
select teacher.tname as a,course.cname as b,avg(sc.score) as c

from teacher join course on teacher.tno=course.tno join sc on course.cno=sc.cno group by teacher.tno,course.cno order by c;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
-- 列别名信息是可以在group by子句之后进行调用的
SELECT column,... FROM table1  UNION [ALL] SELECT column,... FROM table2 ...
# 没有应用子查询操作时
select sal from emp where ename='CLARK';   --2450
select * from emp where sal > 2450;
# 进行应用子查询操作后
select * from emp where sal > (select sal from emp where ename='CLARK');
# 没有应用子查询操作时
select population from city where name='Peking';       -- 城市人口数量为 7472000
select * from city where population > 7472000;
# 进行应用子查询操作后
select * from city where population > (select population from city where name='Peking');
select ename,sal from emp where sal >(select avg(sal) from emp);
select ename,sal,deptno from emp

where deptno = (select deptno from emp where ename=‘CLARK’) and sal <(select sal from emp where ename=‘CLARK’);

查询职务和SCOTT相同,比SCOTT雇佣时间早的雇员;

查询中国城市人口数量高于全国城市人口平均值的城市名称和人口数量情况; 查询和石家庄同一省份的其他城市信息,将其他城市人口数量比石家庄人口数量低的城市名称和人口数量输出显示;

多行子查询: 多行子查询就是子查询输出的结果集为多行信息,不能直接进行比较处理,需要借助 in 或者 any 或者 all 进行处理; 查询工资低于任意一个’CLERK’职位工资的雇员信息; 查询工资比所有的’SALESMAN’都高的雇员的编号、名字和工资 查询部门20中职务同部门10的雇员一样的雇员:

相关子查询: 一条SQL语句含有多个select,先执行外查询,再执行子查询; 子查询不可以独立运行,就称为相关子查询; 相关子查询优势:操作简单,功能强大(一些使用不相关子查询不能实现或者实现繁琐的子查询,可以使用相关子查询实现) 相关子查询缺陷:语句操作稍难理解

子查询知识引入: 查询最高工资的员工(不相关子查询)

1
select * from emp

where job = (select job from emp where ename=‘CLARK’) and sal >(select sal from emp where ename=‘CLARK’);

1
2
3
4
5
6
7
8
# 没有应用子查询操作时
select * from emp where ename='SCOTT';
+----------+--------+------------+------+---------------+-------+--------+-----------+
| EMPNO    | ENAME  | JOB        | MGR  | HIREDATE      | SAL   | COMM   | DEPTNO    |
+----------+--------+------------+------+---------------+-------+--------+-----------+
| 7788     | SCOTT  | ANALYST    | 7566 | 1987-04-19    | 3000  | NULL   | 20        |
+----------+--------+------------+------+---------------+-------+--------+-----------+
select * from emp

where job=‘ANALYST’ and HIREDATE <‘1987-04-19’;

1
2
# 进行应用子查询操作时
select * from emp

where job = (select job from emp where ename=‘SCOTT’) and hiredate < (select hiredate from emp where ename=‘SCOTT’);

1
select name,population from city where

countr ycode=‘chn’ and population > (select avg(population) from city where countr ycode=‘chn’);

1
select name,population,district from city where

district = (select district from city where name=‘shijiazhuang’) and population < (select population from city where name=‘shijiazhuang’);

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
select sal from emp where job = 'CLERK';     -- 1300  1100  950  800
select * from emp where sal < (select max(sal) from emp where job ='CLERK');
select * from emp where sal < (select sal from emp where job ='CLERK');
ERROR 1242 (21000): Subquer y returns more than 1 row
select * from emp where sal < any(select sal from emp where job ='CLERK');
select * from emp where sal < any(select sal from emp where job ='CLERK') AND job !='CLERK';
select empno,ename,sal from emp where sal > (select max(sal) from emp where job ='SALESMAN');
select empno,ename,sal from emp where sal > all(select sal from emp where job ='SALESMAN');
select job from emp where deptno = 20;      -- CLERK  ANALYST  MANAGER
select job from emp where deptno = 10;      -- MANAGER   PRESIDENT   CLERK
-- IN 等于其中任何一个
select * from emp where deptno = 20 and job in ("MANAGER","PRESIDENT","CLERK");
select * from emp where deptno = 20 and job in (select job from emp where deptno = 10);
select * from emp where deptno = 20 and job = any (select job from emp where deptno = 10);
select max(sal) from emp;
select * from emp where sal = (select max(sal) from emp);

语文 数学 英语 及格 优秀 不及格 查询本部门最高工资的员工 查询工资高于其所在部门的平均工资的那些员工

子查询信息练习题目分析:

01 查询每个部门平均薪水的等级(连接查询+子查询+分组查询)

子查询不仅可以出现在where条件中,还可以出现在from中;此练习题是一个不相关子查询;

02 根据学生成绩情况查询数据

一张成绩表,里面有3个字段:语文,数学,英语;请用一条SQL语句查询这表里的记录并按以下条件显示出来: 大于或等于80表示优秀,大于或等于60表示及格,小于60分表示不及格,显示格式为: 创建测试数据:

此题需求,需要利用case where(多分支判断语句)或 if (双分支语句)进行题目处理;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 查询本部门(10)最高工资的员工
select * from emp where deptno=10;
select * from emp where deptno=10 and sal = (select max(sal) from emp where deptno=10);
# 查询本部门(20)最高工资的员工
select * from emp where deptno=20;
select * from emp where deptno=20 and sal = (select max(sal) from emp where deptno=20);
# 查询本部门(30)最高工资的员工
select * from emp where deptno=30;
select * from emp where deptno=30 and sal = (select max(sal) from emp where deptno=30);
select * from emp where deptno=10 and sal = (select max(sal) from emp where deptno=10)

union

1
select * from emp where deptno=20 and sal = (select max(sal) from emp where deptno=20)

union

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
select * from emp where deptno=30 and sal = (select max(sal) from emp where deptno=30);
select * from emp e where e.deptno=10 and sal = (select max(sal) from emp where deptno=10);
select * from emp e where sal = (select max(sal) from emp where deptno=e.deptno);
# 查询工资高于其所在部门10的平均工资的那些员工:
select avg(sal) from emp where deptno=10;
select * from emp where deptno = 10 and sal >2916.6667;
select * from emp where deptno = 10 and sal >(select avg(sal) from emp where deptno=10);
# 查询工资高于其所在部门20的平均工资的那些员工:
select * from emp where deptno = 20 and sal >(select avg(sal) from emp where deptno=20);
# 查询工资高于其所在部门30的平均工资的那些员工:
select * from emp where deptno = 30 and sal >(select avg(sal) from emp where deptno=30);
select * from emp  where sal >(select avg(sal) from emp  where deptno=deptno);    --必须要应用别名功能
select * from emp e1  where sal >(select avg(sal) from emp e2 where e2.deptno=e1.deptno);
# 查询每个部门平均薪水
select deptno,avg(sal) from emp group by deptno;
# 查询每个员工的薪水的等级
select * from emp e join salgrade sg on e.sal between sg.losal and sg.hisal;
# 查询每个部门平均薪水的等级
select * from (select deptno,avg(sal) asl from emp group by deptno) asg

join salgrade sg on asg.asl between sg.losal and sg.hisal;

1
select asg.*,sg.grade from (select deptno,avg(sal) asl from emp group by deptno) asg

join salgrade sg on asg.asl between sg.losal and sg.hisal;

1
2
3
4
5
6
7
-- 创建数据表
create table table1 (chinese int(3),maths int(3),english int(3));
-- 创建测试数据
insert into table1 values(80,78,67);
insert into table1 values(100,45,67);
-- 查询测试数据信息
select * from table1;

比赛日 胜负情况 2005-05-09 胜 2005-05-09 胜 2005-05-09 负 2005-05-09 负 2005-05-10 胜 2005-05-10 负 2005-05-10 负 比赛日期 胜场数量 负场数量 2005-05-09 2 2 2005-05-10 1 2

02 根据比赛日胜负情况,统计胜负结果;(case-when/ if+子查询+分组)

测试数据表中内容如下: 如果要生成下表结果信息,该如何写SQL语句? 创建测试数据:

1
2
-- 利用if语句实现方法:
select *,

if(chinese >=80,‘优秀’,if(chinese >=60,‘及格’,‘不及格’)) from table1;

1
select *,

if(chinese >=80,‘优秀’,if(chinese >=60,‘及格’,‘不及格’)), if(maths >=80,‘优秀’,if(maths  >=60,‘及格’,‘不及格’)), if(english >=80,‘优秀’,if(english  >=60,‘及格’,‘不及格’)) from table1; select if(chinese >=80,‘优秀’,if(chinese >=60,‘及格’,‘不及格’)) as 语文, if(maths >=80,‘优秀’,if(maths  >=60,‘及格’,‘不及格’)) as 数学, if(english >=80,‘优秀’,if(english  >=60,‘及格’,‘不及格’)) as 英语 from table1;

1
2
-- 利用case语句实现方法:
select *,

case when chinese >=80 then ‘优秀’ when chinese >=60 then ‘及格’ else ‘不及格’ end ‘语文’ from table1; select case when chinese >=80 then ‘优秀’ when chinese >=60 then ‘及格’ else ‘不及格’ end ‘语文’, case when maths >=80 then ‘优秀’ when maths >=60 then ‘及格’ else ‘不及格’ end ‘数学’, case when english >=80 then ‘优秀’ when english >=60 then ‘及格’ else ‘不及格’ end ‘英语’ from table1;

1
2
3
4
5
6
-- 创建数据表
create table table2 (gamedate date, result char(3));
-- 创建测试数据
insert into table2 values ('2005-05-09','胜');
insert into table2 values ('2005-05-09','胜');
insert into table2 values ('2005-05-09','负');

此题需求,需要利用case where(多分支判断语句)/if(双分支判断语句)结合子查询,以及分组操作进行题目处理;

1.6.5 操作管理应用实战(获取元数据)

01 元数据概念介绍:

元(meta)一般会被翻译成中文是”关于…的…”,元数据(meta data)等价于data about data,表示关于数据的数据; 一般是元数据就是结构化数据,例如存储在数据库里的数据,规定了字段的长度。类型等; 元数据就是描述数据的数据,在MySQL中就是描述database的数据,属性,状态等相关信息; 表示在数据库服务中有哪些数据库,库中有哪些表,表中有多少字段,字段是什么类型等等,这样的数据就是数据库的元数据; 02 元数据获取方法:

元数据获取方式一:利用命令获取(show)

1
2
3
4
5
6
7
8
insert into table2 values ('2005-05-09','负');
insert into table2 values ('2005-05-10','胜');
insert into table2 values ('2005-05-10','负');
insert into table2 values ('2005-05-10','负');
-- 查询测试数据信息
select * from table2;
-- 利用if语句实现方法:
select *,

if(result=‘胜’,1,0) 胜, if(result=‘负’,1,0) 负 from table2;

1
2
-- 方法01:直接使用group by
select gamedate,

sum(if(result=‘胜’,1,0) )胜, sum(if(result=‘负’,1,0) )负 from table2 group by gamedate;

1
2
3
-- 方法02:直接使用group by+子查询
select gamedate,sum() ,sum()  from (
select gamedate,

if(result=‘胜’,1,0) 胜, if(result=‘负’,1,0) 负 from table2) table3 group by gamedate;

1
2
-- 利用case语句实现方法:
select gamedate,

case when result=‘胜’ then 1 else 0 end 胜, case when result=‘负’ then 1 else 0 end 负 from table2;

1
2
-- 方法01:直接使用group by
select gamedate,

sum(case when result=‘胜’ then 1 else 0 end) 胜, sum(case when result=‘负’ then 1 else 0 end) 负 from table2 group by gamedate;

1
2
3
-- 方法02:直接使用group by+子查询
select gamedate,sum() ,sum()  from(
select gamedate,

case when result=‘胜’ then 1 else 0 end 胜, case when result=‘负’ then 1 else 0 end 负 from table2) table3 group by gamedate;

1
2
3
4
5
6
# 常用SQL语句的show命令查看元数据信息
mysql> show databases;
-- 查询数据库服务中的所有数据库信息(数据库名称-元数据)
mysql> show tables;
mysql> show tables from mysql;
-- 查询数据库服务中的相应数据表信息(数据表名称-元数据)

说明:使用show语句虽然可以快速得到相应的数据库元数据信息,但是查询功能过于单一,想查询全面信息,就需要执行多条语句;

元数据获取方式二:利用库中视图(information_schema) 视图概念: 将查询基表元数据语句信息方法封装在一个变量或别名中,这个封装好的变量或别名就成为视图,视图信息都是存储在内存中的表 元数据信息存储在系统基表中,通过一般的select命令只能查看数据信息,不能查看到系统基表,以免被随意调整篡改;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
mysql> show create database <库名>;
-- 查询数据库服务中的建库语句信息 (建库语句参数-元数据 建库语句就是DDL语句,定义建立数据库的属性信息)
mysql> show create table <表名>;
-- 查询数据库服务中的建表语句信息 (建表语句参数-元数据 建表语句就是DDL语句,定义建立数据表的属性信息)
mysql> desc <表名>;
mysql> show columns from <表名>;
-- 查询数据库服务中的数据表的结构(数据表的列定义信息-元数据)
mysql> show table status from <库名>;
-- 查询数据库服务中的相应数据表状态 (数据表的状态信息/统计信息-元数据)
mysql> show table status from world like 'city' \G

*************************** 1. row *************************** Name: city                 – 数据表名称信息 Engine: InnoDB           – 使用的数据库引擎信息 Version: 10 Row_format: Dynamic Rows: 4046                – 数据表的行数信息 Avg_row_length: 101         – 平均行长度 Data_length: 409600 Max_data_length: 0 Index_length: 114688      – 索引长度信息 Data_free: 0 Auto_increment: 4080       – 自增列的值计数 Create_time: 2022-11-04 09:13:27   – 数据表创建时间 Update_time: NULL Check_time: NULL Collation: utf8mb4_0900_ai_ci      – 校对规则信息 Checksum: NULL Create_options: Comment:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1 row in set (0.00 sec)
-- 查看数据库服务中的具体数据库表的状态信息(属于单库或单表查询)
mysql> show index from world.city;
-- 查询数据库服务中的相应数据表的索引情况(了解即可)
mysql> show grants for root@'localhost';
-- 查询数据库服务中的用户权限属性配置信息
mysql> show [full] processlist;
-- 查询数据库服务的系统状态信息,表示当前数据库的所有连接情况
mysql> show variables;
mysql> show variables like '%xx%';
-- 查询数据库服务的所有配置信息
mysql> show status;
mysql> show status like '%lock%';
-- 查询数据库服务的系统整体状态,表示当前数据库服务运行的即时状态情况
mysql> show binar y logs;
-- 查询数据库服务的所有二进制日志信息(binlog日志)
mysql> show master status;
-- 查询数据库服务正在使用的二进制日志
mysql> show binlog events in 'binlog.000009';
-- 查询数据库服务具体二进制日志内容事件信息
mysql> show engine innodb status \G
-- 查询数据库服务存储引擎相关信息
mysql> show slave hosts;
-- 在数据库服务主库查看从库信息
mysql> show slave status;
-- 查询数据库服务主从状态信息

而查询基表的语句过于复杂,可以将整个查询基表语句定义为一个视图信息(等价于别名/变量),调取视图等价于调取查询基表语句; information_schema库中的内存表都是每次数据库服务启动时生成的,里面存储了查询元数据基表的视图信息; 视图定义: 视图查询:

1
2
# 假设查询基表语句信息如下
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 b.cno=c.cno join student as d on c.sno=d.sno where c.score<60 group by a.tno;

1
2
3
4
5
6
7
8
9
-- 会获取如下查询后的信息
+-----------+--------------------+
| 老师名       | 不及格学生名             |
+-----------+--------------------+
| xiaoQ     | zhang3             |
| xiaoA     | li4,zh4            |
+-----------+--------------------+
# 可以将复杂的查询语句定义为视图
create view tv 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 b.cno=c.cno join student as d on c.sno=d.sno where c.score<60 group by a.tno;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 调取视图信息等价于调取复杂的查询语句
mysql> select * from tv;
+-----------+--------------------+
| 老师名       | 不及格学生名             |
+-----------+--------------------+
| xiaoQ     | zhang3             |
| xiaoA     | li4,zh4            |
+-----------+--------------------+
2 rows in set (0.00 sec)
# 切换进入information_schema数据库中查看表信息
mysql> use information_schema;
mysql> show tables;
-- 此时看到的所有表信息,其实都是视图信息
# 查看获取视图信息创建语句
mysql> show create view tables;
-- 查看tables这个视图表的创建过程
# 查看视图表信息应用
# 统计数据库资产信息(数据资产),获取每个库中表的个数和名称信息(业务相关)
mysql> desc information_schema.tables;
-- 查看information_scheam中的tables表的结构信息;
mysql> select table_schema,count(*),group_concat(table_name) from information_schema.tables group by table_schema;
-- 获取相应数据库中表的个数,与数据库中拥有的表信息
mysql> select table_schema,count(*),group_concat(table_name) from information_schema.tables where table_schema not in

(‘mysql’,‘sys’,‘performance_schema’,‘information_’) group by table_schema;

1
2
# 统计数据库资产信息(数据资产),获取每个数据库数据占用磁盘空间
mysql> select table_schema,sum(table_rows*avg_row_length+index_length)/1024/1024 from information_schema.tables where table_schema not in

(‘mysql’,‘sys’,‘performance_schema’,‘information_’) group by table_schema;

1
2
# 统计数据库资产信息(数据资产),获取具有碎片信息的表
mysql> select table_schema,table_name,data_free from information_schema.tables where table_schema not in ('mysql','sys','performance_schema','information_')

and data_free >0 ;

1
2
3
4
5
-- 碎片信息过多会导致索引信息失效,以及统计信息不真实的情况
# 统计数据库资产信息(数据资产),处理具有碎片信息的表
mysql> alter table t1 engine=innodb;

| 序号 | 字段信息 | 解释说明 |

|—|—|—|

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
| 01 | TABLE_SCHEMA | 表示数据表所属库的名称信息 |
| 02 | TABLE_NAME | 表示数据库中所有数据表名称 |
| 03 | ENGINE | 表示数据库服务中的引擎信息 |
| 04 | TABLE_ROWS | 表示数据库相应数据表的行数 |
| 05 | AVG_ROW_LENGTH | 表示数据表中每行的平均长度 |
| 06 | INDEX_LENGTH | 表示数据表中索引信息的长度 |
| 07 | DATA_FREE | 表示数据库服务碎片数量信息 |
| 08 | CREATE_TIME | 表示数据表创建的时间戳信息 |
| 09 | UPDATE_TIME | 表示数据表修改的时间戳信息 |
| 10 | TABLE_COMMENT | 表示数据表对应所有注释信息 |

tables视图表的结构信息: 关注的视图表字段说明:

1
2
-- 可以对已经是innodb存储引擎的表做操作,实现整理碎片功能
mysql> select concat("alter table ",table_schema,".",table_name," engine=innodb") from information_schema.tables where table_schema not in

(‘mysql’,‘sys’,‘performance_schema’,‘information_’) and data_free >0 ;

1
2
3
-- 可以对已经是innodb存储引擎的表做操作,实现批量整理碎片功能
# 统计数据库资产信息(数据资产),获取数据库中非innodb表信息
mysql>select table_schema,table_name,engine from information_schema.tables where table_schema not in ('mysql','sys','performance_schema','information_') and

engine!=‘innodb’;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
-- 获取非innodb数据库引擎表
mysql> use school;
mysql> create table t1 (id int) engine=myisam;
mysql> create table t2 (id int) engine=myisam;
mysql> create table t3 (id int) engine=myisam;
-- 模拟创建一些myisam引擎数据表
# 统计数据库资产信息(数据资产),修改数据库中非innodb表信息替换成innodb
mysql> alter table world.t1 engine=innodb;
-- 可以对不是innodb存储引擎的表做操作,实现数据表引擎修改
mysql> select concat("alter table ",table_schema,".",table_name," engine=innodb") from information_schema.tables where table_schema not in

(‘mysql’,‘sys’,‘performance_schema’,‘information_’) and engine !=‘innodb’;

1
mysql> select concat("alter table ",table_schema,".",table_name," engine=innodb;") from information_schema.tables where table_schema not in

(‘mysql’,‘sys’,‘performance_schema’,‘information_’) and engine!=‘innodb’ into outfile ‘/tmp/alter.sql’;

1
2
3
ERROR 1290 (HY000): The MySQL ser ver is running with the --secure-file-priv option so it cannot execute this statement
vim /etc/my.cnf
[mysqld]

secure-file-priv=/tmp

1
2
3
-- 修改配置文件参数信息,实现将数据库操作的数据信息导入到系统文件中,配置完毕重启数据库服务
mysql> source /tmp/alter.sql
-- 可以对不是innodb存储引擎的表做操作,实现数据表批量化引擎修改,调用数据库脚本信息

说明:使用information_schema的视图查看功能,可以看到全局数据库或数据表的元数据信息,探究全局层面的元数据