yuanxiaojiang
人的放纵是本能,自律才是修行

数据库服务语句应用(基础)

  mysql默认四张库⭐⭐⭐⭐

数据库名称类型主要作用关键特性
information_schema 元数据库 提供所有数据库对象的元数据视图
(表/列/索引等结构信息)
• 只读虚拟数据库
• 数据实时从内存生成
• 符合SQL标准
mysql 权限库 存储用户权限、密码、存储过程等核心安全数据 • 使用MyISAM引擎(8.0+部分表改用InnoDB)
• 直接修改高风险
• 密码字段5.7+采用caching_sha2加密
performance_schema 性能库 采集服务器事件和性能指标
(SQL执行/锁/连接等微观数据)
• 零存储开销设计
• 可配置监控粒度
• 提供500+监控指标
sys 诊断库 基于performance_schema的友好视图
(提供DBA友好的性能诊断报告)
• 完全由视图和存储过程构成
• 8.0+默认安装
• 支持标准化性能分析

   SQL( Structured Query Language ):结构化查询语言

SQL语句几种常用的标准:SQL89 / SQL 92 / SQL 99 / SQL 03

 DDL Data Definition Language(数据定义语言)

专门用于定义和管理数据库结构及组成:增删库、增删表、增删索引、增删用户

主要涉及语句:CREATE、ALTER、DROP

查看DDL语言负责的操作行为:mysql> ? Data Definition;

 DCL Data Control Language(数据控制语言)

主要用来定义访问权限和安全级别

主要涉及语句:GRANT(用户授权)、REVOKE(权限回收)、COMMIT(提交)、ROLLBACK(回滚)

查看DCL语言负责的操作行为:mysql> ? Account Management;

 DML Data Manipulation Language(数据操作语言)

主要针对数据库里的表里的数据进行操作

主要涉及语句:SELECT、INSERT、DELETE、UPDATE

查看DML语言负责的操作行为: mysql> ? Data Manipulation;

  数据库字符编码设置

 常见的字符编码

ASCII码:1个字节(8位⼆进制)来表示⼀个字符,共可以表示2^8=256个字符

GBK:2个字节(16位二进制)来表示一个字符,共可以表示2^16=65536个字符

Unicode编码:4个字节(32位二进制)来表示一个字符(造成空间的极大浪费) 

UTF-8(Unicode Transform Format)编码:1~4个字节(8位~32位二进制)来表示一个字符

 MySQL服务的字符编码相关系统变量⭐⭐⭐⭐

# 显示mysql服务支持的所有字符集及其描述信息
mysql> show charset;
+----------+---------------+---------------------+-----------------------------+
|  Charset |  Description  |  Default collation  |           Maxlen            |
| 字符集名称 |   字符集描述    |   字符集默认排序规则   |    单个字符占用的最大字节数    |
+----------+-------------- -+---------------------+----------------------------+

# 显示当前MySQL服务的字符编码相关系统变量
mysql> show variables like '%character%';
character_set_server: 服务器默认字符集(新建数据库时使用)
character_set_database: 当前数据库的默认字符集
character_set_client: 客户端发送SQL语句使用的字符集
character_set_connection: 服务器接收SQL语句后转换的字符集
character_set_results: 服务器返回结果使用的字符集
character_set_filesystem: 文件系统字符集(通常为binary)
character_set_system: MySQL内部元数据存储使用的字符集(固定为utf8)

# utf8和utf8mb4之间有什么区别
两种字符集的字符存储量不同     
    utf8:最多存储3字节长度字符(张--3字节)
    utf8mb4:最多存储4字节长度字符(emoji表情--4字节、张--3字节)

 字符集转换流程⭐⭐

1655912700889

# 01.mysql Server收到请求时将请求数据从 character_set_client 转换为 character_set_connection;
# 02.进行内部操作前将请求数据从 character_set_connection 转换为内部操作字符集;
    使用每个数据字段的 CHARACTER SET 设定值;
    若上述值不存在,则使用对应数据表的字符集设定值;
    若上述值不存在,则使用对应数据库的字符集设定值;
    若上述值不存在,则使用 character_set_server 设定值;
# 03.最后将操作结果从内部操作字符集转换为 character_set_results

 数据库字符集永久配置⭐⭐

# 编辑修改服务配置文件参数信息my.cnf(全局设置)
[mysqld]
character-set-server=utf8mb4  # 服务器默认字符集
collation-server=utf8mb4_unicode_ci  # 服务器默认排序规则
[client]
default-character-set=utf8mb4  # 所有客户端连接的默认字符集
[mysql]
default-character-set=utf8mb4  # mysql命令行客户端字符集

 数据已存在的据库服务字符编码信息调整方法⭐⭐⭐⭐

# 假设数据库表原有字符集为gbk,并且已经存储数据了,需要将表和数据字符集进行调整转换utf8mb4
# 方法一:
  mysql > alter table t1 charset utf8mb4;   
  不严谨的方法,只会影响之后存储的数据,不会修改之前存储的数据
# 方法二:
  锁表逻辑导出数据(例如:mysqldump)
  重新创建数据空表(设置目标字符集)
  导入备份数据信息
  -- 严谨的方法,可以影响之后存储的数据,也会修改之前存储的数据
  -- 字符集转换是可以的,但是必须保证修改后的字符集是修改前的严格超集(包含)

 字符编码校对规则(排序规则)⭐⭐

在查询数据信息时,影响数据信息的查询输出和排序效果(字符比较是按照字符编码还是对应的二进制数进行比较)

utf8mb4字符集中常用的排序规则:utf8mb4_unicode_ci、utf8mb4_general_ci、utf8mb4_bin

排序规则后缀解释说明
_ci 不区分大小写,Case-insensitive的缩写
_cs 区分大小写,Case-sensitive的缩写
_ai 不区分重音,Accent-insensitive的缩写
_as 区分重音,Accent-sensitive的缩写
_bin 采用二进制方式存储数据信息

 数据库/表 字符集/校验规则 的创建和修改⭐⭐

-- 创建新数据库/表时指定字符集、校验规则
  create database 库名 charset 字符集 collate 校验规则;
  create table 表名(字段名 类型) charset 字符集 collate 校验规则;
-- 修改数据库或表的字符集、校验规则
  alter database 库名 charset 新的字符集 collate 新的校验规则
  alter table 表名 charset 新的字符集 collate 新的校验规则名;

  数据类型、约束条件、属性

 数据类型

 数字类型 整型(数字/整数)

int:普通整型数字(1字节)

tinyint:微小整型数字(4字节)

bigint:超大整型数字(8字节)

  浮点(数字/小数)

float:单精度浮点数

double:双精度浮点数

decimal:定点数

字符串类型  字符(字符/符号/整数)

char(0~255):定长字符类型

varchar(0~65535):变长字符类型

enum:枚举类型

set:集合类型

text:大文本类型

时间类型 时间类型

date:日期类型

time:时间类型

datetime:日期时间类型(1000~9999)占8字节

timestamp:时间戳类型(1970~2038)格林威治时间 占4字节

二进制类型 二进制类型  
json类型 json类型  

详细的数据类型知识参考链接:https://m.php.cn/article/460317.html

 常见的约束定义⭐⭐⭐

约束方法解释说明
PK(primary key) 表示主键约束,非空且唯一(表中只能有一个主键)
UK(unique key) 表示唯一约束
NN(not null) 表示非空约束
FK(foreign key) 表示外键约束,多表之间关联使用

 常见的属性定义⭐⭐⭐

属性信息解释说明
default 设定默认数据信息,可以实现自动填充
auto_increment 设定数值信息自增,可以实现数值编号自增填充(一般配合主键使用)
comment 设定数据注释信息
unsigned 设定数值信息非负,可以实现数值信息列不能出现负数信息

  外键foreign key⭐⭐⭐⭐⭐

外键字段必须与引用表(父表主键)的数据类型严格保持一致

外键不能被修改,只能先删除再新增

 创建外键⭐⭐⭐

方法一:在创建表的时候就增加外键: 在表字段之后使用foreign key

foreign key(外键字段) references 主表(主键);

-- 创建外键关联的父表
create table class(
id int primary key auto_increment,
name varchar(10) not null comment "班级名字,不能为空",
room varchar(10) comment '教室:允许为空'
) charset utf8;

-- 创建子表使用外键
create table student(
id int primary key auto_increment,
number char(10) not null unique comment "学号:不能重复",
name varchar(10) not null comment "姓名",
c_id int,
foreign key(c_id) references class(id) 
) charset utf8;

-- 查看外键是否配置成功
show create table class;
show create table student;

方法二:在创建表之后添加外键

alter table 表名 add constraint 外键名 foreign key(外键字段) references 父表(主键字段);

-- 创建没有外键信息的表
create table t_foreign(
id int primary key auto_increment,
c_id int
)charset utf8;

-- 在没有外键的表中添加字段
alter table t_foreign add constraint class_foreign foreign key(c_id) references class(id);

 设置删除外键⭐⭐

-- 删除外键语法格式
alter table 表名 drop foreign key 外键名;

-- 删除表(t_foreign)中外键信息
alter table t_foreign drop foreign key class_foreign;

 外键约束说明

约束01:外键对子表的数据写操作约束(增加和更新)

如果子表中插入的数据所对应的外键在父表不存在,创建不能成功.

image

约束02:外键对父表也有数据约束

当父表操作一个记录,但是该记录被子表所引用的时候,那么父表的操作将会被限制(更新: 主键和删除)

image

 数据库数据模式(SQL_mode)⭐⭐

SQL_mode用于设置MySQL服务器的工作模式,控制SQL语法校验规则和数据校验的严格程度,确保SQL语句的执行符合预期标准

例如:日期信息不能出现 0000-00-00 信息,月份只能是1-12,日期只能是1-31,一旦违反常识便会报错;

例如:在进行数据运算时,除法运算时,除数不能为0;

例如:当定义数据类型为char(10),不能超过字符长度,超过长度就报错;

image

当进行数据库服务版本升级时,可能之前版本数据信息不能满足新版本数据库服务的SQL_mode信息设定,需要暂时设置SQLmode为空
mysql> set global sql_mode='';
-- 配置完毕后,可以重新登录数据库服务进行检查确认

 SQL_mode配置参数信息

模式参数配置解释说明
ONLY_FULL_GROUP_BY 对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么这个SQL是不合法的,因为列不在GROUP BY从句中。
STRICT_TRANS_TABLES 在该模式下,如果一个值不能插入到一个事物表中,则中断当前的操作,对非事物表不做限制
NO_ZERO_IN_DATE 在严格模式下,不允许日期和月份为零
NO_ZERO_DATE 设置该值,mysql数据库不允许插入零日期,插入零日期会抛出错误而不是警告
ERROR_FOR_DIVISION_BY_ZERO 在INSERT或UPDATE过程中,如果数据被零除,则产生错误而非警告。如 果未给出该模式,那么数据被零除时MySQL返回NULL
NO_ENGINE_SUBSTITUTION 如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常
NO_AUTO_VALUE_ON_ZERO 该值影响自增长列的插入。默认设置下,插入0或NULL代表生成下一个自增长值。如果用户希望插入的值为0,该列又是自增长的,那么这个选项就有用了。
NO_AUTO_CREATE_USER 禁止GRANT创建密码为空的用户
PIPES_AS_CONCAT 将"||"视为字符串的连接操作符而非或运算符,这和Oracle数据库是一样的,也和字符串的拼接函数Concat相类似
ANSI_QUOTES 启用ANSI_QUOTES后,不能用双引号来引用字符串,因为它被解释为识别符

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

  数据库帮助标签

-- 基本帮助标签
mysql > \h  
mysql > help

-- 分类帮助标签
mysql > help contents
mysql > ? contents

-- 语句级帮助标签
mysql > help create database 
mysql > ? create database 

  DDL:数据定义语言⭐⭐⭐⭐⭐

 数据库相关操作⭐⭐⭐⭐

-- 创建数据库
create <database/schema> 数据库名 <character set/charset> 字符编码 collate 字符编码校验规则;

-- 修改数据库信息
alter database 数据库名 charset 字符编码 collate 字符编码校验规则;

-- 查看数据库信息
show databases;  -- 查看所有数据库信息
show databases like '%yuan%';  -- 检索查看指定的数据库信息
show create database 数据库名;  -- 查看数据库语句信息

-- 删除数据库信息
drop <database/schema> 数据库名;

-- 切换数据库
use 数据库名;
select database();  -- 查看当前所在数据库信息

定义数据库规范说明:

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

 数据表相关操作⭐⭐⭐⭐

  • 创建表
create table <表名> (<字段名1> <类型1> ,<字段名n> <类型n>);
  • 查看表
show tables;  -- 查看数据库所有的表信息
desc 表名;  -- 查看数据库中指定表数据结构信息
show create table 表名;  -- 查看数据库中指定表创建语句信息
  • 修改表
-- 修改表属性信息
  -- 修改数据表名
    rename table 旧表名 to 新表名;
    alter table 旧表名 rename 新表名;
  -- 修改表编码信息
    alter table 表名 charset 字符编码;
  
-- 修改表结构信息
  -- 数据表中添加新的表结构字段
    alter table <表名> add column <字段名称> <数据类型> <约束与属性> [comment '注释'] [选项参数];
    -- 插入字段微信号到student表中的age字段之后
      alter table student add column wechat varchar(64) not null unique key comment '微信号' after age;
    -- 插入字段手机号到student表中最前列(默认追加)
      alter table student add column telephone varchar(11) not null unique key comment '手机号' first; 
-- 数据表中修改已有表结构字段(数据类型 约束与属性 alter table <表名> modify column <字段名称> <数据类型> <约束与属性> [comment '注释'] [选项参数]; -- 修改数据表已有表结构字段(字段名称 数据类型 约束与属性 alter table <表名> change column <旧字段名称> <新字段名称> <数据类型> <约束与属性> [comment '注释'] [选项参数]; -- 数据表中删除已有表结构字段 alter table <表名> drop column <字段名称>; -- 删除数据表中已有表结构字段(约束与属性 alter table <表名> drop index <字段名称> ;
  • 删除表
drop table <表名>;

定义数据表规范说明:

  • 创建数据表名称规范:要和业务有关(含库前缀),不要有大写字母,不要数字开头,不要含有系统关键字信息,名称不要太长;

  • 创建数据表属性规范:属性信息显示设置,引擎选择InnoDB,字符集选择utf8/utf8mb4,表信息添加注释;

  • 创建数据列属性规范:名称要有意义,不要含有系统关键字信息,名称不要太长;

  • 创建数据类型的规范:数据类型选择合适的、足够的、简短的;

  • 创建数据约束的规范:每个表中必须都要有主键,最好是和业务无关列,实现自增功能,建议每个列都非空(避免索引失效)/加注释

  • 删除数据表操作规范:对于普通用户不能具有删表操作,需要操作删表时需要严格审核

  • 修改数据表结构规范:在数据库8.0之前,修改数据表结构需要在业务不繁忙时进行,否则会产生严重的锁

    如果出现紧急修改表结构信息需求时,可以使用工具进行调整,比如使用:pt-osc、gh-ost,从而降低对业务影响

 数据库面试题⭐⭐⭐

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

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),       
    'is_deleted' varchar(200) comment '删除标记(1 ,删除;0,不删除,有效)',     
    primary 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='区域配送运费设置';
表创建信息
# 修改建议01:表明信息略长可以进行调整
create table 't_area_distribution_cost' 
​
# 修改建议02:数据类型信息设定尽量合适
'city_id' varchar(200),   
'city_name' varchar(200),  
​
# 修改建议03:定义索引信息没有设置非空
'city_id' varchar(200),
'warehouse_id' varchar(200),
'station_region_id' varchar(200),
​
# 修改建议04:表中字段列信息可以加注释
 'city_id' varchar(200),
'city_name' varchar(200),
'warehouse_id' varchar(200),
'warehouse_name' varchar(200)  ,
'station_region_id' varchar(200),
优化方案

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

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

  DML:数据管理语言⭐⭐⭐⭐⭐

-- insert:数据表数据插入命令语法 
insert into <表名> [( <字段名1>[,..<字段名n > ])] values ( 值1 )[, ( 值n )];
-- update:数据表数据修改命令语法
update 表名 set 字段=新值,… where 条件;
-- delete:数据表数据删除命令语法
  delete from 表名 where 表达式;  -- 如果不加条件会逐行删除表数据

 禁止修改命令(update/delete)不加条件信息执行命令⭐⭐⭐

  • 修改后命令生效条件
-- WHERE 子句使用主键或索引列
  DELETE FROM 表名 WHERE 主键列 = 值;
  DELETE FROM 表名 WHERE 索引列 = 值;
-- 使用 LIMIT 子句(即使没有索引)
  DELETE FROM 表名 WHERE 条件 LIMIT 行数;
  • 服务端
# 方法1:临时执行
set global sql_safe_updates=1;  # 退出重新登陆生效

# 方法2:永久生效
[root@db01 ~]# vi /etc/my.cnf
[mysqld]
init-file=/opt/init.sql
# init-file:用于指定一个包含 SQL 语句的文件,该文件会在 MySQL 服务器启动时自动执行

# 新建脚本
echo 'set global sql_safe_updates=1;' >/opt/init.sql
chmod +x /opt/init.sql
/etc/init.d/mysqld restart

# 检验 
[root@db01 ~]# mysql -uroot -proot -e "select @@global.sql_safe_updates"
  • 客户端
# 方法一:将sate_updates=1加入到my.cnf的client标签下

# 方法2:设置数据库别名操作方式
  alias mysql='mysql -U'
  U   --safe-updates  Only allow UPDATE and DELETE that uses keys
      表示以安全更新模式登录数据库,并放入/etc/profile永久生效

 伪删除(本质:利用update代替delete)⭐⭐⭐

伪删除是通过更新状态字段标记数据为"删除"状态,而非物理删除数据,从而保留数据可恢复性的技术手段

-- 在原有表中添加新的状态列
alter table student add column state tinyint not null default 1;
-- 将要删除的信息的状态改为0,实现伪删除效果
update student set state=0 where id=1;
-- 实现查询时不要获取状态为0的信息,即不查看获取伪删除数据信息
select * from student where state=1;

 drop/truncate/delete 三者区别⭐⭐⭐⭐⭐

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

自增列信息值调整方法:alter table 表名 auto_increment=10;

DQL:数据库查询语言⭐⭐⭐⭐

  查询服务配置信息

 查询获取信息命令语法

mysql> select @@配置参数信息;
mysql> show variables like '检索的配置信息';

 数据库服务在线调整配置参数方法

-- 表示在线临时调整配置参数,并且只是当前会话生效(session是默认方式,不是所有配置都可以调整)
    mysql > set session innodb_flush_log_at_trx_commit=1
    mysql > set sql_log_bin=0;
-- 表示在线临时调整配置参数,并且将会影响所有连接(global是全局方式,可以进行所有配置调整)
    mysql > set global innodb_flush_log_at_trx_commit=1
-- 数据库服务配置参数在线调整参数,只是临时生效,数据库服务重启后配置会失效,想要永久生效需要修改配置文件信息

 获取函数输出信息(concat)

  mysql> select concat(user,"@","'",host,"'") from mysql.user;
  +-------------------------------+
  | concat(user,"@","'",host,"'") |
  +-------------------------------+
  | root@'172.16.1.%'             |
  +-------------------------------+

  单表查询⭐⭐⭐

# 数据表数据查询命令语法 
select <字段1,字段2,...> from <表名> [WHERE 条件] group by <字段1,字段2,...> \
having 条件 order by 字段 limit 限制信息;
  • 测试文件下载地址:https://dev.mysql.com/doc/index-other.html
  • -- 将world.sql数据库文件上传到数据库服务器中,根据存储路径进行加载恢复数据库数据
  • mysql> source ~/world-db/world.sql

 区间条件表示方法

符号解释说明
< 表示小于指定数值的信息作为条件
> 表示大于指定数值的信息作为条件
<= 表示小于等于指定数值的信息作为条件
>= 表示大于等于指定数值的信息作为条件
!= / <> 表示不等于指定数值的信息作为条件

 逻辑判断符号

逻辑判断符号解释说明
and(并且)/ && 表示多个条件均都满足才能被查找出来
or(或者)/ || 表示多个条件之一满足就能被查找出来
not (取反) / ! 表示查找除过滤查找的信息以外的内容

 like、in、not in、between and、distinct、is null、is not null

# 查询国家代号是CH开头的城市信息
mysql> SELECT * FROM city WHERE countrycode LIKE 'CH%';

# 查询中国和美国的所有城市 
mysql> SELECT * FROM city WHERE countrycode in ('CHN','USA');

# 查询世界上的所有城市信息,但排除中国和美国的城市不查询
mysql> SELECT * FROM city WHERE countrycode not in ('CHN','USA');

# 查询人口数量在50w-100w之间的城市信息
mysql> SELECT * FROM city WHERE population between 500000 and 10000000;

# 查询city表中所有CountryCode为'USA'的城市,并返回去重后的CountryCode列表
mysql> select Distinct CountryCode from city where CountryCode='USA';

# 查询国家编码字段为非空和空的信息
mysql> select * from city where CountryCode not null;
mysql> select * from city where CountryCode is null;   

 聚合函数

函数信息解释说明
count() 此函数表示对数量信息进行统计
sum() 此函数表示对数值信息进行求和
avg() 此函数表示对数值信息进行求平均值
min() 此函数表示对数值信息进行取最小值
max() 此函数表示对数值信息进行取最大值
group_concat() 此函数表示输出信息无法匹配分组和聚合函数时,进行拼接整合显示
distinct 此指令表示作用是对表中的单个字段或多个字段去重操作

image

select+from+where+group by+聚合函数+having+order by+limit
# 查询统计每个国家的人口总数,只显示人口数量超过5千万的信息,并且按照国家人口总数从大到小排序,只显示前三名
mysql > select countrycode,sum(population) from world.city group by countrycode having sum(population)>50000000 order by sum(population) desc limit 3;
mysql > select countrycode,sum(population) from world.city group by countrycode having sum(population)>50000000 order by sum(population) desc limit 0,3;
mysql > select countrycode,sum(population) from world.city group by countrycode having sum(population)>50000000 order by sum(population) desc limit 3 offset 0;
​
# 查询统计每个国家的人口总数,只显示人口数量超过5千万的信息,并且按照国家人口总数从大到小排序,只显示三~五名
mysql > select countrycode,sum(population) from world.city group by countrycode having sum(population)>50000000 order by sum(population) desc limit 2,3;
mysql > select countrycode,sum(population) from world.city group by countrycode having sum(population)>50000000 order by sum(population) desc limit 3 offset 2;
-- 跳过前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;

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;

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');
student表
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;

INSERT INTO course(cno,cname,tno)
VALUES
(1001,'linux',101),
(1002,'python',102),
(1003,'mysql',103),
(1004,'go',105);
course表
CREATE TABLE sc (
    sno INT NOT NULL COMMENT '学号',
    cno INT NOT NULL COMMENT '课程编号',
    score INT NOT NULL DEFAULT 0 COMMENT '成绩'
) ENGINE=INNODB CHARSET=utf8;

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);
sc表
CREATE TABLE teacher (
    tno INT NOT NULL PRIMARY KEY COMMENT '教师编号',
    tname VARCHAR(20) NOT NULL COMMENT '教师名字'
) ENGINE=INNODB CHARSET=utf8;

INSERT INTO teacher(tno,tname)
VALUES
(101,'oldboy'),
(102,'xiaoQ'),
(103,'xiaoA'),
(104,'xiaoB');
teacher表

 案例

image

# 利用内连接显示teacher和course表中相关联的信息
mysql> select * from teacher [inner] join course on teacher.tno=course.tno;

# 利用左外连接显示teacher和course表中相关联的信息
mysql> select * from teacher left join course on teacher.tno=course.tno;

# 利用右外连接显示teacher和course表中相关联的信息
mysql> select * from teacher right join course on teacher.tno=course.tno;

# 统计zhang3,学习了几门课?
mysql> select student.sname,count(*) from student \
join sc on student.sno=sc.sno \
where student.sname='zhang3';
# 查询zhang3,学习的课程名称有哪些? 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'; # 查询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;
# 查询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;
# 每位老师所教课程的平均分,并按平均分排序? 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);
# 查询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' and sc.score<60 group by teacher.tno;
# 查询所有老师所教学生不及格的信息? 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;

 嵌套查询

select 列名 from 表名 where 列名 > (select avg(列名) from 表名);

# 取出大于Linux课程的平均分学生都有哪些;
select name from student where sc > (select avg(sc) from students);

# 取出Linux课程成绩大于70分的所有男同学信息;
select s.name,s.sc,s.gender from (select * from students where gender='M') AS s where s.sc >70;

元数据⭐⭐⭐⭐⭐

描述database的数据,属性,状态等相关信息(表示在数据库服务中有哪些数据库,库中有哪些表,表中有多少字段,字段是什么类型等等)

  show命令获取元数据

-- 查询数据库服务中的所有数据库信息(数据库名称-元数据)
    mysql> show databases;

-- 查询数据库服务中的相应数据表信息(数据表名称-元数据)
    mysql> show tables;
    mysql> show tables from mysql;

-- 查询数据库服务中的建库/建表语句信息
    mysql> show create database <库名>;
    mysql> show create table <表名>;

-- 查询数据库服务中的数据表的结构(数据表的列定义信息-元数据)
    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: 

-- 查询数据库服务中的相应数据表的索引情况(了解即可)
​    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%'; 

-- 查询数据库服务的所有二进制日志信息(binlog日志)
    mysql> show binary logs;

-- 查询数据库服务正在使用的二进制日志
    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)⭐⭐⭐⭐⭐

将查询基表元数据语句信息方法封装在一个变量或别名中,这个封装好的变量或别名就成为视图,视图信息都是存储在内存中的表

information_schema库中的内存表都是每次数据库服务启动时生成的,里面存储了查询元数据基表的视图信息

 视图的基础使用

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;
基表查询语句
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;
将复杂的查询语句定义为视图
# 调取视图信息等价于调取复杂的查询语句
mysql> select * from tv;

 视图查询⭐⭐⭐

# 切换进入information_schema数据库中查看表信息
  mysql> use information_schema;
  mysql> show tables;
  -- 此时看到的所有表信息,其实都是视图信息
​
# 查看获取视图信息创建语句
  mysql> show create view tables;  -- 查看tables这个视图表的创建过程
​
# 统计数据库资产信息(数据资产),获取每个库中表的个数和名称信息(业务相关)
  mysql> select table_schema,count(*),group_concat(table_name) \
         from information_schema.tables group by table_schema; 
  -- 获取相应数据库中表的个数,与数据库中拥有的表信息
​
# 统计数据库资产信息(数据资产),获取每个数据库数据占用磁盘空间
  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;
​
# 统计数据库资产信息(数据资产),获取具有碎片信息的表
  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;
  -- 碎片信息过多会导致索引信息失效,以及统计信息不真实的情况
​
# 统计数据库资产信息(数据资产),处理具有碎片信息的表
  -- 可以对已经是innodb存储引擎的表做操作,实现整理碎片功能
    mysql> alter table 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 data_free >0;
​
# 统计数据库资产信息(数据资产),获取数据库中非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';
  -- 模拟创建一些myisam引擎数据表
    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;
​
# 统计数据库资产信息(数据资产),修改数据库中非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';
  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';  
   ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

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

  视图表字段说明(information_schema.tables)⭐⭐⭐

字段信息解释说明
TABLE_SCHEMA 表示数据表所属库的名称信息
TABLE_NAME 表示数据库中所有数据表名称
ENGINE 表示数据库服务中的引擎信息
TABLE_ROWS 表示数据库相应数据表的行数
AVG_ROW_LENGTH 表示数据表中每行的平均长度
INDEX_LENGTH 表示数据表中索引信息的长度
DATA_FREE 表示数据库服务碎片数量信息
CREATE_TIME 表示数据表创建的时间戳信息
UPDATE_TIME 表示数据表修改的时间戳信息
TABLE_COMMENT 表示数据表对应所有注释信息

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

posted on 2025-08-09 23:40  猿小姜  阅读(26)  评论(0)    收藏  举报

levels of contents