跳到主要内容

1、Mysql

Mysql

image-20240326063147722

目录

[toc]

本站内容

  • 关系型数据库基础
  • 安装MySQL
  • 管理数据库和表
  • 用户和权限管理
  • 函数,存储过程和触发器
  • MySQL架构
  • 存储引擎(Mysql支持插件式存储引擎)
  • 服务器选项,系统和状态变量(这里容易产生混淆)
  • 优化查询和索引管理
  • 锁和事务管理
  • 日志管理(日志种类更多:事务日志、二级日志、慢查询日志、错误日志、通用日志……)
  • 备份还原(必备技能)
  • MySQL集群

1、数据库原理

数据的时代

  • 涉及的数据量大
  • 数据不随程序的结束而消失
  • 数据被多个应用程序共享
  • 大数据

数据的分类:

  • 结构化的数据:即有固定格式和有限长度的数据。例如填的表格就是结构化的数据,国籍:中华人民共和国,民族:汉,性别:男,这都叫结构化数据 (mysql适合管理)
  • 非结构化的数据:非结构化的数据越来越多,就是不定长、无固定格式的数据,例如网页,有时候非常长,有时候几句话就没了;例如语音,视频都是非结构化的数据 (redis适合管理)
  • 半结构化数据:比如:XML或者HTML的格式的数据

数据库的发展史

  • 萌芽阶段:文件系统 使用磁盘文件来存储数据
  • 初级阶段:第一代数据库 出现了网状模型、层次模型的数据库
  • 中级阶段:第二代数据库 关系型数据库和结构化查询语言
  • 高级阶段:新一代数据库 “关系-对象”型数据库

文件管理系统的缺点:

  • 编写应用程序不方便
  • 数据冗余不可避免
  • 应用程序依赖性
  • 不支持对文件的并发访问
  • 数据间联系弱
  • 难以按用户视图表示数据
  • 无安全控制功能

DBMS 数据库管理系统

数据库:database是数据的汇集,它以一定的组织形式存于存储介质上

DBMS:是管理数据库的系统软件,它实现数据库系统的各种功能。是数据库系统的核心

DBA:负责数据库的规划、设计、协调、维护和管理等工作

应用程序:指以数据库为基础的应用程序

image-20240326072516119

数据库管理系统的优点

  • 相互关联的数据的集合
  • 较少的数据冗余
  • 程序与数据相互独立
  • 保证数据的安全、可靠
  • 最大限度地保证数据的正确性
  • 数据可以并发使用并能同时保证一致性

数据库管理系统的基本功能

  • 数据定义
  • 数据处理
  • 数据安全
  • 数据备份

数据库系统的架构

  • 单机架构
  • 大型主机/终端架构
  • 主从式架构(C/S)
  • 分布式架构

各种数据库管理系统

网状数据库

image-20240326074051190

最早出现的是网状DBMS,1964年通用电气公司的Charles Bachman成功地开发出世界上第一个网状IDS,也是第一个数据库管理系统,IDS 具有数据模式和日志的特征,只能在GE主机运行。

层次数据库

image-20240326074228078

以树型结构表示实体及其之间联系,关系只支持一对多 代表数据库:IBM IMS

数据会产生冗余情况。

RDBMS 关系型数据库

关系统型数据库相关概念
  • 关系 :关系就是二维表,其中:表中的行、列次序并不重要
  • 行row:表中的每一行,又称为一条记录record
  • 列column:表中的每一列,称为属性,字段,域field
  • 主键PK ==Primary key==:用于惟一确定一个记录的字段,一张表只有一个主键主键避免一张表里出现了完全一样的记录,要在合适的字段设置主键!
  • 域domain:属性的取值范围,如,性别只能是‘男’和‘女’两个值,人类的年龄只能0-150

image-20240327064335331

常用关系数据库
  • MySQL: MySQL, MariaDB, Percona Server
  • PostgreSQL: 简称为pgsql,EnterpriseDB
  • Oracle
  • MSSQL
  • DB2 (IBM)

目前主流的还是这种关系型数据库。

redis,mongdb---no sql(非关系型数据库)

数据库排名

https://db-engines.com/en/ranking

image-20240327062512399

office,access数据库,单机版。

  • oracle源代码,上亿行了

linux内核源代码,2千万行

据说oracle源代码,上亿行了

关系型数据库理论

实体-联系模型E-R

  • 实体Entity:客观存在并可以相互区分的客观事物或抽象事件称为实体,在E-R图中用矩形框表示实体,把实体名写在框内

  • 属性:实体所具有的特征或性质

  • 联系:联系是数据之间的关联集合,是客观存在的应用语义链

    • 实体内部的联系:指组成实体的各属性之间的联系。如职工实体中,职工号和部门经理号之间有一种关联关系

    • 实体之间的联系:指不同实体之间联系。例:学生选课实体和学生基本信息实体之间

    • 实体之间的联系用菱形框表示

联系类型

  • 一对一联系(1:1)
  • 一对多联系(1:n):外键
  • 多对多联系(m:n):增加第三张表😜

一对多:

==foreign key外键==

image-20240327065731539

多对多:

节约表空间; 数据更加复杂,性能受影响;

image-20240327071519004

数据的操作

  • 数据提取:在数据集合中提取感兴趣的内容。SELECT
  • 数据更新:变更数据库中的数据。INSERT、DELETE、UPDATE

数据库规划流程

  1. 收集数据,得到字段 收集必要且完整的数据项 转换成数据表的字段
  2. 把字段分类,归入表,建立表的关联 关联:表和表间的关系 分割数据表并建立关联的优点 节省空间 减少输入错误 方便数据修改
  3. 规范化数据库

数据库的正规化分析

面试也会被经常问到,一个比较经典的问题。

范式(设计数据库的规范)

数据库规范化,又称数据库或资料库的正规化、标准化,是数据库设计中的一系列原理和技术,以减少数据库中数据冗余,增进数据的一致性。关系模型的发明者埃德加·科德最早提出这一概念,并于1970年代初定义了第一范式、第二范式和第三范式的概念

设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,不同的规范要求被称为不同范式,各种范式呈递次规范,越高的范式数据库冗余越小

目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴德斯科范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般数据库只需满足第三范式(3NF)即可

通常情况:达到第一、二、三范式在生产里就够用了,第4、5范式基本用不到。(或者有时,我们甚至会考虑性能,会故意违反第2/3范式,直接使用第一范式。)

范式级别越高:数据库越节约空间,但复杂性越高,性能越低。

学习范式,并不是为了遵守范式,而是为了违反范式哈哈。

第一范式:1NF

无重复的列,每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性,确保每一列的原子性除去同类型的字段,就是无重复的列。

说明:第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库

举例:

不属于第一范式:

(除去同类型的字段)

image-20240327074728519

(同一列中不能有多个值)

image-20240327074744641

属于第一范式:

image-20240327074801096

第二范式:2NF

属性完全依赖于主键,第二范式必须先满足第一范式,要求表中的每个行必须可以被唯一地区分,通常为表加上每行的唯一标识PK,非PK的字段需要与整个PK有直接相关性

举例:

不符合 第二范式:2NF

(非PK的字段需要与整个PK有直接相关性)

image-20240327075939147

改进后:符合第2范式(拆分成2张表后,节约了空间,但同时也带来了复杂性及性能问题)

image-20240328104035982

第三范式:3NF

属性不依赖于其它非主属性,满足第三范式必须先满足第二范式。第三范式要求一个数据表中不包含已在其它表中已包含的非主关键字信息,非PK的字段间不能有从属关系

举例:

次场景不符合第三范式:(因为非PK的字段间有了从属关系)(会带来一些数据重复录入,数据冗余问题)

image-20240328104728902

解决方法:

还是一样,拆分成2张表就好。(带来的后果还是和上面第二范式一样的效果)

image-20240328105056107

SQL 结构化查询语言简介

SQL:结构化查询语言,Structure Query Language

SQL解释器;

数据存储协议:应用层协议,C/S S:server, 监听于套接字,接收并处理客户端的应用请求 C:Client

客户端程序接口 CLI GUI

应用编程接口 ODBC:Open Database Connectivity JDBC:Java Data Base Connectivity

SQL 基本概念

  • 约束:constraint,表中的数据要遵守的限制
  • 主键:一个或多个字段的组合,填入的数据必须能在本表中唯一标识本行;必须提供数据,即NOT NULL,一个表只能有一个
  • 惟一键:一个或多个字段的组合,填入的数据必须能在本表中唯一标识本行;允许为NULL,一个表可以存在多个
  • 外键:一个表中的某字段可填入的数据取决于另一个表的主键或唯一键已有的数据
  • 检查:字段值在一定范围内
  • 索引:将表中的一个或多个字段中的数据复制一份另存,并且按特定次序排序存储

关系运算

  • 选择:挑选出符合条件的行
  • 投影:挑选出需要的字段 (列)
  • 连接:表间字段的关联

数据抽象

  • 物理层:数据存储格式,即RDBMS在磁盘上如何组织文件
  • 逻辑层:DBA角度,描述存储什么数据,以及数据间存在什么样的关系
  • 视图层:用户角度,描述DB中的部分数据

关系模型的分类

  • 关系模型
  • 基于对象的关系模型
  • 半结构化的关系模型:XML数据

2、MySQL安装和基本使用

MySQL 介绍

MySQL 历史

image-20240328114253070

1979年:TcX公司 Monty Widenius,Unireg 1996年:发布MySQL1.0,Solaris版本,Linux版本 1999年:MySQL AB公司,瑞典 2003年:MySQL 5.0版本,提供视图、存储过程等功能 2008年:Sun 10亿美元收购MySQL 2009年:Oracle 75亿美元收购sun 2009年:Monty成立MariaDB

MySQL系列

MySQL 的三大主要分支
  • mysql (用的最多)
  • mariadb
  • percona Server
官方网址

https://www.mysql.com/

image-20240328131923726

http://mariadb.org/

image-20240328131600396

https://www.percona.com

image-20240328131649563

官方文档

https://dev.mysql.com/doc/

image-20240328132007825

https://mariadb.com/kb/en/

image-20240328132032607

https://www.percona.com/software/mysql-database/percona-server

image-20240328132052217

==版本演变==

MySQL:5.1 --> 5.5 --> 5.6 --> 5.7 -->8.0

MariaDB:5.5 -->10.0--> 10.1 --> 10.2 --> 10.3 --> 10.4 --> 10.5

[!NOTE]

特别注意:各自版本ios默认mysql版本

CentOS 8:安装光盘直接提供
mysql-server:8.0
mariadb-server : 10.3.17

CentOS 7:安装光盘直接提供
mariadb-server:5.5 服务器包
mariadb 客户端工具包

CentOS 6
mysql-server:5.1 服务器包
mysql 客户端工具包

MYSQL的特性

  • ==插件式存储引擎==:也称为“表类型”,存储管理器有多种实现版本,功能和特性可能均略有差别;用户可根据需要灵活选择,Mysql5.5.5开始,innoDB引擎是MYSQL默认引擎

    • MyISAM ==> Aria

    • InnoDB ==> XtraDB

    这里会有一个经典的面试题:InnoDB和MyISAM存储引擎有什么区别。

  • 单进程,多线程

  • 诸多扩展和新特性

  • 提供了较多测试组件

  • 开源

MySQL 安装方式介绍和快速安装

安装方式介绍

  • 源代码:编译安装 (生产环境,可以定制)
  • 二进制格式的程序包:展开至特定路径,并经过简单配置后即可使用 (绿色安装)
  • 程序包管理器管理的程序包 (测试环境)

RPM包安装MySQL

CentOS 安装光盘 项目官方:https://downloads.mariadb.org/mariadb/repositories/ 国内镜像:https://mirrors.tuna.tsinghua.edu.cn/mariadb/yum/ https://mirrors.tuna.tsinghua.edu.cn/mysql/yum/

初始化脚本提高安全性

运行脚本:mysql_secure_installation

设置数据库管理员root口令
禁止root远程登录
删除anonymous用户帐号
删除test数据库
  • mariadb 10.4.33(centos7安装的)
Enter current password for root (enter for none): #默认没密码,这里直接回车


You already have your root account protected, so you can safely answer 'n'.
Switch to unix_socket authentication [Y/n] #输入n(远程可以登录)

#mysql.sock 使用unix socket登录(只能在本地登录,不能远程登录);
/var/lib/mysql/mysql.sock文件

Change the root password? [Y/n] #输入y
New password: #输入密码:xyy520
Re-enter new password:

Remove anonymous users? [Y/n] #输入y

Disallow root login remotely? [Y/n] #输入y,禁用root远程登录

Remove test database and access to it? [Y/n] #输入y

Reload privilege tables now? [Y/n] #输入y(是否加载权限)

测试:

(直接空口令也是可以登录的……)

[root@linux-test ~]#mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 25
Server version: 10.4.33-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> status
--------------
mysql Ver 15.1 Distrib 10.4.33-MariaDB, for Linux (x86_64) using readline 5.1

Connection id: 25
Current database:
Current user: root@localhost #以root身份登录的:
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server: MariaDB
Server version: 10.4.33-MariaDB MariaDB Server
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 1 day 3 hours 44 min 16 sec

Threads: 6 Questions: 180 Slow queries: 0 Opens: 37 Flush tables: 1 Open tables: 30 Queries per second avg: 0.001
--------------

MariaDB [(none)]>




#可以看到root是有口令的:(匿名账号也删除了)
MariaDB [mysql]> select user,host,password from user;
+-------------+-----------+-------------------------------------------+
| User | Host | Password |
+-------------+-----------+-------------------------------------------+
| mariadb.sys | localhost | |
| root | localhost | *ABE374A5F247C93961AD4726B39A5A84FA3BC3B1 |
| mysql | localhost | invalid |
+-------------+-----------+-------------------------------------------+
3 rows in set (0.001 sec)

MariaDB [mysql]>



#重启服务后,root还是可以直接免密登录数据库的:
[root@linux-test ~]#systemctl restart mariadb
[root@linux-test ~]#mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 10.4.33-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

因此,在本地,使用root用户,空口令是可以直接登录数据库的。(正常登录的话,root登录也是需要输入口令的!!!,其他版本是必须要输入口令才能登的)

[root@linux-test ~]#mysql -uroot -pxyy520   ##这里明确地输密码也是可以的。
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 9
Server version: 10.4.33-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>


[root@linux-test ~]#mysql -uroot
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 10
Server version: 10.4.33-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>


[root@linux-test ~]#mysql -uroot -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 11
Server version: 10.4.33-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

退出shell后重新登陆,还是一样的效果。

当然,仅限于root用户而言:(普通用户使用root去登录,不输入密码很定是有问题的)

[root@linux-test ~]#su - xyy
Last login: Fri Mar 29 07:43:03 CST 2024 on pts/1
[xyy@linux-test ~]$mysql -uroot -p
Enter password:
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
[xyy@linux-test ~]$


[xyy@linux-test ~]$mysql -uroot -p
Enter password: ##输入正确密码后。
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 14
Server version: 10.4.33-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

因此:

root是操作系统管理员,当然对mysql具有绝对的控制权哦。

另外,需要注意:

目前配置的策略是,只允许在本机登录数据库才行,远程是不允许被登录的。(只能单机使用,不能跨网络使用)

MariaDB [mysql]> select user,host,password from user;
+-------------+-----------+-------------------------------------------+
| User | Host | Password |
+-------------+-----------+-------------------------------------------+
| mariadb.sys | localhost | |
| root | localhost | *ABE374A5F247C93961AD4726B39A5A84FA3BC3B1 |
| mysql | localhost | invalid |
+-------------+-----------+-------------------------------------------+
3 rows in set (0.001 sec)

MariaDB [mysql]>

如果想要远程用户可以登录数据库,那么就要创建基于远程用户的登录:

localhost和127.0.0.1是不同的。

localhost代表的是走套接字方式(Localhost via UNIX socket)/var/lib/mysql/mysql.sock文件 (不存在封装&解封装过程)

127.0.0.1走的是本机127.0.0.1:3306端口(涉及TCP协议,封装&解封装流程)

它是2个渠道。

客户端和服务端进行连接,相当于是2个进程,一个是客户端(mysql),一个是服务端(mysqld),这两个进程之间通信,可以走unix套接字,也可以走3306端口。

如果只有mysql.socket套接字,那就只能支持本地连接,无法支持远程数据库连接了。

image-20240330101634146

测试远程登录数据库:

[root@linux-test-2 ~]#mysql -uroot -pxyy520 -h172.29.9.31
ERROR 1130 (HY000): Host '172.29.9.32' is not allowed to connect to this MariaDB server
[root@linux-test-2 ~]#

[root@linux-test ~]#mysql
……
MariaDB [mysql]> select user,host,password from user;
+-------------+-----------+-------------------------------------------+
| User | Host | Password |
+-------------+-----------+-------------------------------------------+
| mariadb.sys | localhost | |
| root | localhost | *ABE374A5F247C93961AD4726B39A5A84FA3BC3B1 |
| mysql | localhost | invalid |
+-------------+-----------+-------------------------------------------+
3 rows in set (0.001 sec)

符合预期。

通过127.0.0.1和unix sokcet登录数据库:

[root@linux-test ~]#mysql
……
MariaDB [mysql]> select user,host,password from user;
+-------------+-----------+-------------------------------------------+
| User | Host | Password |
+-------------+-----------+-------------------------------------------+
| mariadb.sys | localhost | |
| root | localhost | *ABE374A5F247C93961AD4726B39A5A84FA3BC3B1 |
| mysql | localhost | invalid |
+-------------+-----------+-------------------------------------------+
3 rows in set (0.001 sec)


[root@linux-test ~]#mysql -uroot -pxyy520 -h127.0.0.1
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 10
Server version: 10.4.33-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> status
--------------
mysql Ver 15.1 Distrib 10.4.33-MariaDB, for Linux (x86_64) using readline 5.1

Connection id: 10
Current database:
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server: MariaDB
Server version: 10.4.33-MariaDB MariaDB Server
Protocol version: 10
Connection: 127.0.0.1 via TCP/IP
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
TCP port: 3306
Uptime: 3 min 49 sec

Threads: 6 Questions: 42 Slow queries: 0 Opens: 37 Flush tables: 1 Open tables: 30 Queries per second avg: 0.183
--------------

MariaDB [(none)]>



[root@linux-test ~]#mysql -uroot -pxyy520 -hlocalhost
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 11
Server version: 10.4.33-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> \s
--------------
mysql Ver 15.1 Distrib 10.4.33-MariaDB, for Linux (x86_64) using readline 5.1

Connection id: 11
Current database:
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server: MariaDB
Server version: 10.4.33-MariaDB MariaDB Server
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 4 min 42 sec

Threads: 6 Questions: 46 Slow queries: 0 Opens: 37 Flush tables: 1 Open tables: 30 Queries per second avg: 0.163
--------------

MariaDB [(none)]>

MySQL 组成

客户端程序

  • mysql: 交互式的CLI工具
  • mysqldump:备份工具,基于mysql协议向mysqld发起查询请求,并将查得的所有数据转换成insert等写操作语句保存文本文件中
  • mysqladmin:基于mysql协议管理mysqld
  • mysqlimport:数据导入工具
  • MyISAM存储引擎的管理工具:
  • myisamchk:检查MyISAM库
  • myisampack:打包MyISAM表,只读

服务器端程序

  • mysqld_safe
  • mysqld
  • mysqld_multi 多实例 ,示例:mysqld_multi --example

用户账号

mysql用户账号由两部分组成'USERNAME'@'HOST‘ 说明: HOST限制此用户可通过哪些远程主机连接mysql服务器 支持使用通配符:

 % 匹配任意长度的任意字符
172.16.0.0/255.255.0.0 或 172.16.%.%
_ 匹配任意单个字符

mysql 客户端命令

mysql 运行命令类型
  • 客户端命令:本地执行,每个命令都完整形式和简写格式
mysql> \h, help
mysql> \u,use
mysql> \s,status
mysql> \!,system
MariaDB [mysql]> help

General information about MariaDB can be found at
http://mariadb.org

List of all client commands:
Note that all text commands must be first on line and end with ';'
? (\?) Synonym for `help'.
clear (\c) Clear the current input statement.
connect (\r) Reconnect to the server. Optional arguments are db and host.
delimiter (\d) Set statement delimiter.
edit (\e) Edit command with $EDITOR.
ego (\G) Send command to MariaDB server, display result vertically.
exit (\q) Exit mysql. Same as quit. ##常用
go (\g) Send command to MariaDB server.
help (\h) Display this help. ##常用
nopager (\n) Disable pager, print to stdout.
notee (\t) Don't write into outfile.
pager (\P) Set PAGER [to_pager]. Print the query results via PAGER.
print (\p) Print current command.
prompt (\R) Change your mysql prompt.
quit (\q) Quit mysql.
rehash (\#) Rebuild completion hash.
source (\.) Execute an SQL script file. Takes a file name as an argument.
status (\s) Get status information from the server. ##常用
system (\!) Execute a system shell command.
tee (\T) Set outfile [to_outfile]. Append everything into given outfile.
use (\u) Use another database. Takes database name as argument.
charset (\C) Switch to another charset. Might be needed for processing binlog with multi-byte charsets.
warnings (\W) Show warnings after every statement.
nowarning (\w) Don't show warnings after every statement.

For server side help, type 'help contents'

MariaDB [mysql]>

举例:(和awk里的system()功能类似)

system    (\!) Execute a system shell command.

MariaDB [(none)]> system ls
MariaDB [(none)]> system date
Sat Mar 30 12:17:32 CST 2024
MariaDB [(none)]> system pwd
/root
MariaDB [(none)]>

举例:

prompt    (\R) Change your mysql prompt. #修改提示符

MariaDB [(none)]> (修改这里的提示符的,类似与PS1
  • 服务端命令:通过mysql协议发往服务器执行并取回结果,命令末尾都必须使用命令结束符号,默认为分号
#示例:
mysql>SELECT VERSION();
MariaDB [(none)]> show databases
-> ; ##必须要加;号才行,不然不给结束;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
+--------------------+
3 rows in set (0.001 sec)

MariaDB [(none)]>
mysql 使用模式

交互模式:

脚本模式:

 mysql –uUSERNAME -pPASSWORD < /path/somefile.sql
cat /path/somefile.sql | mysql –uUSERNAME -pPASSWORD

mysql>source   /path/from/somefile.sql

举例:

[root@linux-test ~]#mysql -uroot -pxyy520 < /tmp/test.sql 
User Host
mariadb.sys localhost
mysql localhost
root localhost
[root@linux-test ~]#


[root@linux-test ~]#cat /tmp/test.sql |mysql -uroot -pxyy520
User Host
mariadb.sys localhost
mysql localhost
root localhost
[root@linux-test ~]#
mysql命令使用格式
mysql [OPTIONS] [database]

mysql客户端常用选项:

-A, --no-auto-rehash 禁止补全
-u, --user= 用户名,默认为root
-h, --host= 服务器主机,默认为localhost
-p, --passowrd= 用户密码,建议使用-p,默认为空密码

-P, --port= 服务器端口
-S, --socket= 指定连接socket文件路径

-D, --database= 指定默认数据库
-C, --compress 启用压缩

-e   “SQL“ 执行SQL命令

-V, --version 显示版本
-v --verbose 显示详细信息
--print-defaults 获取程序默认使用的配置

登录系统:

#默认空密码登录
mysql –uroot –p

运行mysql命令:

mysql>use mysql
mysql>select user(); #查看当前用户
mysql>SELECT User,Host,Password FROM user;

范例:配置客户端mysql的自动登录

vim/etc/my.cnf.d/client.conf
[client]
user=wang
password=centos
服务器端配置

服务器端(mysqld):工作特性有多种配置方式

1、命令行选项:

2、配置文件:类ini格式,集中式的配置,能够为mysql的各应用程序提供配置信息

服务器端配置文件:

/etc/my.cnf #Global选项(主流)

/etc/mysql/my.cnf #Global选项

~/.my.cnf #User-specific 选项

配置文件格式:

[mysqld]
[mysqld_safe]
[mysqld_multi]
[mysql]
[mysqldump]
[server]
[client]

格式:parameter = value

说明:_和- 相同 (不区分)

1,ON,TRUE意义相同, 0,OFF,FALSE意义相同

mariadb 10.4.33

[root@linux-test ~]#ls /etc/my.cnf.d/server.cnf /etc/my.cnf.d/server.cnf

mariadb 10.3.17

image-20240331094942456

socket地址

服务器监听的两种socket地址:

  • ip socket: 监听在tcp的3306端口,支持远程通信 ,侦听3306/tcp端口可以在绑定有一个或全部接口IP上
  • unix sock: 监听在sock文件上,仅支持本机通信, 如:/var/lib/mysql/mysql.sock)

说明:host为localhost 时自动使用unix sock

关闭mysqld网络连接

只侦听本地客户端, 所有客户端和服务器的交互都通过一个socket文件实现,socket的配置存放在/var/lib/mysql/mysql.sock) 可在/etc/my.cnf修改

范例:

#vim /etc/my.cnf 
或者
vim /etc/my.cnf.d/server.cnf
[mysqld]
skip-networking=1

记得配置后,要重启maridb服务的:

systemctl  restart mariadb

3、SQL语言

关系型数据库的常见组件

  • 数据库:database
  • 表:table,行:row 列:column
  • 索引:index
  • 视图:view
  • 用户:user
  • 权限:privilege
  • 存储过程:procedure
  • 存储函数:function
  • 触发器:trigger
  • 事件调度器:event scheduler,任务计划

SQL语言的兴起与语法标准

20世纪70年代,IBM开发出SQL,用于DB2

1981年,IBM推出SQL/DS数据库

业内标准微软和Sybase的T-SQL,Oracle的PL/SQL

SQL作为关系型数据库所使用的标准语言,最初是基于IBM的实现在1986年被批准的。1987年,国际标准化组织(ISO) 把ANSI(美国国家标准化组织) SQL作为国际标准

SQL:ANSI SQL,SQL-1986, SQL-1989, SQL-1992, SQL-1999, SQL-2003,SQL-2008, SQL-2011

SQL语言规范

在数据库系统中,SQL语句不区分大小写,建议用大写

SQL语句可单行或多行书写,以“;”结尾

关键词不能跨多行或简写

用空格和缩进来提高语句的可读性

子句通常位于独立行,便于编辑,提高可读性

注释:

SQL标准:
-- 注释内容 单行注释,注意有空格
/*注释内容*/ 多行注释

MySQL注释:
# 注释内容

数据库对象和命名

数据库的组件(对象)

数据库、表、索引、视图、用户、存储过程、函数、触发器、事件调度器等

命名规则:

必须以字母开头,可包括数字和三个特殊字符(# _ $)

不要使用MySQL的保留字

同一database(Schema)下的对象不能同名

[!NOTE]

在mysql里,Schema和database在数据库下是同义词。但在别的数据库里,不是同义词。

SQL语句分类

  • DDL: Data Defination Language 数据定义语言

​ CREATE,DROP,ALTER(改表的结构)

  • DML: Data Manipulation Language 数据操纵语言

​ INSERT,DELETE,UPDATE

  • DQL:Data Query Language 数据查询语言

​ SELECT

  • DCL:Data Control Language 数据控制语言

​ GRANT(授权),REVOKE(取消),COMMIT,ROLLBACK(撤销)

软件开发:CRUD (R:recieve)

[!NOTE]

面试会经常问到这块儿。

SQL语句构成

关健字Keyword组成子句clause,多条clause组成语句

示例:

SELECT *                 #SELECT子句
FROM products             #FROM子句
WHERE price>400           #WHERE子句

说明:一组SQL语句,由三个子句构成,SELECT,FROM和WHERE是关键字

数据库操作

管理数据库

创建数据库

CREATE DATABASE|SCHEMA [IF NOT EXISTS] 'DB_NAME'
CHARACTER SET 'character set name'
COLLATE 'collate name';


CREATE DATABASE|SCHEMA [IF NOT EXISTS] 'DB_NAME';


CREATE DATABASE|SCHEMA 'DB_NAME';
🍊 范例:创建数据库
mysql> create database db1;
Query OK, 1 row affected (0.00 sec)

mysql> show create database db1;
+----------+-----------------------------------------------------------------+
| Database | Create Database |
+----------+-----------------------------------------------------------------+
| db1 | CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+-----------------------------------------------------------------+
1 row in set (0.00 sec)

mysql>
[root@linux-test ~]#cat /data/mysql/db1/db.opt
default-character-set=utf8mb4
default-collation=utf8mb4_general_ci
[root@linux-test ~]#



mysql> create database db1;
ERROR 1007 (HY000): Can't create database 'db1'; database exists
mysql> create database IF NOT EXISTS db1;
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+----------------------------------------------+
| Level | Code | Message |
+-------+------+----------------------------------------------+
| Note | 1007 | Can't create database 'db1'; database exists |
+-------+------+----------------------------------------------+
1 row in set (0.00 sec)

mysql>
🍊 范例:指定字符集创建新数据库
mysql> create database IF NOT EXISTS db2 CHARACTER SET 'utf8';
Query OK, 1 row affected (0.01 sec)

mysql> show create database db2;
+----------+--------------------------------------------------------------+
| Database | Create Database |
+----------+--------------------------------------------------------------+
| db2 | CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+--------------------------------------------------------------+
1 row in set (0.00 sec)

mysql>


default-character-set=utf8
default-collation=utf8_general_ci
[root@linux-test ~]#

修改数据库

ALTER DATABASE DB_NAME character set utf8;

[!NOTE]

修改字符集后,此刻数据库里会存在2种类型字符集,刚修改的只会对新数据产生影响,老的数据会保持旧字符集不变,可能会出现乱码问题,因此最好在创建数据库时就规划好字符集。

🍊 范例:修改数据库的字符集
mysql> show create database db1;
+----------+-----------------------------------------------------------------+
| Database | Create Database |
+----------+-----------------------------------------------------------------+
| db1 | CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+-----------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> alter database db1 character set utf8;
Query OK, 1 row affected (0.00 sec)

mysql> show create database db1;
+----------+--------------------------------------------------------------+
| Database | Create Database |
+----------+--------------------------------------------------------------+
| db1 | CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+--------------------------------------------------------------+
1 row in set (0.00 sec)

mysql>

[root@linux-test ~]#cat /data/mysql/db1/db.opt
default-character-set=utf8
default-collation=utf8_general_ci
[root@linux-test ~]#

删除数据库

DROP DATABASE|SCHEMA [IF EXISTS] 'DB_NAME';

🍊 范例:删除数据库

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db2 |
| mysql |
| performance_schema |
+--------------------+
5 rows in set (0.00 sec)

mysql> drop database db1;
Query OK, 0 rows affected (0.02 sec)

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db2 |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)

mysql>

[root@linux-test ~]#ls /data/mysql/db1
ls: cannot access /data/mysql/db1: No such file or directory
[root@linux-test ~]#

🍊 范例:如果在数据库目录里创建一个文件,删除数据库后,还能删除这个数据库目录吗

[root@linux-test ~]#ll /data/mysql/db2
total 4
-rw-rw---- 1 mysql mysql 61 Apr 23 07:04 db.opt
[root@linux-test ~]#touch /data/mysql/db2/xxx.txt
[root@linux-test ~]#ll /data/mysql/db2
total 4
-rw-rw---- 1 mysql mysql 61 Apr 23 07:04 db.opt
-rw-r--r-- 1 root root 0 Apr 23 07:25 xxx.txt
[root@linux-test ~]#


mysql> drop database db2;
ERROR 1010 (HY000): Error dropping database (can't rmdir './db2/', errno: 17)
mysql>

#修改权限
[root@linux-test ~]#ll /data/mysql/db2
total 0
-rw-r--r-- 1 root root 0 Apr 23 07:25 xxx.txt
[root@linux-test ~]#chown -R mysql.mysql /data/mysql/
[root@linux-test ~]#ll /data/mysql/db2
total 0
-rw-r--r-- 1 mysql mysql 0 Apr 23 07:25 xxx.txt
[root@linux-test ~]#


#再次删除还是报错……
mysql> drop database db2;
ERROR 1010 (HY000): Error dropping database (can't rmdir './db2/', errno: 17)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db2 |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)

mysql>

🍊 范例:删除mysql数据库(自杀)

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db2 |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)

mysql> drop database mysql;
Query OK, 28 rows affected, 2 warnings (0.03 sec)

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db2 |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)

mysql>


##删除mysql数据库后,停止mysql服务再次启动后,会报错的,完了,mysql废了哈哈😂
[root@linux-test ~]#systemctl status mysql
● mysqld.service - LSB: start and stop MySQL
Loaded: loaded (/etc/rc.d/init.d/mysqld; bad; vendor preset: disabled)
Active: active (running) since Tue 2024-04-23 06:40:40 CST; 47min ago
Docs: man:systemd-sysv-generator(8)
Process: 6518 ExecStart=/etc/rc.d/init.d/mysqld start (code=exited, status=0/SUCCESS)
CGroup: /system.slice/mysqld.service
├─6536 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir=/data/mysql --pid-file=/data/mysql/linux...
└─6788 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/data/mysql --plugin-dir=/...

Apr 23 06:40:40 linux-test systemd[1]: Starting LSB: start and stop MySQL...
Apr 23 06:40:40 linux-test mysqld[6518]: Starting MySQL SUCCESS!
Apr 23 06:40:40 linux-test systemd[1]: Started LSB: start and stop MySQL.
[root@linux-test ~]#systemctl stop mysql
[root@linux-test ~]#systemctl start mysql
Job for mysqld.service failed because the control process exited with error code. See "systemctl status mysqld.service" and "journalctl -xe" for details.
[root@linux-test ~]#
[root@linux-test ~]#netstat -ntlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 6514/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 6877/master
tcp6 0 0 :::22 :::* LISTEN 6514/sshd
tcp6 0 0 ::1:25 :::* LISTEN 6877/master
[root@linux-test ~]#

查看数据库列表

SHOW DATABASES;

🍊 范例:查看数据库列表

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db2 |
| mysql |
| performance_schema |
+--------------------+
5 rows in set (0.00 sec)

mysql>

数据类型

数据类型

数据长什么样

数据需要多少空间来存放

数据类型

系统内置数据类型

用户定义数据类型

MySQL支持多种内置数据类型

数值类型

日期/时间类型

字符串(字符)类型

数据类型参考链接

https://dev.mysql.com/doc/refman/8.0/en/data-types.html

image-20240425054201892

tinyint:2^8-1=255 -127到+128 符号位
unsigned 无符号位;
截断;

选择正确的数据类型对于获得高性能至关重要,三大原则:

  1. 更小的通常更好,尽量使用可正确存储数据的最小数据类型
  2. 简单就好,简单数据类型的操作通常需要更少的CPU周期
  3. 尽量避免NULL,包含为NULL的列,对MySQL更难优化

整数型

tinyint(m) 1个字节 范围(-128~127)

smallint(m) 2个字节 范围(-32768~32767)

mediumint(m) 3个字节 范围(-8388608~8388607)

int(m) 4个字节 范围(-2147483648~2147483647)

bigint(m) 8个字节 范围(+-9.22*10的18次方)

上述数据类型,如果加修饰符unsigned后,则最大值翻倍

如:tinyint unsigned的取值范围为(0~255)

int(m)里的m是表示SELECT查询结果集中的显示宽度,并不影响实际的取值范围,规定了MySQL的一些交互工具(例如MySQL命令行客户端)用来显示字符的个数。对于存储和计算来说,Int(1)和Int(20)是相同的

BOOL,BOOLEAN:布尔型,是TINYINT(1)的同义词。zero值被视为假,非zero值视为真。

浮点型(float和double),近似值

float(m,d) 单精度浮点型 8位精度(4字节) m总个数,d小数位

double(m,d) 双精度浮点型16位精度(8字节) m总个数,d小数位

设一个字段定义为float(6,3),如果插入一个数123.45678,实际数据库里存的是123.457,但总个数还以实际为准,即6位

定点数

在数据库中存放的是精确值,存为十进制

decimal(m,d) 参数m<65 是总个数,d<30且 d<m 是小数位

MySQL5.0和更高版本将数字打包保存到一个二进制字符串中(每4个字节存9个数字)。

例如:

decimal(18,9)小数点两边将各存储9个数字,一共使用9个字节:其中,小数点前的9个数字用4个字节,小数点后的9个数字用4个字节,小数点本身占1个字节

浮点类型在存储同样范围的值时,通常比decimal使用更少的空间。float使用4个字节存储。double占用8个字节

因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时才使用decimal,例如存储财务数据。但在数据量比较大的时候,可以考虑使用bigint代替decimal。

字符串(char,varchar,text)

char(n) 固定长度,最多255个字符

varchar(n) 可变长度,最多65535个字符

tinytext 可变长度,最多255个字符

text 可变长度,最多65535个字符

mediumtext 可变长度,最多2的24次方-1个字符

longtext 可变长度,最多2的32次方-1个字符

BINARY(M) 固定长度,可存二进制或字符,长度为0-M字节

VARBINARY(M) 可变长度,可存二进制或字符,允许长度为0-M字节

内建类型:ENUM枚举, SET集合

char和varchar

参考:https://dev.mysql.com/doc/refman/8.0/en/char.html

image-20240425060302661

1.char(n) 若存入字符数小于n,则以空格补于其后,查询之时再将空格去掉,所以char类型存储的字符串末尾不能有空格,varchar不限于此

2.char(n) 固定长度,char(4)不管是存入几个字符,都将占用4个字节,varchar是存入的实际字符数+1个字节(n< n>255),所以varchar(4),存入3个字符将占用4个字节

3.char类型的字符串检索速度要比varchar类型的快

varchar和text: 1.varchar可指定n,text不能指定,内部存储varchar是存入的实际字符数+1个字节(n< n>255),text是实际字符数+2个字节。 2.text类型不能有默认值 3.varchar可直接创建索引,text创建索引要指定前多少个字符。varchar查询速度快于text数据类型。

二进制数据BLOB

BLOB和text存储方式不同,TEXT以文本方式存储,英文存储区分大小写,而Blob以二进制方式存储,不分大小写

BLOB存储的数据只能整体读出

TEXT可以指定字符集,BLOB不用指定字符集

日期时间类型

date 日期 '2008-12-2'

time 时间 '12:25:36'

datetime 日期时间 '2008-12-2 22:06:44'

timestamp 自动存储记录修改时间

YEAR(2), YEAR(4):年份

timestamp字段里的时间数据会随其他字段修改的时候自动刷新,这个数据类型的字段可以存放这条记录最后被修改的时间

修饰符

适用所有类型的修饰符:

NULL 数据列可包含NULL值,默认值

NOT NULL 数据列不允许包含NULL值,为必填选项

DEFAULT 默认值

PRIMARY KEY 主键,所有记录中此字段的值不能重复,且不能为NULL

UNIQUE KEY 唯一键,所有记录中此字段的值不能重复,但可以为NULL

CHARACTER SET name 指定一个字符集

适用数值型的修饰符:

AUTO_INCREMENT 自动递增,适用于整数类型

UNSIGNED 无符号

DDL语句

表:二维关系

设计表:遵循规范

定义:字段,索引

  • 字段:字段名,字段数据类型,修饰符
  • 约束,索引:应该创建在经常用作查询条件的字段上

创建表

创建表:

CREATE TABLE

获取帮助:

HELP CREATE TABLE
CREATE TABLE [IF NOT EXISTS] ‘tbl_name’ (col1 type1 修饰符, col2 type2 修饰符, 
...)
#字段信息
col type1
PRIMARY KEY(col1,...)
INDEX(col1, ...)
UNIQUE KEY(col1, ...)
#表选项:
ENGINE [=] engine_name
ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}

注意:

  • Storage Engine是指表类型,也即在表创建时指明其使用的存储引擎
  • 同一库中不同表可以使用不同的存储引擎
  • 同一个库中表建议要使用同一种存储引擎类型
方式1:直接创建(常用)

范例:表的创建和修改

CREATE TABLE student (
id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
age tinyint UNSIGNED,
gender ENUM('M','F') default 'M'
)ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

范例:

student | CREATE TABLE `student` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) CHARACTER SET utf8 NOT NULL,
`age` tinyint(3) unsigned DEFAULT NULL,
`gender` enum('M','F') CHARACTER SET utf8 DEFAULT 'M',
PRIMARY KEY (`id`)
) ;

测试过程:

##创建表
mysql> CREATE TABLE student (
-> id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
-> name VARCHAR(20) NOT NULL,
-> age tinyint UNSIGNED,
-> gender ENUM('M','F') default 'M'
-> )ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.00 sec)
#id字段以10初始值

##查看表结构
mysql> desc student;
+--------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+---------------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)

mysql>
#说明:enum 是枚举类型。 括号里的数字不是字节大小,而是代表的对其宽度;

##查看表内容
mysql> select * from student;
Empty set (0.00 sec)


##修改表
mysql> insert student (name,age)values('xiaoming',20);
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 10 | xiaoming | 20 | M |
+----+----------+------+--------+
1 row in set (0.00 sec)
mysql> insert student (name,age,gender)values('xiaohong',18,'f'); ##注意:枚举类型,这里小写字母f或者大写字母F都是可以的;
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
+----+----------+------+--------+
2 rows in set (0.00 sec)

mysql>

🍊 范例:创建复合主键

CREATE TABLE employee (id int UNSIGNED NOT NULL ,name VARCHAR(20) NOT NULL,age tinyint UNSIGNED,PRIMARY KEY(id,name));

🍊 范例:auto_increment 属性

demo1:

# auto_increment_offset 定义初始值
# auto_increment_increment 定义步进


mysql> SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
+--------------------------+-------+
2 rows in set (0.00 sec)

##设置auto_increment 属性
mysql> SET @@auto_increment_increment=10;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @@auto_increment_offset=3;
Query OK, 0 rows affected (0.00 sec)


mysql> SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 10 |
| auto_increment_offset | 3 |
+--------------------------+-------+
2 rows in set (0.00 sec)


##创建表和修改表
mysql> CREATE TABLE autoinc1 (col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO autoinc1 VALUES (NULL), (NULL), (NULL), (NULL); ##代表插入4条数据
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0



mysql> SELECT * FROM autoinc1;
+-----+
| col |
+-----+
| 3 |
| 13 |
| 23 |
| 33 |
+-----+
4 rows in set (0.00 sec)

mysql>

demo2:

🍊 范例:表的创建及auto_increment测试

```sql
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> use test
Database changed

mysql> create table t1(id int unsigned auto_increment primary key);
Query OK, 0 rows affected (0.02 sec)

mysql> desc t1;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
+-------+------------------+------+-----+---------+----------------+
1 row in set (0.00 sec)


mysql> insert into t1 values(null);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t1;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)



#又插入一条
mysql> insert into t1 values(null);
Query OK, 1 row affected (0.01 sec)

mysql> select * from t1;
+----+
| id |
+----+
| 1 |
| 2 |
+----+
2 rows in set (0.00 sec)



##测试auto_increment
mysql> create table t2(id int unsigned auto_increment primary key) auto_increment = 4294967294;
Query OK, 0 rows affected (0.00 sec)

mysql> desc t2;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
+-------+------------------+------+-----+---------+----------------+
1 row in set (0.00 sec)

mysql> insert into t2 values(null);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t2;
+------------+
| id |
+------------+
| 4294967294 |
+------------+
1 row in set (0.00 sec)

mysql> insert into t2 values(null);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t2;
+------------+
| id |
+------------+
| 4294967294 |
| 4294967295 |
+------------+
2 rows in set (0.00 sec)

mysql> insert into t2 values(null);
ERROR 1062 (23000): Duplicate entry '4294967295' for key 'PRIMARY'
mysql>

##说明
int(10) unsigned 4个字节
0~4294967295

[root@linux-test ~]#echo 2^32|bc
4294967296
[root@linux-test ~]#
```

🍊 范例:timestamp修饰符

mysql> create table testdate (id int auto_increment primary key,date timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL);

测试过程:

##创建表
mysql> create table testdate (id int auto_increment primary key,date timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL);
Query OK, 0 rows affected (0.02 sec)


##插入数据
mysql> insert testdate (id)values(1);
Query OK, 1 row affected (0.01 sec)

mysql> insert testdate (id)values(2);
Query OK, 1 row affected (0.00 sec)

mysql> insert testdate (id)values(3);
Query OK, 1 row affected (0.01 sec)

mysql> insert testdate (id)values(4);
Query OK, 1 row affected (0.00 sec)


##查询表
mysql> select * from testdate;
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2024-04-27 13:35:20 |
| 2 | 2024-04-27 13:35:22 |
| 3 | 2024-04-27 13:35:24 |
| 4 | 2024-04-27 13:35:27 |
+----+---------------------+
4 rows in set (0.00 sec)

mysql>
方式2: 通过查询现存表创建;新表会被直接插入查询而来的数据
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name   [(create_definition,...)]   
[table_options]
[partition_options]   select_statement

范例:

##当前表:
mysql> desc testdate;
+-------+-----------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+-----------+------+-----+-------------------+----------------+
2 rows in set (0.00 sec)

mysql> select * from testdate;
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2024-04-27 13:35:20 |
| 2 | 2024-04-27 13:35:22 |
| 3 | 2024-04-27 13:35:24 |
| 4 | 2024-04-27 13:35:27 |
+----+---------------------+
4 rows in set (0.00 sec)


##新创建表
mysql> create table testdate2 select * from testdate;
Query OK, 4 rows affected (0.02 sec)
Records: 4 Duplicates: 0 Warnings: 0

mysql> desc testdate2;
+-------+-----------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+-------+
| id | int(11) | NO | | 0 | |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+-----------+------+-----+-------------------+-------+
2 rows in set (0.00 sec)

mysql> select * from testdate2;
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2024-04-27 13:35:20 |
| 2 | 2024-04-27 13:35:22 |
| 3 | 2024-04-27 13:35:24 |
| 4 | 2024-04-27 13:35:27 |
+----+---------------------+
4 rows in set (0.00 sec)

#注意:新创建的表里的数据和原表一致,只是表结构里可能会缺少一些属性值;
mysql> desc testdate;
+-------+-----------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+-----------+------+-----+-------------------+----------------+
2 rows in set (0.00 sec)
mysql> desc testdate2;
+-------+-----------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+-------+
| id | int(11) | NO | | 0 | |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+-----------+------+-----+-------------------+-------+
2 rows in set (0.00 sec)
方式3:通过复制现存的表的表结构创建,但不复制数据
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name { LIKE old_tbl_name | (LIKEold_tbl_name) }

范例:

##老表
mysql> desc testdate;
+-------+-----------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+-----------+------+-----+-------------------+----------------+
2 rows in set (0.00 sec)

mysql> select * from testdate;
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2024-04-27 13:35:20 |
| 2 | 2024-04-27 13:35:22 |
| 3 | 2024-04-27 13:35:24 |
| 4 | 2024-04-27 13:35:27 |
+----+---------------------+
4 rows in set (0.00 sec)



##新表
mysql> create table testdate3 like testdate;
Query OK, 0 rows affected (0.00 sec)
mysql> desc testdate3;
+-------+-----------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+-----------+------+-----+-------------------+----------------+
2 rows in set (0.00 sec)

mysql> select * from testdate3;
Empty set (0.00 sec)

#说明:通过这种方式创建的表,数据为空,但表结构和老表完全一致。

表查看

  • 查看支持的engine类型
SHOW ENGINES;
  • 查看表:
SHOW TABLES [FROM db_name]

范例:
mysql> SHOW TABLES;
+----------------+
| Tables_in_test |
+----------------+
| autiinc1 |
| autoinc1 |
| student |
| t1 |
| t2 |
| testdate |
| testdate2 |
| testdate3 |
+----------------+
8 rows in set (0.00 sec)
  • 查看表结构:
DESC [db_name.]tb_name
SHOW COLUMNS FROM [db_name.]tb_name

范例:

mysql> desc testdate;
+-------+-----------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+-----------+------+-----+-------------------+----------------+
2 rows in set (0.00 sec)

mysql> show columns from testdate;
+-------+-----------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+-----------+------+-----+-------------------+----------------+
2 rows in set (0.00 sec)

  • 查看表创建命令:
SHOW CREATE TABLE tbl_name

范例:

mysql> show create table student;
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| student | CREATE TABLE `student` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`age` tinyint(3) unsigned DEFAULT NULL,
`gender` enum('M','F') DEFAULT 'M',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from stu
+----+----------+------+
| id | name | age |
+----+----------+------+
| 10 | xiaoming | 20 |
| 11 | xiaohong | 18 |
+----+----------+------+
2 rows in set (0.00 sec)
  • 查看表状态:
SHOW TABLE STATUS LIKE 'student'\G

范例:

mysql>  SHOW TABLE STATUS LIKE 'student'\G
*************************** 1. row ***************************
Name: student
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 2
Avg_row_length: 8192
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: 12
Create_time: 2024-04-27 09:10:06
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)

mysql>
  • 查看库中所有表状态
SHOW TABLE STATUS FROM db_name;

范例:

mysql> show table status from test\G;
*************************** 1. row ***************************
Name: autiinc1
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 0
Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: 1
Create_time: 2024-04-27 09:29:38
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
*************************** 2. row ***************************
Name: autoinc1
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 4
Avg_row_length: 4096
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: 43
Create_time: 2024-04-27 09:32:21
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
*************************** 3. row ***************************
Name: student
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 2
Avg_row_length: 8192
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: 12
Create_time: 2024-04-27 09:10:06
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
……

修改和删除表

  • 删除表
DROP TABLE [IF EXISTS] 'tbl_name';

范例:

mysql> drop table autoinc1; ##就是删除了mysql目录对应表的2个文件
Query OK, 0 rows affected (0.00 sec)

mysql>
  • 修改表
ALTER TABLE 'tbl_name'
#字段:
#添加字段:add
ADD col1 data_type [FIRST|AFTER col_name]
#删除字段:drop
#修改字段:
alter(默认值), change(字段名), modify(字段属性)

范例:添加字段:add

mysql> alter table student add mobile char(11) not null default '13801380000' after name;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> select *from student;
+----+----------+-------------+------+--------+
| id | name | mobile | age | gender |
+----+----------+-------------+------+--------+
| 10 | xiaoming | 13801380000 | 20 | M |
| 11 | xiaohong | 13801380000 | 18 | F |
+----+----------+-------------+------+--------+
2 rows in set (0.00 sec)

mysql>

范例:修改字段属性

mysql> alter table student modify  mobile char(12);
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0

mysql> desc student;
+--------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| mobile | char(12) | YES | | NULL | |
| age | tinyint(3) unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+---------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

mysql>

范例:删除表的某一列

mysql> select *from student;
+----+----------+-------------+------+--------+
| id | name | mobile | age | gender |
+----+----------+-------------+------+--------+
| 10 | xiaoming | 13801380000 | 20 | M |
| 11 | xiaohong | 13801380000 | 18 | F |
+----+----------+-------------+------+--------+
2 rows in set (0.00 sec)

mysql> alter table student drop column mobile;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
+----+----------+------+--------+
2 rows in set (0.00 sec)
  • 查看修改表帮助
Help ALTER TABLE
  • 修改表范例
ALTER TABLE students RENAME s1;
ALTER TABLE s1 ADD phone varchar(11) AFTER name;
ALTER TABLE s1 MODIFY phone int;
ALTER TABLE s1 CHANGE COLUMN phone mobile char(11);
ALTER TABLE s1 DROP COLUMN mobile;
ALTER TABLE s1 character set utf8;
ALTER TABLE s1 change name name varchar(20) character set utf8;
ALTER TABLE students ADD gender ENUM('m','f');
ALETR TABLE students CHANGE id sid int UNSIGNED NOT NULL PRIMARY KEY;
ALTER TABLE students DROP age;
DESC students;

#新建表无主键,添加和删除主键
CREATE TABLE t1 SELECT * FROM students;
ALTER TABLE t1 add primary key (stuid);
ALTER TABLE t1 drop primary key ;

🍊 范例:

ALTER TABLE s1 character set utf8;


DML语句

DML: INSERT, DELETE, UPDATE

INSERT 语句

功能:一次插入一行或多行数据 语法

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
  [INTO] tbl_name [(col_name,...)]
  {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
  [ ON DUPLICATE KEY UPDATE #如果重复更新之
    col_name=expr
      [, col_name=expr] ... ]
     
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
  [INTO] tbl_name
   SET col_name={expr | DEFAULT}, ...
  [ ON DUPLICATE KEY UPDATE
    col_name=expr
      [, col_name=expr] ... ]
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
  [INTO] tbl_name [(col_name,...)]
   SELECT ...
  [ ON DUPLICATE KEY UPDATE
    col_name=expr
      [, col_name=expr] ... ]

简化写法:

INSERT tbl_name [(col1,...)] VALUES (val1,...), (val21,...)

方法1:

🍊 范例:省略col_name,给所有value赋值

mysql> select *from student;                                                                                                    
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
+----+----------+------+--------+
2 rows in set (0.00 sec)

mysql> insert student value (1,'xyy',18,'F');
Query OK, 1 row affected (0.02 sec)

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
+----+----------+------+--------+
3 rows in set (0.00 sec)

🍊 范例:给部分列属性赋值

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
+----+----------+------+--------+
3 rows in set (0.00 sec)

mysql> insert student (name,age,gender) value ('hg',19,'M');
Query OK, 1 row affected (0.02 sec)

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
+----+----------+------+--------+
4 rows in set (0.00 sec)

🍊 范例:给部分列属性赋值,并一次性添加多条记录。

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
+----+----------+------+--------+
4 rows in set (0.00 sec)

mysql> insert student (name,age,gender) value ('lianlian',18,'F'),('xiaoxiao',18,'F'),('yanyan',19,'F');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
| 13 | lianlian | 18 | F |
| 14 | xiaoxiao | 18 | F |
| 15 | yanyan | 19 | F |
+----+----------+------+--------+
7 rows in set (0.00 sec)

方法2:

🍊 范例:利用旧表的数据批量地导入

mysql> create table student2 like  student;
Query OK, 0 rows affected (0.02 sec)

mysql> select *from student2;
Empty set (0.00 sec)

mysql> insert student2 select *from student;
Query OK, 7 rows affected (0.01 sec)
Records: 7 Duplicates: 0 Warnings: 0

mysql> select *from student2;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
| 13 | lianlian | 18 | F |
| 14 | xiaoxiao | 18 | F |
| 15 | yanyan | 19 | F |
+----+----------+------+--------+
7 rows in set (0.00 sec)

方法3:set方式

mysql> insert student set name='hao',age=22,gender='M';

范例:

mysql> insert student set name='hao',age=22,gender='M';
Query OK, 1 row affected (0.01 sec)

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
| 13 | lianlian | 18 | F |
| 14 | xiaoxiao | 18 | F |
| 15 | yanyan | 19 | F |
| 16 | hao | 22 | M |
+----+----------+------+--------+
8 rows in set (0.00 sec)

UPDATE 语句

语法:

UPDATE [LOW_PRIORITY] [IGNORE] table_reference
   SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...
  [WHERE where_condition]
  [ORDER BY ...]
  [LIMIT row_count]

注意:一定要有限制条件,否则将修改所有行的指定字段

可利用mysql 选项避免此错误:

mysql -U | --safe-updates| --i-am-a-dummy
[root@centos8 ~]#vim /etc/my.cnf
[mysql]
safe-updates

🍊 范例:更新某个单元格的数据

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
| 13 | lianlian | 18 | F |
| 14 | xiaoxiao | 18 | F |
| 15 | yanyan | 19 | F |
| 16 | hao | 22 | M |
+----+----------+------+--------+
8 rows in set (0.00 sec)

#mysql> update student set age=18; ##这个是灾难性的后果,会修改该列的所有值的;
mysql> update student set age=18 where id=15;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
| 13 | lianlian | 18 | F |
| 14 | xiaoxiao | 18 | F |
| 15 | yanyan | 18 | F |
| 16 | hao | 22 | M |
+----+----------+------+--------+
8 rows in set (0.00 sec)

🍊 范例:多个字段同时修改

mysql> update student set age=28,gender='F' where id=16;
mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
| 13 | lianlian | 18 | F |
| 14 | xiaoxiao | 18 | F |
| 15 | yanyan | 18 | F |
| 16 | hao | 22 | M |
+----+----------+------+--------+
8 rows in set (0.00 sec)

mysql> update student set age=28,gender='F' where id=16;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
| 13 | lianlian | 18 | F |
| 14 | xiaoxiao | 18 | F |
| 15 | yanyan | 18 | F |
| 16 | hao | 28 | F |
+----+----------+------+--------+
8 rows in set (0.00 sec)

mysql>

🍊 范例:模拟灾难性更新效果

mysql> update student set age=8;
##当前表信息
mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
| 13 | lianlian | 18 | F |
| 14 | xiaoxiao | 18 | F |
| 15 | yanyan | 18 | F |
| 16 | hao | 28 | F |
+----+----------+------+--------+
8 rows in set (0.00 sec)


##灾难性更新
mysql> update student set age=8;
Query OK, 8 rows affected (0.00 sec)
Rows matched: 8 Changed: 8 Warnings: 0


##查询
mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 8 | F |
| 10 | xiaoming | 8 | M |
| 11 | xiaohong | 8 | F |
| 12 | hg | 8 | M |
| 13 | lianlian | 8 | F |
| 14 | xiaoxiao | 8 | F |
| 15 | yanyan | 8 | F |
| 16 | hao | 8 | F |
+----+----------+------+--------+
8 rows in set (0.00 sec)

如何避免这个问题呢?

mysql -U | --safe-updates| --i-am-a-dummy
[root@centos8 ~]#vim /etc/my.cnf
[mysql]
safe-updates

方法1:加上-U选项

[root@linux-test ~]#mysql -uroot -pxyy520 -U
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 5.6.47 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> update student set age=18;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
mysql>

方法2:写到mysql配置文件里

[root@linux-test ~]#vim /etc/my.cnf
[mysql]
safe-updates

然后再次测试:
[root@linux-test ~]#mysql -uroot -pxyy520
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 5.6.47 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 8 | F |
| 10 | xiaoming | 8 | M |
| 11 | xiaohong | 8 | F |
| 12 | hg | 8 | M |
| 13 | lianlian | 8 | F |
| 14 | xiaoxiao | 8 | F |
| 15 | yanyan | 8 | F |
| 16 | hao | 8 | F |
+----+----------+------+--------+
8 rows in set (0.00 sec)

mysql> update student set age=18;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
mysql>
#符合预期。

DELETE语句

删除表中数据,但不会自动缩减数据文件的大小。

语法:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
  [WHERE where_condition]
  [ORDER BY ...]
  [LIMIT row_count]
可先排序再指定删除的行数

注意:一定要有限制条件,否则将清空表中的所有数据

🍊 范例:删除表里某行数据

mysql> delete from student where id=16;
mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 8 | F |
| 10 | xiaoming | 8 | M |
| 11 | xiaohong | 8 | F |
| 12 | hg | 8 | M |
| 13 | lianlian | 8 | F |
| 14 | xiaoxiao | 8 | F |
| 15 | yanyan | 8 | F |
| 16 | hao | 8 | F |
+----+----------+------+--------+
8 rows in set (0.00 sec)

mysql> delete from student where id=16;
Query OK, 1 row affected (0.02 sec)

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 8 | F |
| 10 | xiaoming | 8 | M |
| 11 | xiaohong | 8 | F |
| 12 | hg | 8 | M |
| 13 | lianlian | 8 | F |
| 14 | xiaoxiao | 8 | F |
| 15 | yanyan | 8 | F |
+----+----------+------+--------+
7 rows in set (0.00 sec)

🍊 范例:删除表里所有数据

mysql> delete from student;
mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 8 | F |
| 10 | xiaoming | 8 | M |
| 11 | xiaohong | 8 | F |
| 12 | hg | 8 | M |
| 13 | lianlian | 8 | F |
| 14 | xiaoxiao | 8 | F |
| 15 | yanyan | 8 | F |
+----+----------+------+--------+
7 rows in set (0.00 sec)

mysql> delete from student;
Query OK, 7 rows affected (0.02 sec)

mysql> select *from student;
Empty set (0.00 sec)

🍊 范例:TRUNCATE命令来删除表数据

如果想清空表,保留表结构,也可以使用下面语句,此语句会自动缩减数据文件的大小。

TRUNCATE TABLE tbl_name; #当表数据量很大的时候,这个方式删除会比前面 delete from student; 这条命令速度更快些的;
mysql> insert student select *from student2;
Query OK, 7 rows affected (0.00 sec)
Records: 7 Duplicates: 0 Warnings: 0

mysql> select *from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
| 13 | lianlian | 18 | F |
| 14 | xiaoxiao | 18 | F |
| 15 | yanyan | 19 | F |
+----+----------+------+--------+
7 rows in set (0.00 sec)

mysql> truncate table student;
Query OK, 0 rows affected (0.02 sec)

mysql> select *from student;
Empty set (0.00 sec)

[!NOTE]

注意:mysql -U选项也可以防止delete命令忘记添加where条件导致误删数据的,但对truncate命令无影响。

🍊 范例:缩减表大小

OPTIMIZE TABLE tb_name

如下是一个生成大文件表的sql脚本:

testlog.sql

create table testlog (id int auto_increment primary key,name char(10),age int default 20);

delimiter $$

create procedure pro_testlog()
begin
declare i int;
set i = 1;
while i < 100000
do insert into testlog(name,age) values (concat('wang',i),i);
set i = i +1;
end while;
end$$

delimiter ;

将这个代码拷贝到自己数据库里:

[root@linux-test ~]#mysql -uroot -pxyy520 test

mysql> create table testlog (id int auto_increment primary key,name char(10),age int default 20);
Query OK, 0 rows affected (0.01 sec)

mysql>
mysql> delimiter $$
mysql>
mysql> create procedure pro_testlog()
-> begin
-> declare i int;
-> set i = 1;
-> while i < 100000
-> do insert into testlog(name,age) values (concat('wang',i),i);
-> set i = i +1;
-> end while;
-> end$$
Query OK, 0 rows affected (0.01 sec)

mysql>
mysql> delimiter ;
mysql>

查看当前表信息:

mysql> select *from testlog;
Empty set (0.00 sec)

[root@linux-test ~]#ll -h /data/mysql/test
total 1.1M
……
-rw-rw---- 1 mysql mysql 8.5K Apr 28 07:19 testlog.frm
-rw-rw---- 1 mysql mysql 96K Apr 28 07:19 testlog.ibd #这个文件是96K

触发脚本:

mysql> call pro_testlog;
Query OK, 1 row affected (16.77 sec)

[root@linux-test ~]#ll -h /data/mysql/test/testlog.ibd
-rw-rw---- 1 mysql mysql 11M Apr 28 07:21 /data/mysql/test/testlog.ibd
[root@linux-test ~]#ll -h /data/mysql/test/testlog.ibd
-rw-rw---- 1 mysql mysql 12M Apr 28 07:21 /data/mysql/test/testlog.ibd
#可以看到这个testlog.ibd文件已经增大到12M了。

此时直接使用delete from testlog; 命令删除表后,那么这个/data/mysql/test/testlog.ibd文件大小是否会变小呢?

mysql> delete from testlog;
Query OK, 99999 rows affected (0.20 sec)

mysql> select *from testlog;
Empty set (0.00 sec)

mysql>


[root@linux-test ~]#ll -h /data/mysql/test/testlog.ibd
-rw-rw---- 1 mysql mysql 12M Apr 28 07:24 /data/mysql/test/testlog.ibd
#可以发现这个文件大小依然没有变化。

那么我们可以利用如下命令来清理这种空洞文件:

mysql> OPTIMIZE TABLE testlog;
+--------------+----------+----------+-------------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------------+----------+----------+-------------------------------------------------------------------+
| test.testlog | optimize | note | Table does not support optimize, doing recreate + analyze instead |
| test.testlog | optimize | status | OK |
+--------------+----------+----------+-------------------------------------------------------------------+
2 rows in set (0.01 sec)

##再次验证(符合预期)
[root@linux-test ~]#ll -h /data/mysql/test/testlog.ibd
-rw-rw---- 1 mysql mysql 96K Apr 28 07:25 /data/mysql/test/testlog.ibd

当然,truncate命令直接是可以会自动缩减数据文件的大小的。

| 199997 | wang99998 | 99998 |
| 199998 | wang99999 | 99999 |
+--------+-----------+-------+
99999 rows in set (0.04 sec)

mysql> truncate table testlog;
Query OK, 0 rows affected (0.01 sec)

[root@linux-test ~]#ll -h /data/mysql/test/testlog.ibd
-rw-rw---- 1 mysql mysql 96K Apr 28 07:26 /data/mysql/test/testlog.ibd

DQL语句

行的过滤才是至关重要的!

单表操作

语法:

SELECT
[ALL | DISTINCT | DISTINCTROW ]
[SQL_CACHE | SQL_NO_CACHE]
select_expr [, select_expr ...]
  [FROM table_references
  [WHERE where_condition]
  [GROUP BY {col_name | expr | position}
    [ASC | DESC], ... [WITH ROLLUP]]
  [HAVING where_condition]
  [ORDER BY {col_name | expr | position}
    [ASC | DESC], ...]
  [LIMIT {[offset,] row_count | row_count OFFSET offset}]
  [FOR UPDATE | LOCK IN SHARE MODE]

说明:

  • 字段显示可以使用别名:col1 AS alias1, col2 AS alias2, ...

  • WHERE子句:指明过滤条件以实现“选择”的功能:

过滤条件:布尔型表达式

算术操作符:+, -, *, /, %

比较操作符:=,<=>(相等或都为空), <>(不等), !=(非标准SQL), >, >=, <, <=

BETWEEN min_num AND max_num

IN (element1, element2, ...)

IS NULL

IS NOT NULL

DISTINCT 去除重复行,范例:SELECT DISTINCT gender FROM students;

LIKE:

% 任意长度的任意字符

_ 任意单个字符

RLIKE:正则表达式,索引失效,不建议使用 --一般不建议使用正则表达式,它的性能很差

REGEXP:匹配字符串可用正则表达式书写模式,同上

逻辑操作符:NOT,AND,OR,XOR

GROUP:根据指定的条件把查询结果进行“分组”以用于做“聚合”运算

常见聚合函数:avg(), max(), min(), count(), sum()

HAVING: 对分组聚合运算后的结果指定过滤条件

一旦分组group by ,select语句后只跟分组的字段,聚合函数

ORDER BY: 根据指定的字段对查询结果进行排序

升序:ASC

降序:DESC

LIMIT [[offset,]row_count]:对查询的结果进行输出行数数量限制

对查询结果中的数据请求施加“锁”

FOR UPDATE: 写锁,独占或排它锁,只有一个读和写操作

LOCK IN SHARE MODE: 读锁,共享锁,同时多个读操作

范例:整张表的所有内容
06:44:07(root@localhost) [test]> select * from student; #*代表对所有列不过滤,student后面也没where,代表对所有航也不过滤,即显示整张表的所有内容。
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 1 | xyy | 18 | F |
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
| 12 | hg | 19 | M |
| 13 | lianlian | 18 | F |
| 14 | xiaoxiao | 18 | F |
| 15 | yanyan | 19 | F |
| 17 | 马哥 | 30 | M |
| 18 | 马云 | 30 | M |
| 19 | 马弟弟 | 30 | M |
| 20 | 小彦彦 | 18 | F |
+----+-----------+------+--------+
11 rows in set (0.00 sec)
范例:过滤列
select name,age from student; #列的字段名是不区分大小写的,但数据库、表名是区分大小写的;
select NAME,AGE from student;
06:44:18(root@localhost) [test]> select name,age from student; #列的字段名是不区分大小写的,但数据库、表名是区分大小写的;
+-----------+------+
| name | age |
+-----------+------+
| xyy | 18 |
| xiaoming | 20 |
| xiaohong | 18 |
| hg | 19 |
| lianlian | 18 |
| xiaoxiao | 18 |
| yanyan | 19 |
| 马哥 | 30 |
| 马云 | 30 |
| 马弟弟 | 30 |
| 小彦彦 | 18 |
+-----------+------+
11 rows in set (0.00 sec)

06:51:25(root@localhost) [test]> select NAME,AGE from student;
+-----------+------+
| NAME | AGE |
+-----------+------+
| xyy | 18 |
| xiaoming | 20 |
| xiaohong | 18 |
| hg | 19 |
| lianlian | 18 |
| xiaoxiao | 18 |
| yanyan | 19 |
| 马哥 | 30 |
| 马云 | 30 |
| 马弟弟 | 30 |
| 小彦彦 | 18 |
+-----------+------+
11 rows in set (0.00 sec)
范例:过滤列(给字段起别名)
06:51:41(root@localhost) [test]> select name as 姓名,age 年龄,gender 性别  from student; #加不加as都行的。
+-----------+--------+--------+
| 姓名 | 年龄 | 性别 |
+-----------+--------+--------+
| xyy | 18 | F |
| xiaoming | 20 | M |
| xiaohong | 18 | F |
| hg | 19 | M |
| lianlian | 18 | F |
| xiaoxiao | 18 | F |
| yanyan | 19 | F |
| 马哥 | 30 | M |
| 马云 | 30 | M |
| 马弟弟 | 30 | M |
| 小彦彦 | 18 | F |
+-----------+--------+--------+
11 rows in set (0.00 sec)

🍊 范例:(多表的情况下,别名还是经常会用的)

[!NOTE]

注意:mysql里,一旦定义了别名就必须要使用别名,再使用原名是不行的。

MariaDB [hellodb]> select stuid,students.name 学生姓名,s.age 学生年龄,tid,t.name 老师姓名,t.age 老师 年龄 from students s cross join teachers t;;
ERROR 1054 (42S22): Unknown column 'students.name' in 'field list'

MariaDB [hellodb]> select stuid,s.name 学生姓名,s.age 学生年龄,tid,t.name 老师姓名,t.age 老师年龄 from students s cross join teachers t;
+-------+---------------+--------------+-----+---------------+--------------+
| stuid | 学生姓名 | 学生年龄 | tid | 老师姓名 | 老师年龄 |
+-------+---------------+--------------+-----+---------------+--------------+
| 1 | Shi Zhongyu | 22 | 1 | Song Jiang | 45 |
| 1 | Shi Zhongyu | 22 | 2 | Zhang Sanfeng | 94 |
| 1 | Shi Zhongyu | 22 | 3 | Miejue Shitai | 77 |
范例:针对特定字段DISTINCT 去除重复行
07:03:09(root@localhost) [test]> SELECT DISTINCT gender FROM student;
+--------+
| gender |
+--------+
| F |
| M |
+--------+
2 rows in set (0.00 sec)
范例:过滤列和行(等于/不等于)
07:03:13(root@localhost) [test]> select * from student where gender='F';
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 1 | xyy | 18 | F |
| 11 | xiaohong | 18 | F |
| 13 | lianlian | 18 | F |
| 14 | xiaoxiao | 18 | F |
| 15 | yanyan | 19 | F |
| 20 | 小彦彦 | 18 | F |
+----+-----------+------+--------+
6 rows in set (0.01 sec)

07:08:45(root@localhost) [test]> select name,age,gender from student where gender='F';
+-----------+------+--------+
| name | age | gender |
+-----------+------+--------+
| xyy | 18 | F |
| xiaohong | 18 | F |
| lianlian | 18 | F |
| xiaoxiao | 18 | F |
| yanyan | 19 | F |
| 小彦彦 | 18 | F |
+-----------+------+--------+
6 rows in set (0.00 sec)

其它demo:
select name,age,gender from student where gender <> 'F';
select name,age,gender from student where gender != 'F';

select name,age,gender from student where gender = 'F';
select name,age,gender from student where gender <=> 'F';
范例:(>=或者between …… and ……
07:09:46(root@localhost) [test]> select name,age,gender  from student where age<=18;
+-----------+------+--------+
| name | age | gender |
+-----------+------+--------+
| xyy | 18 | F |
| xiaohong | 18 | F |
| lianlian | 18 | F |
| xiaoxiao | 18 | F |
| 小彦彦 | 18 | F |
+-----------+------+--------+
5 rows in set (0.00 sec)

07:13:07(root@localhost) [test]> select name,age,gender from student where age>=18 and age <=28;
+-----------+------+--------+
| name | age | gender |
+-----------+------+--------+
| xyy | 18 | F |
| xiaoming | 20 | M |
| xiaohong | 18 | F |
| hg | 19 | M |
| lianlian | 18 | F |
| xiaoxiao | 18 | F |
| yanyan | 19 | F |
| 小彦彦 | 18 | F |
+-----------+------+--------+
8 rows in set (0.00 sec)

07:13:29(root@localhost) [test]> select name,age,gender from student where age between 18 and 28;
+-----------+------+--------+
| name | age | gender |
+-----------+------+--------+
| xyy | 18 | F |
| xiaoming | 20 | M |
| xiaohong | 18 | F |
| hg | 19 | M |
| lianlian | 18 | F |
| xiaoxiao | 18 | F |
| yanyan | 19 | F |
| 小彦彦 | 18 | F |
+-----------+------+--------+
8 rows in set (0.00 sec)
范例:参与数字运算
07:14:44(root@localhost) [test]> select name,age+18,gender  from student;
+-----------+--------+--------+
| name | age+18 | gender |
+-----------+--------+--------+
| xyy | 36 | F |
| xiaoming | 38 | M |
| xiaohong | 36 | F |
| hg | 37 | M |
| lianlian | 36 | F |
| xiaoxiao | 36 | F |
| yanyan | 37 | F |
| 马哥 | 48 | M |
| 马云 | 48 | M |
| 马弟弟 | 48 | M |
| 小彦彦 | 36 | F |
+-----------+--------+--------+
11 rows in set (0.00 sec)



07:16:40(root@localhost) [test]> select 10*20;
+-------+
| 10*20 |
+-------+
| 200 |
+-------+
1 row in set (0.00 sec)

07:18:17(root@localhost) [test]> select 10*20 as result;
+--------+
| result |
+--------+
| 200 |
+--------+
1 row in set (0.00 sec)
范例:in用法
07:19:22(root@localhost) [test]> select name,age,gender  from student where age in (18,19,20);
+-----------+------+--------+
| name | age | gender |
+-----------+------+--------+
| xyy | 18 | F |
| xiaoming | 20 | M |
| xiaohong | 18 | F |
| hg | 19 | M |
| lianlian | 18 | F |
| xiaoxiao | 18 | F |
| yanyan | 19 | F |
| 小彦彦 | 18 | F |
+-----------+------+--------+
8 rows in set (0.00 sec)

范例:判断为空
07:24:26(root@localhost) [hellodb]> select * from students where classid == NULL;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '== NULL' at line 1
07:24:30(root@localhost) [hellodb]> select * from students where classid == null;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '== null' at line 1


07:24:39(root@localhost) [hellodb]> select * from students where classid is NULL;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+-------------+-----+--------+---------+-----------+
2 rows in set (0.00 sec)

07:24:45(root@localhost) [hellodb]> select * from students where classid is null;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+-------------+-----+--------+---------+-----------+
2 rows in set (0.00 sec)

07:24:49(root@localhost) [hellodb]> select * from students where classid <=> null; #这个写法也是可以的。
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+-------------+-----+--------+---------+-----------+
2 rows in set (0.00 sec)

select * from students where classid is not null;
范例:模糊查找
07:27:07(root@localhost) [hellodb]> select * from students where name like 'xu%'; #大小写不敏感的,过滤xu开头的
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
+-------+-------------+-----+--------+---------+-----------+
3 rows in set (0.00 sec)

范例:SQL 注入攻击
方式1
select * from user where username='admin' and password='' or '1'='1';
select * from user where username='admin' and password='' or '1=1';

方式2:注释方式
select * from user where username='admin'; -- ' and password='magedu123';
select * from user where username='admin'; # ' and password='magedu123';
##先创建一张表:
07:26:13(root@localhost) [test]> create table user (id int primary key auto_increment, username varchar(30) not null, password varchar(50));
Query OK, 0 rows affected (0.01 sec)

07:27:40(root@localhost) [test]> select *from user;
Empty set (0.00 sec)


##插入一条数据:
07:27:49(root@localhost) [test]> insert user (username,password)values('admin','Magedu20230206');
Query OK, 1 row affected (0.01 sec)

07:29:23(root@localhost) [test]> select *from user;
+----+----------+----------------+
| id | username | password |
+----+----------+----------------+
| 1 | admin | Magedu20230206 |
+----+----------+----------------+
1 row in set (0.00 sec)
##再插入一条数据:
07:32:18(root@localhost) [test]> insert user (username,password)values('hg','Magedu');
Query OK, 1 row affected (0.01 sec)

07:33:17(root@localhost) [test]> select *from user;
+----+----------+----------------+
| id | username | password |
+----+----------+----------------+
| 1 | admin | Magedu20230206 |
| 2 | hg | Magedu |
+----+----------+----------------+
2 rows in set (0.00 sec)




##一般网页登录时会查询后台数据库里用户名和密码是否匹配
07:29:26(root@localhost) [test]> select *from user where username='admin' and password='mage';
Empty set (0.00 sec)

07:32:03(root@localhost) [test]> select *from user where username='admin' and password='Magedu20230206';
+----+----------+----------------+
| id | username | password |
+----+----------+----------------+
| 1 | admin | Magedu20230206 |
+----+----------+----------------+
1 row in set (0.00 sec)



##此时如何利用mysql注入攻击呢?
07:33:36(root@localhost) [test]> select * from user where username='admin' and password='' or '1'='1';
+----+----------+----------------+
| id | username | password |
+----+----------+----------------+
| 1 | admin | Magedu20230206 |
| 2 | hg | Magedu |
+----+----------+----------------+
2 rows in set (0.00 sec)
##呃呃,这个也就绕过来密码,直接查到了user表里的所有信息。
07:34:59(root@localhost) [test]> select * from user where '1'='1'; ##这个同理也是可以查出表的所有信息的!
+----+----------+----------------+
| id | username | password |
+----+----------+----------------+
| 1 | admin | Magedu20230206 |
| 2 | hg | Magedu |
+----+----------+----------------+
2 rows in set (0.00 sec)




另一个方式测试SQL注入攻击:
构建一个特殊的用户名:
#-- 和 #代表注释;
07:49:29(root@localhost) [test]> select * from user where username='admin'; -- ' and password='magedu123';
+----+----------+----------------+
| id | username | password |
+----+----------+----------------+
| 1 | admin | Magedu20230206 |
+----+----------+----------------+
1 row in set (0.00 sec)

07:50:30(root@localhost) [test]> select * from user where username='admin'; # ' and password='magedu123';
+----+----------+----------------+
| id | username | password |
+----+----------+----------------+
| 1 | admin | Magedu20230206 |
+----+----------+----------------+
1 row in set (0.00 sec)
范例:rlike正则表达式
07:56:39(root@localhost) [hellodb]> select *from students where name rlike '^Shi';
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
+-------+-------------+-----+--------+---------+-----------+
3 rows in set (0.01 sec)

07:56:43(root@localhost) [hellodb]> select *from students where name rlike '^shi'; #这里的正则表达式后不区分大小写。
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
+-------+-------------+-----+--------+---------+-----------+
3 rows in set (0.00 sec)

范例:group分组

一个是分组字段本身;

或者是聚合函数;

其它字段毫无意义。

08:10:34(root@localhost) [hellodb]> select gender,avg(age),max(age),min(age) from students group by gender;
+--------+----------+----------+----------+
| gender | avg(age) | max(age) | min(age) |
+--------+----------+----------+----------+
| F | 19.0000 | 22 | 17 |
| M | 33.0000 | 100 | 19 |
+--------+----------+----------+----------+
2 rows in set (0.00 sec)
08:13:35(root@localhost) [hellodb]> select gender,avg(age),sum(age),max(age),min(age) from students group by gender;
+--------+----------+----------+----------+----------+
| gender | avg(age) | sum(age) | max(age) | min(age) |
+--------+----------+----------+----------+----------+
| F | 19.0000 | 190 | 22 | 17 |
| M | 33.0000 | 495 | 100 | 19 |
+--------+----------+----------+----------+----------+
2 rows in set (0.00 sec)

对多字段分别统计:

08:11:41(root@localhost) [hellodb]> select classid,gender,avg(age),max(age),min(age) from students group by classid,gender;
+---------+--------+----------+----------+----------+
| classid | gender | avg(age) | max(age) | min(age) |
+---------+--------+----------+----------+----------+
| NULL | M | 63.5000 | 100 | 27 |
| 1 | F | 19.5000 | 20 | 19 |
| 1 | M | 21.5000 | 22 | 21 |
| 2 | M | 36.0000 | 53 | 22 |
| 3 | F | 18.3333 | 19 | 17 |
| 3 | M | 26.0000 | 26 | 26 |
| 4 | M | 24.7500 | 32 | 19 |
| 5 | M | 46.0000 | 46 | 46 |
| 6 | F | 20.0000 | 22 | 18 |
| 6 | M | 23.0000 | 23 | 23 |
| 7 | F | 18.0000 | 19 | 17 |
| 7 | M | 23.0000 | 23 | 23 |
+---------+--------+----------+----------+----------+
12 rows in set (0.00 sec)
  • 范例:统计某个班的平均年龄:

方法1:先分组后过滤

06:10:38(root@localhost) [hellodb]> select classid,avg(age) from students group by classid;
+---------+----------+
| classid | avg(age) |
+---------+----------+
| NULL | 63.5000 |
| 1 | 20.5000 |
| 2 | 36.0000 |
| 3 | 20.2500 |
| 4 | 24.7500 |
| 5 | 46.0000 |
| 6 | 20.7500 |
| 7 | 19.6667 |
+---------+----------+
8 rows in set (0.00 sec)

##如果分组右面有where筛选的话,那么where要替换成having才行!
06:11:28(root@localhost) [hellodb]> select classid,avg(age) from students group by classid where classid is not null;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where classid is not null' at line 1



06:11:42(root@localhost) [hellodb]> select classid,avg(age) from students group by classid having classid is not null;
+---------+----------+
| classid | avg(age) |
+---------+----------+
| 1 | 20.5000 |
| 2 | 36.0000 |
| 3 | 20.2500 |
| 4 | 24.7500 |
| 5 | 46.0000 |
| 6 | 20.7500 |
| 7 | 19.6667 |
+---------+----------+
7 rows in set (0.00 sec)

方法2:先过滤后分组

06:11:52(root@localhost) [hellodb]> select classid,avg(age) from students where classid is not null group by classid;
+---------+----------+
| classid | avg(age) |
+---------+----------+
| 1 | 20.5000 |
| 2 | 36.0000 |
| 3 | 20.2500 |
| 4 | 24.7500 |
| 5 | 46.0000 |
| 6 | 20.7500 |
| 7 | 19.6667 |
+---------+----------+
7 rows in set (0.00 sec)
范例:排序
  • 范例:排序
06:20:16(root@localhost) [hellodb]> select *from students order by age;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
  • 范例:排序(逆序)
06:20:33(root@localhost) [hellodb]> select *from students order by age desc;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
  • 范例:排序(字段含null处理)(小技巧)
##默认null优先级比较高,会排在最前面
06:21:00(root@localhost) [hellodb]> select *from students order by classid;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)


##如果让null排在最后面呢?
06:22:40(root@localhost) [hellodb]> select *from students order by -classid desc;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)

asc--正序;(默认不写)

desc--排序;

  • 范例:多列排序
06:22:49(root@localhost) [hellodb]> select *from students order by classid,age; ##先按classid排序,再按age排序;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)

06:26:55(root@localhost) [hellodb]>




06:26:55(root@localhost) [hellodb]> select *from students order by classid desc,age;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
范例:limit

LIMIT [[offset,]row_count]:对查询的结果进行输出行数数量限制。

  • 范例:显示过滤的前10行
06:27:31(root@localhost) [hellodb]> select *from students order by age limit 10;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
+-------+--------------+-----+--------+---------+-----------+
10 rows in set (0.00 sec)


#跳过前2行,显示后3行;(但是这里有问题,后续几行都是19,这里把Duan Yu给跳过了)
06:33:17(root@localhost) [hellodb]> select *from students order by age limit 2,3;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
+-------+--------------+-----+--------+---------+-----------+
3 rows in set (0.00 sec)

#
06:33:29(root@localhost) [hellodb]> select distinct age from students;
+-----+
| age |
+-----+
| 22 |
| 53 |
| 32 |
| 26 |
| 46 |
| 19 |
| 17 |
| 20 |
| 23 |
| 33 |
| 21 |
| 25 |
| 18 |
| 27 |
| 100 |
+-----+
15 rows in set (0.00 sec)

06:38:22(root@localhost) [hellodb]> select distinct age from students order by age;
+-----+
| age |
+-----+
| 17 |
| 18 |
| 19 |
| 20 |
| 21 |
| 22 |
| 23 |
| 25 |
| 26 |
| 27 |
| 32 |
| 33 |
| 46 |
| 53 |
| 100 |
+-----+
15 rows in set (0.00 sec)

06:38:30(root@localhost) [hellodb]> select distinct age from students order by age limit 5;
+-----+
| age |
+-----+
| 17 |
| 18 |
| 19 |
| 20 |
| 21 |
+-----+
5 rows in set (0.00 sec)

06:38:44(root@localhost) [hellodb]> select distinct age from students order by age limit 2,3;
+-----+
| age |
+-----+
| 19 |
| 20 |
| 21 |
+-----+
3 rows in set (0.00 sec)


##当然,我们对主键操作是没问题的,主键里的字段是不重复的。
06:38:48(root@localhost) [hellodb]> select *from students order by stuid limit 2,3;
+-------+-----------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-----------+-----+--------+---------+-----------+
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
+-------+-----------+-----+--------+---------+-----------+
3 rows in set (0.00 sec)
范例:时间查询
  • 范例
06:44:19(root@localhost) [test]> show create table testdate;
+----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| testdate | CREATE TABLE `testdate` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 |
+----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)


06:44:33(root@localhost) [test]> desc testdate;
+-------+-----------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+-----------+------+-----+-------------------+----------------+
2 rows in set (0.00 sec)

06:45:04(root@localhost) [test]> select *from testdate;
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2024-04-27 13:35:20 |
| 2 | 2024-04-27 13:35:22 |
| 3 | 2024-04-27 13:35:24 |
| 4 | 2024-04-27 13:35:27 |
+----+---------------------+
4 rows in set (0.00 sec)


##新加几行数据
06:45:49(root@localhost) [test]> insert testdate (id)values(5);
Query OK, 1 row affected (0.01 sec)

06:46:18(root@localhost) [test]> insert testdate (id)values(6);
Query OK, 1 row affected (0.00 sec)

06:46:20(root@localhost) [test]> insert testdate (id)values(7);
Query OK, 1 row affected (0.00 sec)

06:46:23(root@localhost) [test]> select *from testdate;
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2024-04-27 13:35:20 |
| 2 | 2024-04-27 13:35:22 |
| 3 | 2024-04-27 13:35:24 |
| 4 | 2024-04-27 13:35:27 |
| 5 | 2024-05-02 06:46:18 |
| 6 | 2024-05-02 06:46:20 |
| 7 | 2024-05-02 06:46:23 |
+----+---------------------+
7 rows in set (0.00 sec)



##时间过滤
06:49:18(root@localhost) [test]> select *from testdate where date between '2024-04-27 13:35:22' and '2024-05-02 06:46:20';
+----+---------------------+
| id | date |
+----+---------------------+
| 2 | 2024-04-27 13:35:22 |
| 3 | 2024-04-27 13:35:24 |
| 4 | 2024-04-27 13:35:27 |
| 5 | 2024-05-02 06:46:18 |
| 6 | 2024-05-02 06:46:20 |
+----+---------------------+
5 rows in set (0.00 sec)
06:49:36(root@localhost) [test]> select *from testdate where date between '2024-05-02 06:46:20' and '2024-04-27 13:35:22'; ##小的数值一定要放在前面才行的;
Empty set (0.00 sec)
  • 范例:>= and <=也是可以的。
06:50:38(root@localhost) [test]> select *from testdate where date >='2024-04-27 13:35:22' and date <= '2024-05-02 06:46:20';
+----+---------------------+
| id | date |
+----+---------------------+
| 2 | 2024-04-27 13:35:22 |
| 3 | 2024-04-27 13:35:24 |
| 4 | 2024-04-27 13:35:27 |
| 5 | 2024-05-02 06:46:18 |
| 6 | 2024-05-02 06:46:20 |
+----+---------------------+
5 rows in set (0.00 sec)

多表查询(7个图)🍕

image-20240506061109396

最重要的是这2张图,其它都是从这2个图变过来的。(内连接+左外连接-->其它方式(变种))

多表连接--面试常用的题;工作中也是比较常用的;

多表查询,即查询结果来自于多张表

image-20240502075323051

子查询:在SQL语句嵌套着查询语句,性能较差,基于某语句的查询结果再次进行的查询

联合查询:UNION

交叉连接:笛卡尔乘积

内连接:

等值连接:让表之间的字段以“等值”建立连接关系

不等值连接

自然连接:去掉重复列的等值连接

外连接:

左外连接:FROM tb1 LEFT JOIN tb2 ON tb1.col=tb2.col

右外连接:FROM tb1 RIGHT JOIN tb2 ON tb1.col=tb2.col

自连接:本表和本表进行连接查询

子查询

效率比较低。

常用在WHERE子句中的子查询

1、用于比较表达式中的子查询;子查询仅能返回单个值

SELECT Name,Age FROM students WHERE Age>(SELECT avg(Age) FROM teachers);
  • 范例:
08:37:04(root@localhost) [hellodb]> select avg(age) from students;
+----------+
| avg(age) |
+----------+
| 27.4000 |
+----------+
1 row in set (0.00 sec)

08:37:13(root@localhost) [hellodb]> select *from students where age > (select avg(age) from students);
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+--------------+-----+--------+---------+-----------+
5 rows in set (0.00 sec)



##当然,也可以从其他表查数据的
08:37:50(root@localhost) [hellodb]> select avg(age) from teachers;
+----------+
| avg(age) |
+----------+
| 77.2500 |
+----------+
1 row in set (0.00 sec)

08:37:59(root@localhost) [hellodb]> select *from students where age > (select avg(age) from teachers);\
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+-------------+-----+--------+---------+-----------+
1 row in set (0.00 sec)



##错误案例演示:子查询仅能返回单个值
08:38:00(root@localhost) [hellodb]> select *from students where age > (select name,age from teachers order by age desc limit 1);
ERROR 1241 (21000): Operand should contain 1 column(s)
08:39:39(root@localhost) [hellodb]> select name,age from teachers order by age desc limit 1;
+---------------+-----+
| name | age |
+---------------+-----+
| Zhang Sanfeng | 94 |
+---------------+-----+
1 row in set (0.00 sec)

08:39:44(root@localhost) [hellodb]> select *from students where age > (select name,age from teachers order by age desc limit 1);
ERROR 1241 (21000): Operand should contain 1 column(s)

2、 用于IN中的子查询:子查询应该单独查询并返回一个或多个值重新构成列表

SELECT Name,Age FROM students WHERE Age IN (SELECT Age FROM teachers);

范例:

08:47:03(root@localhost) [hellodb]> update students set age=45 where stuid=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

08:47:20(root@localhost) [hellodb]> update students set age=77 where stuid=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

08:47:25(root@localhost) [hellodb]> SELECT Name,Age FROM students WHERE Age IN (SELECT Age FROM teachers);
+-------------+-----+
| Name | Age |
+-------------+-----+
| Shi Zhongyu | 45 |
| Xie Yanke | 77 |
+-------------+-----+
2 rows in set (0.00 sec)

3、用于EXISTS 和 Not EXISTS

有点绕……

参考链接:https://dev.mysql.com/doc/refman/8.0/en/exists-and-not-exists-subqueries.html

EXISTS(包括 NOT EXISTS )子句的返回值是一个BOOL值。 EXISTS 内部有一个子查询语句(SELECT ... FROM...), 将其称为EXIST的内查询语句。其内查询语句返回一个结果集。 EXISTS子句根据其内查询语句的结果集空或者非空,返回一个布尔值。将外查询表的每一行,代入内查询作为检验,如果内查询返回的结果为非空值,则EXISTS子句返回TRUE,外查询的这一行数据便可作为外查询的结果行返回,否则不能作为结果

MariaDB [hellodb]> select * from students s where  EXISTS (select * from teachers t where s.teacherid=t.tid);
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name       | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
|     1 | Shi Zhongyu |  22 | M     |       2 |         3 |
|     4 | Ding Dian   |  32 | M     |       4 |         4 |
|     5 | Yu Yutong   |  26 | M     |       3 |         1 |
+-------+-------------+-----+--------+---------+-----------+

#说明:
1EXISTS (NOT EXISTS) 用在 where之后,且后面紧跟子查询语句(带括号)
2EXISTS (NOT EXISTS) 只关心子查询有没有结果,并不关心子查询的结果具体是什么
3、上述语句把students的记录逐条代入到Exists后面的子查询中,如果子查询结果集不为空,即说明存在,那么这条students的记录出现在最终结果集,否则被排除;


MariaDB [hellodb]> select * from students s where NOT EXISTS (select * from teachers t where s.teacherid=t.tid);
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name         | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
|     2 | Shi Potian   |  22 | M     |       1 |         7 |
|     3 | Xie Yanke     |  53 | M     |       2 |        16 |
|     6 | Shi Qing     |  46 | M     |       5 |      NULL |
|     7 | Xi Ren       |  19 | F     |       3 |      NULL |
|     8 | Lin Daiyu     |  17 | F     |       7 |      NULL |
|     9 | Ren Yingying |  20 | F     |       6 |      NULL |
|    10 | Yue Lingshan |  19 | F     |       3 |      NULL |
|    11 | Yuan Chengzhi |  23 | M     |       6 |      NULL |
|    12 | Wen Qingqing |  19 | F     |       1 |      NULL |
|    13 | Tian Boguang |  33 | M     |       2 |      NULL |
|    14 | Lu Wushuang   |  17 | F     |       3 |      NULL |
|    15 | Duan Yu       |  19 | M     |       4 |      NULL |
|    16 | Xu Zhu       |  21 | M     |       1 |      NULL |
|    17 | Lin Chong     |  25 | M     |       4 |      NULL |
|    18 | Hua Rong     |  23 | M     |       7 |      NULL |
|    19 | Xue Baochai   |  18 | F     |       6 |      NULL |
|    20 | Diao Chan     |  19 | F     |       7 |      NULL |
|    21 | Huang Yueying |  22 | F     |       6 |      NULL |
|    22 | Xiao Qiao     |  20 | F     |       1 |      NULL |
|    23 | Ma Chao       |  23 | M     |       4 |      NULL |
|    24 | Xu Xian       |  27 | M     |    NULL |      NULL |
|    25 | Sun Dasheng   | 100 | M     |    NULL |      NULL |
+-------+---------------+-----+--------+---------+-----------+
22 rows in set (0.001 sec)

4、用于FROM子句中的子查询

使用格式:

SELECT tb_alias.col1,... FROM (SELECT clause) AS tb_alias WHERE Clause;

范例:

09:19:22(root@localhost) [hellodb]> select * from students where age>30;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 45 | M | 2 | 3 |
| 3 | Xie Yanke | 77 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+--------------+-----+--------+---------+-----------+
6 rows in set (0.00 sec)

09:19:42(root@localhost) [hellodb]> select name,age from (select * from students where age>30) old_students;
+--------------+-----+
| name | age |
+--------------+-----+
| Shi Zhongyu | 45 |
| Xie Yanke | 77 |
| Ding Dian | 32 |
| Shi Qing | 46 |
| Tian Boguang | 33 |
| Sun Dasheng | 100 |
+--------------+-----+
6 rows in set (0.00 sec)


09:20:32(root@localhost) [hellodb]> SELECT s.aage,s.ClassID FROM (SELECT avg(Age) AS aage,ClassID FROM students
-> WHERE ClassID IS NOT NULL GROUP BY ClassID) AS s WHERE s.aage>30;
+---------+---------+
| aage | ClassID |
+---------+---------+
| 51.6667 | 2 |
| 46.0000 | 5 |
+---------+---------+
2 rows in set (0.00 sec)
  • 范例:子查询用于更新表
09:22:55(root@localhost) [hellodb]> select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)

09:28:10(root@localhost) [hellodb]> update teachers set age=(select avg(age) from students) where tid=4;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

09:28:57(root@localhost) [hellodb]> select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 29 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)
联合查询:UNION
SELECT Name,Age FROM students UNION SELECT Name,Age FROM teachers;
  • 范例:

一般是要对应好字段数量,及字段类型,否则语法没错,但没啥实际意义。

MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)

MariaDB [hellodb]> select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)



MariaDB [hellodb]> select *from teachers union select stuid,name,age,gender from students;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 1 | Shi Zhongyu | 22 | M |
| 2 | Shi Potian | 22 | M |
| 3 | Xie Yanke | 53 | M |
| 4 | Ding Dian | 32 | M |
| 5 | Yu Yutong | 26 | M |
| 6 | Shi Qing | 46 | M |
| 7 | Xi Ren | 19 | F |
| 8 | Lin Daiyu | 17 | F |
| 9 | Ren Yingying | 20 | F |
| 10 | Yue Lingshan | 19 | F |
| 11 | Yuan Chengzhi | 23 | M |
| 12 | Wen Qingqing | 19 | F |
| 13 | Tian Boguang | 33 | M |
| 14 | Lu Wushuang | 17 | F |
| 15 | Duan Yu | 19 | M |
| 16 | Xu Zhu | 21 | M |
| 17 | Lin Chong | 25 | M |
| 18 | Hua Rong | 23 | M |
| 19 | Xue Baochai | 18 | F |
| 20 | Diao Chan | 19 | F |
| 21 | Huang Yueying | 22 | F |
| 22 | Xiao Qiao | 20 | F |
| 23 | Ma Chao | 23 | M |
| 24 | Xu Xian | 27 | M |
| 25 | Sun Dasheng | 100 | M |
+-----+---------------+-----+--------+
29 rows in set (0.00 sec)



##没啥实际意义……
MariaDB [hellodb]> select *from teachers union select name,stuid,age,gender from students;
+---------------+---------------+-----+--------+
| TID | Name | Age | Gender |
+---------------+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| Shi Zhongyu | 1 | 22 | M |
| Shi Potian | 2 | 22 | M |
| Xie Yanke | 3 | 53 | M |
| Ding Dian | 4 | 32 | M |
| Yu Yutong | 5 | 26 | M |
| Shi Qing | 6 | 46 | M |
| Xi Ren | 7 | 19 | F |
| Lin Daiyu | 8 | 17 | F |
| Ren Yingying | 9 | 20 | F |
| Yue Lingshan | 10 | 19 | F |
| Yuan Chengzhi | 11 | 23 | M |
| Wen Qingqing | 12 | 19 | F |
| Tian Boguang | 13 | 33 | M |
| Lu Wushuang | 14 | 17 | F |
| Duan Yu | 15 | 19 | M |
| Xu Zhu | 16 | 21 | M |
| Lin Chong | 17 | 25 | M |
| Hua Rong | 18 | 23 | M |
| Xue Baochai | 19 | 18 | F |
| Diao Chan | 20 | 19 | F |
| Huang Yueying | 21 | 22 | F |
| Xiao Qiao | 22 | 20 | F |
| Ma Chao | 23 | 23 | M |
| Xu Xian | 24 | 27 | M |
| Sun Dasheng | 25 | 100 | M |
+---------------+---------------+-----+--------+
29 rows in set (0.00 sec)

MariaDB [hellodb]>
  • 范例:2个表union会产生什么问题?(去重)
##创建新表
MariaDB [hellodb]> create table teachers2 select *from teachers;
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0

MariaDB [hellodb]> select *from teachers2;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)

##修改2个字段
MariaDB [hellodb]> update teachers2 set name='mage' where tid=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

MariaDB [hellodb]> update teachers2 set name='wang' where tid=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0


##查询
MariaDB [hellodb]> select *from teachers2;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | mage | 45 | M |
| 2 | wang | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)


#union操作
MariaDB [hellodb]> selec
+-----+---------------+-
| TID | Name |
+-----+---------------+-
| 1 | mage |
| 2 | wang |
| 3 | Miejue Shitai |
| 4 | Lin Chaoying |
| 1 | Song Jiang |
| 2 | Zhang Sanfeng |
+-----+---------------+-
6 rows in set (0.01 sec)
##可以看到,用这种小技巧也可以实现简单的去重操作;



##那如何去重呢?
MariaDB [hellodb]> create table teachers3 select *from teachers2 union select *from teachers;
Query OK, 6 rows affected (0.01 sec)
Records: 6 Duplicates: 0 Warnings: 0

MariaDB [hellodb]> select *from teachers3;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | mage | 45 | M |
| 2 | wang | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
+-----+---------------+-----+--------+
6 rows in set (0.00 sec)
  • 范例:能不能不去重呢?
MariaDB [hellodb]> select *from teachers2 union all select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | mage | 45 | M |
| 2 | wang | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
8 rows in set (0.00 sec)
  • 范例:3个语句的union
MariaDB [hellodb]> select *from teachers2 union all select *from teachers union select stuid,name,age,gender from students;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | mage | 45 | M |
| 2 | wang | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 1 | Shi Zhongyu | 22 | M |
| 2 | Shi Potian | 22 | M |
| 3 | Xie Yanke | 53 | M |
| 4 | Ding Dian | 32 | M |
| 5 | Yu Yutong | 26 | M |
| 6 | Shi Qing | 46 | M |
| 7 | Xi Ren | 19 | F |
| 8 | Lin Daiyu | 17 | F |
| 9 | Ren Yingying | 20 | F |
| 10 | Yue Lingshan | 19 | F |
| 11 | Yuan Chengzhi | 23 | M |
| 12 | Wen Qingqing | 19 | F |
| 13 | Tian Boguang | 33 | M |
| 14 | Lu Wushuang | 17 | F |
| 15 | Duan Yu | 19 | M |
| 16 | Xu Zhu | 21 | M |
| 17 | Lin Chong | 25 | M |
| 18 | Hua Rong | 23 | M |
| 19 | Xue Baochai | 18 | F |
| 20 | Diao Chan | 19 | F |
| 21 | Huang Yueying | 22 | F |
| 22 | Xiao Qiao | 20 | F |
| 23 | Ma Chao | 23 | M |
| 24 | Xu Xian | 27 | M |
| 25 | Sun Dasheng | 100 | M |
+-----+---------------+-----+--------+
31 rows in set (0.00 sec)
交叉连接

2张表横向连接,交叉组合。

即笛卡尔乘积,"雨露均沾",利用 cross join实现

交叉连接通常结果意义不是很大,用的场景不是很多。它还有一个巨大的缺点,两张表明明是小表,但合并后却成为一个巨大的表。所以,cross join在生产里尽可能不要去执行。

  • 范例:交叉连接
 select * from students cross join teachers;
MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)

MariaDB [hellodb]> select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.01 sec)



#会产生4+6=10列数据,25*4=100行数据
MariaDB [hellodb]> select *from students cross join teachers;
+-------+---------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 1 | Song Jiang | 45 | M |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 2 | Zhang Sanfeng | 94 | M |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 4 | Lin Chaoying | 93 | F |
| 2 | Shi Potian | 22 | M | 1 | 7 | 1 | Song Jiang | 45 | M |
| 2 | Shi Potian | 22 | M | 1 | 7 | 2 | Zhang Sanfeng | 94 | M |
| 2 | Shi Potian | 22 | M | 1 | 7 | 3 | Miejue Shitai | 77 | F |
| 2 | Shi Potian | 22 | M | 1 | 7 | 4 | Lin Chaoying | 93 | F |
| 3 | Xie Yanke | 53 | M | 2 | 16 | 1 | Song Jiang | 45 | M |
| 3 | Xie Yanke | 53 | M | 2 | 16 | 2 | Zhang Sanfeng | 94 | M |
| 3 | Xie Yanke | 53 | M | 2 | 16 | 3 | Miejue Shitai | 77 | F |
| 3 | Xie Yanke | 53 | M | 2 | 16 | 4 | Lin Chaoying | 93 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 1 | Song Jiang | 45 | M |
| 4 | Ding Dian | 32 | M | 4 | 4 | 2 | Zhang Sanfeng | 94 | M |
| 4 | Ding Dian | 32 | M | 4 | 4 | 3 | Miejue Shitai | 77 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 93 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 2 | Zhang Sanfeng | 94 | M |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 3 | Miejue Shitai | 77 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 4 | Lin Chaoying | 93 | F |
| 6 | Shi Qing | 46 | M | 5 | NULL | 1 | Song Jiang | 45 | M |
| 6 | Shi Qing | 46 | M | 5 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 6 | Shi Qing | 46 | M | 5 | NULL | 3 | Miejue Shitai | 77 | F |
| 6 | Shi Qing | 46 | M | 5 | NULL | 4 | Lin Chaoying | 93 | F |
| 7 | Xi Ren | 19 | F | 3 | NULL | 1 | Song Jiang | 45 | M |
| 7 | Xi Ren | 19 | F | 3 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 7 | Xi Ren | 19 | F | 3 | NULL | 3 | Miejue Shitai | 77 | F |
| 7 | Xi Ren | 19 | F | 3 | NULL | 4 | Lin Chaoying | 93 | F |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | 1 | Song Jiang | 45 | M |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | 3 | Miejue Shitai | 77 | F |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | 4 | Lin Chaoying | 93 | F |
| 9 | Ren Yingying | 20 | F | 6 | NULL | 1 | Song Jiang | 45 | M |
| 9 | Ren Yingying | 20 | F | 6 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 9 | Ren Yingying | 20 | F | 6 | NULL | 3 | Miejue Shitai | 77 | F |
| 9 | Ren Yingying | 20 | F | 6 | NULL | 4 | Lin Chaoying | 93 | F |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | 1 | Song Jiang | 45 | M |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | 3 | Miejue Shitai | 77 | F |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | 4 | Lin Chaoying | 93 | F |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | 1 | Song Jiang | 45 | M |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | 3 | Miejue Shitai | 77 | F |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | 4 | Lin Chaoying | 93 | F |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | 1 | Song Jiang | 45 | M |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | 3 | Miejue Shitai | 77 | F |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | 4 | Lin Chaoying | 93 | F |
| 13 | Tian Boguang | 33 | M | 2 | NULL | 1 | Song Jiang | 45 | M |
| 13 | Tian Boguang | 33 | M | 2 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 13 | Tian Boguang | 33 | M | 2 | NULL | 3 | Miejue Shitai | 77 | F |
| 13 | Tian Boguang | 33 | M | 2 | NULL | 4 | Lin Chaoying | 93 | F |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | 1 | Song Jiang | 45 | M |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | 3 | Miejue Shitai | 77 | F |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | 4 | Lin Chaoying | 93 | F |
| 15 | Duan Yu | 19 | M | 4 | NULL | 1 | Song Jiang | 45 | M |
| 15 | Duan Yu | 19 | M | 4 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 15 | Duan Yu | 19 | M | 4 | NULL | 3 | Miejue Shitai | 77 | F |
| 15 | Duan Yu | 19 | M | 4 | NULL | 4 | Lin Chaoying | 93 | F |
| 16 | Xu Zhu | 21 | M | 1 | NULL | 1 | Song Jiang | 45 | M |
| 16 | Xu Zhu | 21 | M | 1 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 16 | Xu Zhu | 21 | M | 1 | NULL | 3 | Miejue Shitai | 77 | F |
| 16 | Xu Zhu | 21 | M | 1 | NULL | 4 | Lin Chaoying | 93 | F |
| 17 | Lin Chong | 25 | M | 4 | NULL | 1 | Song Jiang | 45 | M |
| 17 | Lin Chong | 25 | M | 4 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 17 | Lin Chong | 25 | M | 4 | NULL | 3 | Miejue Shitai | 77 | F |
| 17 | Lin Chong | 25 | M | 4 | NULL | 4 | Lin Chaoying | 93 | F |
| 18 | Hua Rong | 23 | M | 7 | NULL | 1 | Song Jiang | 45 | M |
| 18 | Hua Rong | 23 | M | 7 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 18 | Hua Rong | 23 | M | 7 | NULL | 3 | Miejue Shitai | 77 | F |
| 18 | Hua Rong | 23 | M | 7 | NULL | 4 | Lin Chaoying | 93 | F |
| 19 | Xue Baochai | 18 | F | 6 | NULL | 1 | Song Jiang | 45 | M |
| 19 | Xue Baochai | 18 | F | 6 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 19 | Xue Baochai | 18 | F | 6 | NULL | 3 | Miejue Shitai | 77 | F |
| 19 | Xue Baochai | 18 | F | 6 | NULL | 4 | Lin Chaoying | 93 | F |
| 20 | Diao Chan | 19 | F | 7 | NULL | 1 | Song Jiang | 45 | M |
| 20 | Diao Chan | 19 | F | 7 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 20 | Diao Chan | 19 | F | 7 | NULL | 3 | Miejue Shitai | 77 | F |
| 20 | Diao Chan | 19 | F | 7 | NULL | 4 | Lin Chaoying | 93 | F |
| 21 | Huang Yueying | 22 | F | 6 | NULL | 1 | Song Jiang | 45 | M |
| 21 | Huang Yueying | 22 | F | 6 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 21 | Huang Yueying | 22 | F | 6 | NULL | 3 | Miejue Shitai | 77 | F |
| 21 | Huang Yueying | 22 | F | 6 | NULL | 4 | Lin Chaoying | 93 | F |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | 1 | Song Jiang | 45 | M |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | 3 | Miejue Shitai | 77 | F |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | 4 | Lin Chaoying | 93 | F |
| 23 | Ma Chao | 23 | M | 4 | NULL | 1 | Song Jiang | 45 | M |
| 23 | Ma Chao | 23 | M | 4 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 23 | Ma Chao | 23 | M | 4 | NULL | 3 | Miejue Shitai | 77 | F |
| 23 | Ma Chao | 23 | M | 4 | NULL | 4 | Lin Chaoying | 93 | F |
| 24 | Xu Xian | 27 | M | NULL | NULL | 1 | Song Jiang | 45 | M |
| 24 | Xu Xian | 27 | M | NULL | NULL | 2 | Zhang Sanfeng | 94 | M |
| 24 | Xu Xian | 27 | M | NULL | NULL | 3 | Miejue Shitai | 77 | F |
| 24 | Xu Xian | 27 | M | NULL | NULL | 4 | Lin Chaoying | 93 | F |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | 1 | Song Jiang | 45 | M |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | 2 | Zhang Sanfeng | 94 | M |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | 3 | Miejue Shitai | 77 | F |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | 4 | Lin Chaoying | 93 | F |
+-------+---------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
100 rows in set (0.01 sec)



##报错:2张表里都有name字段,所以报错了
MariaDB [hellodb]> select stuid,name,age,tid,name,age from students cross join teachers;
ERROR 1052 (23000): Column 'name' in field list is ambiguous


##
MariaDB [hellodb]> select stuid,students.name,students.age,tid,teachers.name,teachers.age from students cross join teachers;
##这里给表起个别名,更简洁。
MariaDB [hellodb]> select stuid,s.name,s.age,tid,t.name,t.age from students s cross join teachers t;
+-------+---------------+-----+-----+---------------+-----+
| stuid | name | age | tid | name | age |
+-------+---------------+-----+-----+---------------+-----+
| 1 | Shi Zhongyu | 22 | 1 | Song Jiang | 45 |
| 1 | Shi Zhongyu | 22 | 2 | Zhang Sanfeng | 94 |
| 1 | Shi Zhongyu | 22 | 3 | Miejue Shitai | 77 |
| 1 | Shi Zhongyu | 22 | 4 | Lin Chaoying | 93 |
| 2 | Shi Potian | 22 | 1 | Song Jiang | 45 |
| 2 | Shi Potian | 22 | 2 | Zhang Sanfeng | 94 |
| 2 | Shi Potian | 22 | 3 | Miejue Shitai | 77 |
| 2 | Shi Potian | 22 | 4 | Lin Chaoying | 93 |
| 3 | Xie Yanke | 53 | 1 | Song Jiang | 45 |
| 3 | Xie Yanke | 53 | 2 | Zhang Sanfeng | 94 |
| 3 | Xie Yanke | 53 | 3 | Miejue Shitai | 77 |
| 3 | Xie Yanke | 53 | 4 | Lin Chaoying | 93 |
| 4 | Ding Dian | 32 | 1 | Song Jiang | 45 |
| 4 | Ding Dian | 32 | 2 | Zhang Sanfeng | 94 |
| 4 | Ding Dian | 32 | 3 | Miejue Shitai | 77 |
| 4 | Ding Dian | 32 | 4 | Lin Chaoying | 93 |
| 5 | Yu Yutong | 26 | 1 | Song Jiang | 45 |
| 5 | Yu Yutong | 26 | 2 | Zhang Sanfeng | 94 |
| 5 | Yu Yutong | 26 | 3 | Miejue Shitai | 77 |
| 5 | Yu Yutong | 26 | 4 | Lin Chaoying | 93 |
| 6 | Shi Qing | 46 | 1 | Song Jiang | 45 |
| 6 | Shi Qing | 46 | 2 | Zhang Sanfeng | 94 |
| 6 | Shi Qing | 46 | 3 | Miejue Shitai | 77 |
| 6 | Shi Qing | 46 | 4 | Lin Chaoying | 93 |
| 7 | Xi Ren | 19 | 1 | Song Jiang | 45 |
| 7 | Xi Ren | 19 | 2 | Zhang Sanfeng | 94 |
| 7 | Xi Ren | 19 | 3 | Miejue Shitai | 77 |
| 7 | Xi Ren | 19 | 4 | Lin Chaoying | 93 |
| 8 | Lin Daiyu | 17 | 1 | Song Jiang | 45 |
| 8 | Lin Daiyu | 17 | 2 | Zhang Sanfeng | 94 |
| 8 | Lin Daiyu | 17 | 3 | Miejue Shitai | 77 |
| 8 | Lin Daiyu | 17 | 4 | Lin Chaoying | 93 |
| 9 | Ren Yingying | 20 | 1 | Song Jiang | 45 |
| 9 | Ren Yingying | 20 | 2 | Zhang Sanfeng | 94 |
| 9 | Ren Yingying | 20 | 3 | Miejue Shitai | 77 |
| 9 | Ren Yingying | 20 | 4 | Lin Chaoying | 93 |
| 10 | Yue Lingshan | 19 | 1 | Song Jiang | 45 |
| 10 | Yue Lingshan | 19 | 2 | Zhang Sanfeng | 94 |
| 10 | Yue Lingshan | 19 | 3 | Miejue Shitai | 77 |
| 10 | Yue Lingshan | 19 | 4 | Lin Chaoying | 93 |
| 11 | Yuan Chengzhi | 23 | 1 | Song Jiang | 45 |
| 11 | Yuan Chengzhi | 23 | 2 | Zhang Sanfeng | 94 |
| 11 | Yuan Chengzhi | 23 | 3 | Miejue Shitai | 77 |
| 11 | Yuan Chengzhi | 23 | 4 | Lin Chaoying | 93 |
| 12 | Wen Qingqing | 19 | 1 | Song Jiang | 45 |
| 12 | Wen Qingqing | 19 | 2 | Zhang Sanfeng | 94 |
| 12 | Wen Qingqing | 19 | 3 | Miejue Shitai | 77 |
| 12 | Wen Qingqing | 19 | 4 | Lin Chaoying | 93 |
| 13 | Tian Boguang | 33 | 1 | Song Jiang | 45 |
| 13 | Tian Boguang | 33 | 2 | Zhang Sanfeng | 94 |
| 13 | Tian Boguang | 33 | 3 | Miejue Shitai | 77 |
| 13 | Tian Boguang | 33 | 4 | Lin Chaoying | 93 |
| 14 | Lu Wushuang | 17 | 1 | Song Jiang | 45 |
| 14 | Lu Wushuang | 17 | 2 | Zhang Sanfeng | 94 |
| 14 | Lu Wushuang | 17 | 3 | Miejue Shitai | 77 |
| 14 | Lu Wushuang | 17 | 4 | Lin Chaoying | 93 |
| 15 | Duan Yu | 19 | 1 | Song Jiang | 45 |
| 15 | Duan Yu | 19 | 2 | Zhang Sanfeng | 94 |
| 15 | Duan Yu | 19 | 3 | Miejue Shitai | 77 |
| 15 | Duan Yu | 19 | 4 | Lin Chaoying | 93 |
| 16 | Xu Zhu | 21 | 1 | Song Jiang | 45 |
| 16 | Xu Zhu | 21 | 2 | Zhang Sanfeng | 94 |
| 16 | Xu Zhu | 21 | 3 | Miejue Shitai | 77 |
| 16 | Xu Zhu | 21 | 4 | Lin Chaoying | 93 |
| 17 | Lin Chong | 25 | 1 | Song Jiang | 45 |
| 17 | Lin Chong | 25 | 2 | Zhang Sanfeng | 94 |
| 17 | Lin Chong | 25 | 3 | Miejue Shitai | 77 |
| 17 | Lin Chong | 25 | 4 | Lin Chaoying | 93 |
| 18 | Hua Rong | 23 | 1 | Song Jiang | 45 |
| 18 | Hua Rong | 23 | 2 | Zhang Sanfeng | 94 |
| 18 | Hua Rong | 23 | 3 | Miejue Shitai | 77 |
| 18 | Hua Rong | 23 | 4 | Lin Chaoying | 93 |
| 19 | Xue Baochai | 18 | 1 | Song Jiang | 45 |
| 19 | Xue Baochai | 18 | 2 | Zhang Sanfeng | 94 |
| 19 | Xue Baochai | 18 | 3 | Miejue Shitai | 77 |
| 19 | Xue Baochai | 18 | 4 | Lin Chaoying | 93 |
| 20 | Diao Chan | 19 | 1 | Song Jiang | 45 |
| 20 | Diao Chan | 19 | 2 | Zhang Sanfeng | 94 |
| 20 | Diao Chan | 19 | 3 | Miejue Shitai | 77 |
| 20 | Diao Chan | 19 | 4 | Lin Chaoying | 93 |
| 21 | Huang Yueying | 22 | 1 | Song Jiang | 45 |
| 21 | Huang Yueying | 22 | 2 | Zhang Sanfeng | 94 |
| 21 | Huang Yueying | 22 | 3 | Miejue Shitai | 77 |
| 21 | Huang Yueying | 22 | 4 | Lin Chaoying | 93 |
| 22 | Xiao Qiao | 20 | 1 | Song Jiang | 45 |
| 22 | Xiao Qiao | 20 | 2 | Zhang Sanfeng | 94 |
| 22 | Xiao Qiao | 20 | 3 | Miejue Shitai | 77 |
| 22 | Xiao Qiao | 20 | 4 | Lin Chaoying | 93 |
| 23 | Ma Chao | 23 | 1 | Song Jiang | 45 |
| 23 | Ma Chao | 23 | 2 | Zhang Sanfeng | 94 |
| 23 | Ma Chao | 23 | 3 | Miejue Shitai | 77 |
| 23 | Ma Chao | 23 | 4 | Lin Chaoying | 93 |
| 24 | Xu Xian | 27 | 1 | Song Jiang | 45 |
| 24 | Xu Xian | 27 | 2 | Zhang Sanfeng | 94 |
| 24 | Xu Xian | 27 | 3 | Miejue Shitai | 77 |
| 24 | Xu Xian | 27 | 4 | Lin Chaoying | 93 |
| 25 | Sun Dasheng | 100 | 1 | Song Jiang | 45 |
| 25 | Sun Dasheng | 100 | 2 | Zhang Sanfeng | 94 |
| 25 | Sun Dasheng | 100 | 3 | Miejue Shitai | 77 |
| 25 | Sun Dasheng | 100 | 4 | Lin Chaoying | 93 |
+-------+---------------+-----+-----+---------------+-----+
100 rows in set (0.00 sec)


##再次修改:
MariaDB [hellodb]> select stuid,s.name 学生姓名,s.age 学生年龄,tid,t.name 老师姓名,t.age 老师年龄 from students s cross join teachers t;
+-------+---------------+--------------+-----+---------------+--------------+
| stuid | 学生姓名 | 学生年龄 | tid | 老师姓名 | 老师年龄 |
+-------+---------------+--------------+-----+---------------+--------------+
| 1 | Shi Zhongyu | 22 | 1 | Song Jiang | 45 |
| 1 | Shi Zhongyu | 22 | 2 | Zhang Sanfeng | 94 |
| 1 | Shi Zhongyu | 22 | 3 | Miejue Shitai | 77 |
| 1 | Shi Zhongyu | 22 | 4 | Lin Chaoying | 93 |
| 2 | Shi Potian | 22 | 1 | Song Jiang | 45 |
| 2 | Shi Potian | 22 | 2 | Zhang Sanfeng | 94 |
| 2 | Shi Potian | 22 | 3 | Miejue Shitai | 77 |
| 2 | Shi Potian | 22 | 4 | Lin Chaoying | 93 |
| 3 | Xie Yanke | 53 | 1 | Song Jiang | 45 |
| 3 | Xie Yanke | 53 | 2 | Zhang Sanfeng | 94 |
| 3 | Xie Yanke | 53 | 3 | Miejue Shitai | 77 |
| 3 | Xie Yanke | 53 | 4 | Lin Chaoying | 93 |
| 4 | Ding Dian | 32 | 1 | Song Jiang | 45 |
| 4 | Ding Dian | 32 | 2 | Zhang Sanfeng | 94 |
| 4 | Ding Dian | 32 | 3 | Miejue Shitai | 77 |
| 4 | Ding Dian | 32 | 4 | Lin Chaoying | 93 |
| 5 | Yu Yutong | 26 | 1 | Song Jiang | 45 |
| 5 | Yu Yutong | 26 | 2 | Zhang Sanfeng | 94 |
| 5 | Yu Yutong | 26 | 3 | Miejue Shitai | 77 |
| 5 | Yu Yutong | 26 | 4 | Lin Chaoying | 93 |
| 6 | Shi Qing | 46 | 1 | Song Jiang | 45 |
| 6 | Shi Qing | 46 | 2 | Zhang Sanfeng | 94 |
| 6 | Shi Qing | 46 | 3 | Miejue Shitai | 77 |
| 6 | Shi Qing | 46 | 4 | Lin Chaoying | 93 |
| 7 | Xi Ren | 19 | 1 | Song Jiang | 45 |
| 7 | Xi Ren | 19 | 2 | Zhang Sanfeng | 94 |
| 7 | Xi Ren | 19 | 3 | Miejue Shitai | 77 |
| 7 | Xi Ren | 19 | 4 | Lin Chaoying | 93 |
| 8 | Lin Daiyu | 17 | 1 | Song Jiang | 45 |
| 8 | Lin Daiyu | 17 | 2 | Zhang Sanfeng | 94 |
| 8 | Lin Daiyu | 17 | 3 | Miejue Shitai | 77 |
| 8 | Lin Daiyu | 17 | 4 | Lin Chaoying | 93 |
| 9 | Ren Yingying | 20 | 1 | Song Jiang | 45 |
| 9 | Ren Yingying | 20 | 2 | Zhang Sanfeng | 94 |
| 9 | Ren Yingying | 20 | 3 | Miejue Shitai | 77 |
| 9 | Ren Yingying | 20 | 4 | Lin Chaoying | 93 |
| 10 | Yue Lingshan | 19 | 1 | Song Jiang | 45 |
| 10 | Yue Lingshan | 19 | 2 | Zhang Sanfeng | 94 |
| 10 | Yue Lingshan | 19 | 3 | Miejue Shitai | 77 |
| 10 | Yue Lingshan | 19 | 4 | Lin Chaoying | 93 |
| 11 | Yuan Chengzhi | 23 | 1 | Song Jiang | 45 |
| 11 | Yuan Chengzhi | 23 | 2 | Zhang Sanfeng | 94 |
| 11 | Yuan Chengzhi | 23 | 3 | Miejue Shitai | 77 |
| 11 | Yuan Chengzhi | 23 | 4 | Lin Chaoying | 93 |
| 12 | Wen Qingqing | 19 | 1 | Song Jiang | 45 |
| 12 | Wen Qingqing | 19 | 2 | Zhang Sanfeng | 94 |
| 12 | Wen Qingqing | 19 | 3 | Miejue Shitai | 77 |
| 12 | Wen Qingqing | 19 | 4 | Lin Chaoying | 93 |
| 13 | Tian Boguang | 33 | 1 | Song Jiang | 45 |
| 13 | Tian Boguang | 33 | 2 | Zhang Sanfeng | 94 |
| 13 | Tian Boguang | 33 | 3 | Miejue Shitai | 77 |
| 13 | Tian Boguang | 33 | 4 | Lin Chaoying | 93 |
| 14 | Lu Wushuang | 17 | 1 | Song Jiang | 45 |
| 14 | Lu Wushuang | 17 | 2 | Zhang Sanfeng | 94 |
| 14 | Lu Wushuang | 17 | 3 | Miejue Shitai | 77 |
| 14 | Lu Wushuang | 17 | 4 | Lin Chaoying | 93 |
| 15 | Duan Yu | 19 | 1 | Song Jiang | 45 |
| 15 | Duan Yu | 19 | 2 | Zhang Sanfeng | 94 |
| 15 | Duan Yu | 19 | 3 | Miejue Shitai | 77 |
| 15 | Duan Yu | 19 | 4 | Lin Chaoying | 93 |
| 16 | Xu Zhu | 21 | 1 | Song Jiang | 45 |
| 16 | Xu Zhu | 21 | 2 | Zhang Sanfeng | 94 |
| 16 | Xu Zhu | 21 | 3 | Miejue Shitai | 77 |
| 16 | Xu Zhu | 21 | 4 | Lin Chaoying | 93 |
| 17 | Lin Chong | 25 | 1 | Song Jiang | 45 |
| 17 | Lin Chong | 25 | 2 | Zhang Sanfeng | 94 |
| 17 | Lin Chong | 25 | 3 | Miejue Shitai | 77 |
| 17 | Lin Chong | 25 | 4 | Lin Chaoying | 93 |
| 18 | Hua Rong | 23 | 1 | Song Jiang | 45 |
| 18 | Hua Rong | 23 | 2 | Zhang Sanfeng | 94 |
| 18 | Hua Rong | 23 | 3 | Miejue Shitai | 77 |
| 18 | Hua Rong | 23 | 4 | Lin Chaoying | 93 |
| 19 | Xue Baochai | 18 | 1 | Song Jiang | 45 |
| 19 | Xue Baochai | 18 | 2 | Zhang Sanfeng | 94 |
| 19 | Xue Baochai | 18 | 3 | Miejue Shitai | 77 |
| 19 | Xue Baochai | 18 | 4 | Lin Chaoying | 93 |
| 20 | Diao Chan | 19 | 1 | Song Jiang | 45 |
| 20 | Diao Chan | 19 | 2 | Zhang Sanfeng | 94 |
| 20 | Diao Chan | 19 | 3 | Miejue Shitai | 77 |
| 20 | Diao Chan | 19 | 4 | Lin Chaoying | 93 |
| 21 | Huang Yueying | 22 | 1 | Song Jiang | 45 |
| 21 | Huang Yueying | 22 | 2 | Zhang Sanfeng | 94 |
| 21 | Huang Yueying | 22 | 3 | Miejue Shitai | 77 |
| 21 | Huang Yueying | 22 | 4 | Lin Chaoying | 93 |
| 22 | Xiao Qiao | 20 | 1 | Song Jiang | 45 |
| 22 | Xiao Qiao | 20 | 2 | Zhang Sanfeng | 94 |
| 22 | Xiao Qiao | 20 | 3 | Miejue Shitai | 77 |
| 22 | Xiao Qiao | 20 | 4 | Lin Chaoying | 93 |
| 23 | Ma Chao | 23 | 1 | Song Jiang | 45 |
| 23 | Ma Chao | 23 | 2 | Zhang Sanfeng | 94 |
| 23 | Ma Chao | 23 | 3 | Miejue Shitai | 77 |
| 23 | Ma Chao | 23 | 4 | Lin Chaoying | 93 |
| 24 | Xu Xian | 27 | 1 | Song Jiang | 45 |
| 24 | Xu Xian | 27 | 2 | Zhang Sanfeng | 94 |
| 24 | Xu Xian | 27 | 3 | Miejue Shitai | 77 |
| 24 | Xu Xian | 27 | 4 | Lin Chaoying | 93 |
| 25 | Sun Dasheng | 100 | 1 | Song Jiang | 45 |
| 25 | Sun Dasheng | 100 | 2 | Zhang Sanfeng | 94 |
| 25 | Sun Dasheng | 100 | 3 | Miejue Shitai | 77 |
| 25 | Sun Dasheng | 100 | 4 | Lin Chaoying | 93 |
+-------+---------------+--------------+-----+---------------+--------------+
100 rows in set (0.00 sec)
内连接

两张表交叉连接之后,符合条件的信息。

内连接不分谁在前,谁在后。但左、右外连接,得分左右了。

image-20240504095508951

  • 范例:内连接
#内连接inner join
MariaDB [hellodb]> select *from students inner join teachers on students.teacherid=teachers.tid;
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 93 | F |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
3 rows in set (0.00 sec)
MariaDB [hellodb]> select *from students s inner join teachers t on s.teacherid=t.tid;
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 93 | F |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
3 rows in set (0.00 sec)



##另一个逻辑:哈哈(男女搭配,干活不累)
MariaDB [hellodb]> select *from students s inner join teachers t on s.gender != t.gender;
MariaDB [hellodb]> select *from students s inner join teachers t on s.gender='m' and t.gender='F' or s.gender='F' and t.gender='M' ;
+-------+---------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 4 | Lin Chaoying | 93 | F |
| 2 | Shi Potian | 22 | M | 1 | 7 | 3 | Miejue Shitai | 77 | F |
| 2 | Shi Potian | 22 | M | 1 | 7 | 4 | Lin Chaoying | 93 | F |
| 3 | Xie Yanke | 53 | M | 2 | 16 | 3 | Miejue Shitai | 77 | F |
| 3 | Xie Yanke | 53 | M | 2 | 16 | 4 | Lin Chaoying | 93 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 3 | Miejue Shitai | 77 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 93 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 3 | Miejue Shitai | 77 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 4 | Lin Chaoying | 93 | F |
| 6 | Shi Qing | 46 | M | 5 | NULL | 3 | Miejue Shitai | 77 | F |
| 6 | Shi Qing | 46 | M | 5 | NULL | 4 | Lin Chaoying | 93 | F |
| 7 | Xi Ren | 19 | F | 3 | NULL | 1 | Song Jiang | 45 | M |
| 7 | Xi Ren | 19 | F | 3 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | 1 | Song Jiang | 45 | M |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 9 | Ren Yingying | 20 | F | 6 | NULL | 1 | Song Jiang | 45 | M |
| 9 | Ren Yingying | 20 | F | 6 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | 1 | Song Jiang | 45 | M |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | 3 | Miejue Shitai | 77 | F |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | 4 | Lin Chaoying | 93 | F |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | 1 | Song Jiang | 45 | M |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 13 | Tian Boguang | 33 | M | 2 | NULL | 3 | Miejue Shitai | 77 | F |
| 13 | Tian Boguang | 33 | M | 2 | NULL | 4 | Lin Chaoying | 93 | F |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | 1 | Song Jiang | 45 | M |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 15 | Duan Yu | 19 | M | 4 | NULL | 3 | Miejue Shitai | 77 | F |
| 15 | Duan Yu | 19 | M | 4 | NULL | 4 | Lin Chaoying | 93 | F |
| 16 | Xu Zhu | 21 | M | 1 | NULL | 3 | Miejue Shitai | 77 | F |
| 16 | Xu Zhu | 21 | M | 1 | NULL | 4 | Lin Chaoying | 93 | F |
| 17 | Lin Chong | 25 | M | 4 | NULL | 3 | Miejue Shitai | 77 | F |
| 17 | Lin Chong | 25 | M | 4 | NULL | 4 | Lin Chaoying | 93 | F |
| 18 | Hua Rong | 23 | M | 7 | NULL | 3 | Miejue Shitai | 77 | F |
| 18 | Hua Rong | 23 | M | 7 | NULL | 4 | Lin Chaoying | 93 | F |
| 19 | Xue Baochai | 18 | F | 6 | NULL | 1 | Song Jiang | 45 | M |
| 19 | Xue Baochai | 18 | F | 6 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 20 | Diao Chan | 19 | F | 7 | NULL | 1 | Song Jiang | 45 | M |
| 20 | Diao Chan | 19 | F | 7 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 21 | Huang Yueying | 22 | F | 6 | NULL | 1 | Song Jiang | 45 | M |
| 21 | Huang Yueying | 22 | F | 6 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | 1 | Song Jiang | 45 | M |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | 2 | Zhang Sanfeng | 94 | M |
| 23 | Ma Chao | 23 | M | 4 | NULL | 3 | Miejue Shitai | 77 | F |
| 23 | Ma Chao | 23 | M | 4 | NULL | 4 | Lin Chaoying | 93 | F |
| 24 | Xu Xian | 27 | M | NULL | NULL | 3 | Miejue Shitai | 77 | F |
| 24 | Xu Xian | 27 | M | NULL | NULL | 4 | Lin Chaoying | 93 | F |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | 3 | Miejue Shitai | 77 | F |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | 4 | Lin Chaoying | 93 | F |
+-------+---------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
50 rows in set (0.00 sec)



##过滤部分字段
MariaDB [hellodb]> select s.name 学生姓名,s.age 学生年龄,s.gender 学生性别,t.name 老师姓名,t.age 老师年龄, t.gender 老师性别 from students s inner join teachers t on s.gender <> t.gender;
+---------------+--------------+--------------+---------------+--------------+--------------+
| 学生姓名 | 学生年龄 | 学生性别 | 老师姓名 | 老师年龄 | 老师性别 |
+---------------+--------------+--------------+---------------+--------------+--------------+
| Shi Zhongyu | 22 | M | Miejue Shitai | 77 | F |
| Shi Zhongyu | 22 | M | Lin Chaoying | 93 | F |
| Shi Potian | 22 | M | Miejue Shitai | 77 | F |
| Shi Potian | 22 | M | Lin Chaoying | 93 | F |
| Xie Yanke | 53 | M | Miejue Shitai | 77 | F |
| Xie Yanke | 53 | M | Lin Chaoying | 93 | F |
| Ding Dian | 32 | M | Miejue Shitai | 77 | F |
| Ding Dian | 32 | M | Lin Chaoying | 93 | F |
| Yu Yutong | 26 | M | Miejue Shitai | 77 | F |
| Yu Yutong | 26 | M | Lin Chaoying | 93 | F |
| Shi Qing | 46 | M | Miejue Shitai | 77 | F |
| Shi Qing | 46 | M | Lin Chaoying | 93 | F |
| Xi Ren | 19 | F | Song Jiang | 45 | M |
| Xi Ren | 19 | F | Zhang Sanfeng | 94 | M |
| Lin Daiyu | 17 | F | Song Jiang | 45 | M |
| Lin Daiyu | 17 | F | Zhang Sanfeng | 94 | M |
| Ren Yingying | 20 | F | Song Jiang | 45 | M |
| Ren Yingying | 20 | F | Zhang Sanfeng | 94 | M |
| Yue Lingshan | 19 | F | Song Jiang | 45 | M |
| Yue Lingshan | 19 | F | Zhang Sanfeng | 94 | M |
| Yuan Chengzhi | 23 | M | Miejue Shitai | 77 | F |
| Yuan Chengzhi | 23 | M | Lin Chaoying | 93 | F |
| Wen Qingqing | 19 | F | Song Jiang | 45 | M |
| Wen Qingqing | 19 | F | Zhang Sanfeng | 94 | M |
| Tian Boguang | 33 | M | Miejue Shitai | 77 | F |
| Tian Boguang | 33 | M | Lin Chaoying | 93 | F |
| Lu Wushuang | 17 | F | Song Jiang | 45 | M |
| Lu Wushuang | 17 | F | Zhang Sanfeng | 94 | M |
| Duan Yu | 19 | M | Miejue Shitai | 77 | F |
| Duan Yu | 19 | M | Lin Chaoying | 93 | F |
| Xu Zhu | 21 | M | Miejue Shitai | 77 | F |
| Xu Zhu | 21 | M | Lin Chaoying | 93 | F |
| Lin Chong | 25 | M | Miejue Shitai | 77 | F |
| Lin Chong | 25 | M | Lin Chaoying | 93 | F |
| Hua Rong | 23 | M | Miejue Shitai | 77 | F |
| Hua Rong | 23 | M | Lin Chaoying | 93 | F |
| Xue Baochai | 18 | F | Song Jiang | 45 | M |
| Xue Baochai | 18 | F | Zhang Sanfeng | 94 | M |
| Diao Chan | 19 | F | Song Jiang | 45 | M |
| Diao Chan | 19 | F | Zhang Sanfeng | 94 | M |
| Huang Yueying | 22 | F | Song Jiang | 45 | M |
| Huang Yueying | 22 | F | Zhang Sanfeng | 94 | M |
| Xiao Qiao | 20 | F | Song Jiang | 45 | M |
| Xiao Qiao | 20 | F | Zhang Sanfeng | 94 | M |
| Ma Chao | 23 | M | Miejue Shitai | 77 | F |
| Ma Chao | 23 | M | Lin Chaoying | 93 | F |
| Xu Xian | 27 | M | Miejue Shitai | 77 | F |
| Xu Xian | 27 | M | Lin Chaoying | 93 | F |
| Sun Dasheng | 100 | M | Miejue Shitai | 77 | F |
| Sun Dasheng | 100 | M | Lin Chaoying | 93 | F |
+---------------+--------------+--------------+---------------+--------------+--------------+
50 rows in set (0.00 sec)



##范例:另一种古老的写法(这个写法也是可以的)
MariaDB [hellodb]> select s.name 学生姓名,s.age 学生年龄,s.gender 学生性别,t.name 老师姓名,t.age 老师年龄, t.gender 老师性别 from students s, teachers t where s.gender <> t.gender;


##进一步再去过滤
select s.name 学生姓名,s.age 学生年龄,s.gender 学生性别,t.name 老师姓名,t.age 老师年龄, t.gender 老师性别 from students s inner join teachers t on s.gender <> t.gender where t.age<=50;

select s.name 学生姓名,s.age 学生年龄,s.gender 学生性别,t.name 老师姓名,t.age 老师年龄, t.gender 老师性别 from students s inner join teachers t on s.gender <> t.gender and t.age<=50;
左和右外连接

image-20240504110550199

image-20240504111111942

  • 范例:左,右外连接
MariaDB [hellodb]> select *from students inner join teachers on students.teacherid=teachers.tid;
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 93 | F |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
3 rows in set (0.00 sec)

MariaDB [hellodb]> select *from students left join teachers on students.teacherid=teachers.tid;
+-------+---------------+-----+--------+---------+-----------+------+---------------+------+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+-----+--------+---------+-----------+------+---------------+------+--------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 2 | Shi Potian | 22 | M | 1 | 7 | NULL | NULL | NULL | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 | NULL | NULL | NULL | NULL |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 93 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
| 6 | Shi Qing | 46 | M | 5 | NULL | NULL | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | NULL | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL | NULL | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL | NULL | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL | NULL | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | NULL | NULL | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+------+---------------+------+--------+
25 rows in set (0.00 sec)




#谁左谁右很关键。
MariaDB [hellodb]> select *from teachers left join students on students.teacherid=teachers.tid;
+-----+---------------+-----+--------+-------+-------------+------+--------+---------+-----------+
| TID | Name | Age | Gender | StuID | Name | Age | Gender | ClassID | TeacherID |
+-----+---------------+-----+--------+-------+-------------+------+--------+---------+-----------+
| 3 | Miejue Shitai | 77 | F | 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 4 | Lin Chaoying | 93 | F | 4 | Ding Dian | 32 | M | 4 | 4 |
| 1 | Song Jiang | 45 | M | 5 | Yu Yutong | 26 | M | 3 | 1 |
| 2 | Zhang Sanfeng | 94 | M | NULL | NULL | NULL | NULL | NULL | NULL |
+-----+---------------+-----+--------+-------+-------------+------+--------+---------+-----------+
4 rows in set (0.00 sec)





##右外连接
MariaDB [hellodb]> select *from teachers right join students on students.teacherid=teachers.tid;
+------+---------------+------+--------+-------+---------------+-----+--------+---------+-----------+
| TID | Name | Age | Gender | StuID | Name | Age | Gender | ClassID | TeacherID |
+------+---------------+------+--------+-------+---------------+-----+--------+---------+-----------+
| 3 | Miejue Shitai | 77 | F | 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| NULL | NULL | NULL | NULL | 2 | Shi Potian | 22 | M | 1 | 7 |
| NULL | NULL | NULL | NULL | 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Lin Chaoying | 93 | F | 4 | Ding Dian | 32 | M | 4 | 4 |
| 1 | Song Jiang | 45 | M | 5 | Yu Yutong | 26 | M | 3 | 1 |
| NULL | NULL | NULL | NULL | 6 | Shi Qing | 46 | M | 5 | NULL |
| NULL | NULL | NULL | NULL | 7 | Xi Ren | 19 | F | 3 | NULL |
| NULL | NULL | NULL | NULL | 8 | Lin Daiyu | 17 | F | 7 | NULL |
| NULL | NULL | NULL | NULL | 9 | Ren Yingying | 20 | F | 6 | NULL |
| NULL | NULL | NULL | NULL | 10 | Yue Lingshan | 19 | F | 3 | NULL |
| NULL | NULL | NULL | NULL | 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| NULL | NULL | NULL | NULL | 12 | Wen Qingqing | 19 | F | 1 | NULL |
| NULL | NULL | NULL | NULL | 13 | Tian Boguang | 33 | M | 2 | NULL |
| NULL | NULL | NULL | NULL | 14 | Lu Wushuang | 17 | F | 3 | NULL |
| NULL | NULL | NULL | NULL | 15 | Duan Yu | 19 | M | 4 | NULL |
| NULL | NULL | NULL | NULL | 16 | Xu Zhu | 21 | M | 1 | NULL |
| NULL | NULL | NULL | NULL | 17 | Lin Chong | 25 | M | 4 | NULL |
| NULL | NULL | NULL | NULL | 18 | Hua Rong | 23 | M | 7 | NULL |
| NULL | NULL | NULL | NULL | 19 | Xue Baochai | 18 | F | 6 | NULL |
| NULL | NULL | NULL | NULL | 20 | Diao Chan | 19 | F | 7 | NULL |
| NULL | NULL | NULL | NULL | 21 | Huang Yueying | 22 | F | 6 | NULL |
| NULL | NULL | NULL | NULL | 22 | Xiao Qiao | 20 | F | 1 | NULL |
| NULL | NULL | NULL | NULL | 23 | Ma Chao | 23 | M | 4 | NULL |
| NULL | NULL | NULL | NULL | 24 | Xu Xian | 27 | M | NULL | NULL |
| NULL | NULL | NULL | NULL | 25 | Sun Dasheng | 100 | M | NULL | NULL |
+------+---------------+------+--------+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
  • 范例:左外连接的扩展用法

image-20240504112147465

MariaDB [hellodb]> select *from students left join teachers on students.teacherid=teachers.tid where tid is null;
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
| 2 | Shi Potian | 22 | M | 1 | 7 | NULL | NULL | NULL | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 | NULL | NULL | NULL | NULL |
| 6 | Shi Qing | 46 | M | 5 | NULL | NULL | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | NULL | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL | NULL | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL | NULL | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL | NULL | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | NULL | NULL | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
22 rows in set (0.00 sec)
完全外连接

可惜,mysql里不支持完全外连接这种语法!

image-20240506053704039

  • 范例:完全外连接
#可惜,mysql里不支持完全外连接这种语法!
MariaDB [hellodb]> select *from students full outer join teachers on students.teacherid=teachers.tid;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'outer join teachers on students.teacherid=teachers.tid' at line 1
MariaDB [hellodb]> select *from students full join teachers on students.teacherid=teachers.tid;
ERROR 1054 (42S22): Unknown column 'students.teacherid' in 'on clause'
  • 范例:我们可以通过其它方式来实现:

对这2种表union,且union可以去重。

image-20240506054241758

注意:这个不是交叉连接哦。

MariaDB [hellodb]> select *from students left join teachers on students.teacherid=teachers.tid;
+-------+---------------+-----+--------+---------+-----------+------+---------------+------+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+-----+--------+---------+-----------+------+---------------+------+--------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 2 | Shi Potian | 22 | M | 1 | 7 | NULL | NULL | NULL | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 | NULL | NULL | NULL | NULL |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 93 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
| 6 | Shi Qing | 46 | M | 5 | NULL | NULL | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | NULL | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL | NULL | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL | NULL | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL | NULL | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | NULL | NULL | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+------+---------------+------+--------+
25 rows in set (0.00 sec)

MariaDB [hellodb]> select *from students right join teachers on students.teacherid=teachers.tid;
+-------+-------------+------+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+-------------+------+--------+---------+-----------+-----+---------------+-----+--------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 93 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
| NULL | NULL | NULL | NULL | NULL | NULL | 2 | Zhang Sanfeng | 94 | M |
+-------+-------------+------+--------+---------+-----------+-----+---------------+-----+--------+
4 rows in set (0.00 sec)

MariaDB [hellodb]> select *from students left join teachers on students.teacherid=teachers.tid
-> union
-> select *from students right join teachers on students.teacherid=teachers.tid;
+-------+---------------+------+--------+---------+-----------+------+---------------+------+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+------+--------+---------+-----------+------+---------------+------+--------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 | 3 | Miejue Shitai | 77 | F |
| 2 | Shi Potian | 22 | M | 1 | 7 | NULL | NULL | NULL | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 | NULL | NULL | NULL | NULL |
| 4 | Ding Dian | 32 | M | 4 | 4 | 4 | Lin Chaoying | 93 | F |
| 5 | Yu Yutong | 26 | M | 3 | 1 | 1 | Song Jiang | 45 | M |
| 6 | Shi Qing | 46 | M | 5 | NULL | NULL | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | NULL | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL | NULL | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL | NULL | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL | NULL | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| NULL | NULL | NULL | NULL | NULL | NULL | 2 | Zhang Sanfeng | 94 | M |
+-------+---------------+------+--------+---------+-----------+------+---------------+------+--------+
26 rows in set (0.00 sec)

MariaDB [hellodb]>

通过这个方式就实现了完全外连接这个功能了。

左外连接,再右外连接,然后中间union

86259d4919e59ed9f7f085b47a5d997f

  • 范例:这个如何实现呢?2个变种+union

image-20240506055602596

MariaDB [hellodb]> select *from students left join teachers on students.teacherid=teachers.tid where tid is null;
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
| 2 | Shi Potian | 22 | M | 1 | 7 | NULL | NULL | NULL | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 | NULL | NULL | NULL | NULL |
| 6 | Shi Qing | 46 | M | 5 | NULL | NULL | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | NULL | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL | NULL | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL | NULL | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL | NULL | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | NULL | NULL | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+------+------+------+--------+
22 rows in set (0.00 sec)



MariaDB [hellodb]> select *from students right join teachers on students.teacherid=teachers.tid where teacherid is null;
+-------+------+------+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+------+------+--------+---------+-----------+-----+---------------+-----+--------+
| NULL | NULL | NULL | NULL | NULL | NULL | 2 | Zhang Sanfeng | 94 | M |
+-------+------+------+--------+---------+-----------+-----+---------------+-----+--------+
1 row in set (0.00 sec)


MariaDB [hellodb]> select *from students left join teachers on students.teacherid=teachers.tid where tid is null
-> union
-> select *from students right join teachers on students.teacherid=teachers.tid where teacherid is null;
+-------+---------------+------+--------+---------+-----------+------+---------------+------+--------+
| StuID | Name | Age | Gender | ClassID | TeacherID | TID | Name | Age | Gender |
+-------+---------------+------+--------+---------+-----------+------+---------------+------+--------+
| 2 | Shi Potian | 22 | M | 1 | 7 | NULL | NULL | NULL | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 | NULL | NULL | NULL | NULL |
| 6 | Shi Qing | 46 | M | 5 | NULL | NULL | NULL | NULL | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL | NULL | NULL | NULL | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL | NULL | NULL | NULL | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL | NULL | NULL | NULL | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL | NULL | NULL | NULL | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL | NULL | NULL | NULL | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL | NULL | NULL | NULL | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL | NULL | NULL | NULL | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL | NULL | NULL | NULL | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL | NULL | NULL | NULL | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL | NULL | NULL | NULL | NULL |
| NULL | NULL | NULL | NULL | NULL | NULL | 2 | Zhang Sanfeng | 94 | M |
+-------+---------------+------+--------+---------+-----------+------+---------------+------+--------+
23 rows in set (0.00 sec)
自连接

即:表自身连接自身。

把一张表当2张表来用。

  • 范例:自连接测试

案例背景:想要查询公司里所有员工的姓名,及对应直属领导姓名。

image-20240506062635612

创建表:

MariaDB [hellodb]> create table emp (id int auto_increment primary key,name varchar(20),leader_id int);
Query OK, 0 rows affected (0.01 sec)

MariaDB [hellodb]> desc emp;
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| leader_id | int(11) | YES | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)


##插入数据
MariaDB [hellodb]> insert emp (name,leader_id)value('mage',null),('zhangsir',1),('wang',2),('zhang',3);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0

MariaDB [hellodb]> select *from emp;
+----+----------+-----------+
| id | name | leader_id |
+----+----------+-----------+
| 1 | mage | NULL |
| 2 | zhangsir | 1 |
| 3 | wang | 2 |
| 4 | zhang | 3 |
+----+----------+-----------+
4 rows in set (0.00 sec)

如果使用内连接+表别名呢?

MariaDB [hellodb]> select e.name,l.name from emp e inner join emp l on e.leader_id=l.id;
+----------+----------+
| name | name |
+----------+----------+
| zhangsir | mage |
| wang | zhangsir |
| zhang | wang |
+----------+----------+
3 rows in set (0.00 sec)


##存在的问题
把mage给丢了……

最后,选择使用左外连接+表别名

MariaDB [hellodb]> select e.name,l.name from emp e left join emp l on e.leader_id=l.id;
+----------+----------+
| name | name |
+----------+----------+
| mage | NULL |
| zhangsir | mage |
| wang | zhangsir |
| zhang | wang |
+----------+----------+
4 rows in set (0.00 sec)

再次更新:

MariaDB [hellodb]> select e.name,IFNULL(l.name,'无上级') from emp e left join emp l on e.leader_id=l.id;
+----------+----------------------------+
| name | IFNULL(l.name,'无上级') |
+----------+----------------------------+
| mage | 无上级 |
| zhangsir | mage |
| wang | zhangsir |
| zhang | wang |
+----------+----------------------------+
4 rows in set (0.00 sec)

测试结束。


三表连接😊
  • 范例:

2张表在什么情况下需要构建出第三张表?

image-20240506073156544

MariaDB [hellodb]> show tables;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes |
| coc |
| courses |
| emp |
| scores |
| students |
| teachers |
| teachers2 |
| teachers3 |
| toc |
+-------------------+
10 rows in set (0.00 sec)

MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)

MariaDB [hellodb]> select *from courses;
+----------+----------------+
| CourseID | Course |
+----------+----------------+
| 1 | Hamo Gong |
| 2 | Kuihua Baodian |
| 3 | Jinshe Jianfa |
| 4 | Taiji Quan |
| 5 | Daiyu Zanghua |
| 6 | Weituo Zhang |
| 7 | Dagou Bangfa |
+----------+----------------+
7 rows in set (0.00 sec)

MariaDB [hellodb]> select *from scores;
+----+-------+----------+-------+
| ID | StuID | CourseID | Score |
+----+-------+----------+-------+
| 1 | 1 | 2 | 77 |
| 2 | 1 | 6 | 93 |
| 3 | 2 | 2 | 47 |
| 4 | 2 | 5 | 97 |
| 5 | 3 | 2 | 88 |
| 6 | 3 | 6 | 75 |
| 7 | 4 | 5 | 71 |
| 8 | 4 | 2 | 89 |
| 9 | 5 | 1 | 39 |
| 10 | 5 | 7 | 63 |
| 11 | 6 | 1 | 96 |
| 12 | 7 | 1 | 86 |
| 13 | 7 | 7 | 83 |
| 14 | 8 | 4 | 57 |
| 15 | 8 | 3 | 93 |
+----+-------+----------+-------+
15 rows in set (0.00 sec)

需求:如何查询学生的姓名-报的课程姓名-考试成绩?

学生成绩表-学生姓名

MariaDB [hellodb]> select st.name 学生姓名,sc.CourseID,sc.Score 考试成绩 from students st inner join scores sc on st.StuID=sc.StuID;
+--------------+----------+--------------+
| 学生姓名 | CourseID | 考试成绩 |
+--------------+----------+--------------+
| Shi Zhongyu | 2 | 77 |
| Shi Zhongyu | 6 | 93 |
| Shi Potian | 2 | 47 |
| Shi Potian | 5 | 97 |
| Xie Yanke | 2 | 88 |
| Xie Yanke | 6 | 75 |
| Ding Dian | 5 | 71 |
| Ding Dian | 2 | 89 |
| Yu Yutong | 1 | 39 |
| Yu Yutong | 7 | 63 |
| Shi Qing | 1 | 96 |
| Xi Ren | 1 | 86 |
| Xi Ren | 7 | 83 |
| Lin Daiyu | 4 | 57 |
| Lin Daiyu | 3 | 93 |
+--------------+----------+--------------+
15 rows in set (0.00 sec)

再与课程表进行内连接:

MariaDB [hellodb]> select st.name 学生姓名,co.Course 课程名称,sc.Score 考试成绩 from students st inner join scores sc on st.StuID=sc.StuID 
-> inner join
-> courses co where sc.CourseID=co. CourseID;

select st.name 学生姓名,co.Course 课程名称,sc.Score 考试成绩 from students st inner join scores sc on st.StuID=sc.StuID inner join courses co where sc.CourseID=co. CourseID;
+--------------+----------------+--------------+
| 学生姓名 | 课程名称 | 考试成绩 |
+--------------+----------------+--------------+
| Shi Zhongyu | Kuihua Baodian | 77 |
| Shi Zhongyu | Weituo Zhang | 93 |
| Shi Potian | Kuihua Baodian | 47 |
| Shi Potian | Daiyu Zanghua | 97 |
| Xie Yanke | Kuihua Baodian | 88 |
| Xie Yanke | Weituo Zhang | 75 |
| Ding Dian | Daiyu Zanghua | 71 |
| Ding Dian | Kuihua Baodian | 89 |
| Yu Yutong | Hamo Gong | 39 |
| Yu Yutong | Dagou Bangfa | 63 |
| Shi Qing | Hamo Gong | 96 |
| Xi Ren | Hamo Gong | 86 |
| Xi Ren | Dagou Bangfa | 83 |
| Lin Daiyu | Taiji Quan | 57 |
| Lin Daiyu | Jinshe Jianfa | 93 |
+--------------+----------------+--------------+
15 rows in set (0.00 sec)

测试结束。😍

SELECT语句处理的顺序

image-20240506074434157

查询执行路径中的组件:查询缓存、解析器、预处理器、优化器、查询执行引擎、存储引擎

SELECT语句的执行流程:

FROM Clause --> WHERE Clause --> GROUP BY --> HAVING Clause -->SELECT --> ORDER BY --> LIMIT

练习

导入hellodb.sql生成数据库

  1. 在students表中,查询年龄大于25岁,且为男性的同学的名字和年龄
  2. 以ClassID为分组依据,显示每组的平均年龄
  3. 显示第2题中平均年龄大于30的分组及平均年龄
  4. 显示以L开头的名字的同学的信息
  5. 显示TeacherID非空的同学的相关信息
  6. 以年龄排序后,显示年龄最大的前10位同学的信息
  7. 查询年龄大于等于20岁,小于等于25岁的同学的信息
  8. 以ClassID分组,显示每班的同学的人数
  9. 以Gender分组,显示其年龄之和
  10. 以ClassID分组,显示其平均年龄大于25的班级
  11. 以Gender分组,显示各组中年龄大于25的学员的年龄之和
  12. 显示前5位同学的姓名、课程及成绩
  13. 显示其成绩高于80的同学的名称及课程
  14. 取每位同学各门课的平均成绩,显示成绩前三名的同学的姓名和平均成绩
  15. 显示每门课程课程名称及学习了这门课的同学的个数
  16. 显示其年龄大于平均年龄的同学的名字
  17. 显示其学习的课程为第1、2,4或第7门课的同学的名字
  18. 显示其成员数最少为3个的班级的同学中年龄大于同班同学平均年龄的同学
  19. 统计各班级中年龄大于全校同学平均年龄的同学

VIEW 视图

视图:虚拟表,保存有实表的查询结果,相当于别名。

试图,通常都是供查,改的会少一些;

通过视图可以隐藏数据库结构,起到安全防护作用;

但好多企业生产环境里是不推荐使用视图的;

视图本身不存放数据;

创建方法:

CREATE   VIEW view_name [(column_list)]
    AS select_statement
    [WITH [CASCADED | LOCAL] CHECK OPTION]

查看视图定义:

SHOW CREATE VIEW view_name #只能看视图定义
SHOW CREATE TABLE view_name # 可以查看表和视图

删除视图:

DROP VIEW [IF EXISTS]
  view_name [, view_name] ...
  [RESTRICT | CASCADE]

注意:视图中的数据事实上存储于“基表”中,因此,其修改操作也会针对基表实现;其修改操作受基表限制

  • 范例:
MariaDB [hellodb]> select st.name 学生姓名,co.Course 课程名称,sc.Score 考试成绩 from students st inner join scores sc on st.StuID=sc.StuID inner join courses co where sc.CourseID=co. CourseID;
+--------------+----------------+--------------+
| 学生姓名 | 课程名称 | 考试成绩 |
+--------------+----------------+--------------+
| Shi Zhongyu | Kuihua Baodian | 77 |
| Shi Zhongyu | Weituo Zhang | 93 |
| Shi Potian | Kuihua Baodian | 47 |
| Shi Potian | Daiyu Zanghua | 97 |
| Xie Yanke | Kuihua Baodian | 88 |
| Xie Yanke | Weituo Zhang | 75 |
| Ding Dian | Daiyu Zanghua | 71 |
| Ding Dian | Kuihua Baodian | 89 |
| Yu Yutong | Hamo Gong | 39 |
| Yu Yutong | Dagou Bangfa | 63 |
| Shi Qing | Hamo Gong | 96 |
| Xi Ren | Hamo Gong | 86 |
| Xi Ren | Dagou Bangfa | 83 |
| Lin Daiyu | Taiji Quan | 57 |
| Lin Daiyu | Jinshe Jianfa | 93 |
+--------------+----------------+--------------+
15 rows in set (0.01 sec)


##创建视图:(其实,就是相当于给一大串select语句起了一个别名)
MariaDB [hellodb]> create view v_score as select st.name 学生姓名,co.Course 课程名称,sc.Score 考试成绩 from students st inner join scores sc on st.StuID=sc.StuID inner join courses co where sc.CourseID=co. CourseID;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> show tables;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes |
| coc |
| courses |
| emp |
| scores |
| students |
| teachers |
| teachers2 |
| teachers3 |
| toc |
| v_score |##可以看到,这里出现了一个v_score表;
+-------------------+
11 rows in set (0.01 sec)


##问题:如果我更改了原来某张表信息,那么刚才创建的视图里的表信息会变化吗?(会的)
MariaDB [hellodb]> select *from scores;
+----+-------+----------+-------+
| ID | StuID | CourseID | Score |
+----+-------+----------+-------+
| 1 | 1 | 2 | 77 |
| 2 | 1 | 6 | 93 |
| 3 | 2 | 2 | 47 |
| 4 | 2 | 5 | 97 |
| 5 | 3 | 2 | 88 |
| 6 | 3 | 6 | 75 |
| 7 | 4 | 5 | 71 |
| 8 | 4 | 2 | 89 |
| 9 | 5 | 1 | 39 |
| 10 | 5 | 7 | 63 |
| 11 | 6 | 1 | 96 |
| 12 | 7 | 1 | 86 |
| 13 | 7 | 7 | 83 |
| 14 | 8 | 4 | 57 |
| 15 | 8 | 3 | 93 |
+----+-------+----------+-------+
15 rows in set (0.00 sec)

MariaDB [hellodb]> update scores set score=88 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

MariaDB [hellodb]> select *from scores;
+----+-------+----------+-------+
| ID | StuID | CourseID | Score |
+----+-------+----------+-------+
| 1 | 1 | 2 | 88 |
| 2 | 1 | 6 | 93 |
| 3 | 2 | 2 | 47 |
| 4 | 2 | 5 | 97 |
| 5 | 3 | 2 | 88 |
| 6 | 3 | 6 | 75 |
| 7 | 4 | 5 | 71 |
| 8 | 4 | 2 | 89 |
| 9 | 5 | 1 | 39 |
| 10 | 5 | 7 | 63 |
| 11 | 6 | 1 | 96 |
| 12 | 7 | 1 | 86 |
| 13 | 7 | 7 | 83 |
| 14 | 8 | 4 | 57 |
| 15 | 8 | 3 | 93 |
+----+-------+----------+-------+
15 rows in set (0.00 sec)

MariaDB [hellodb]> select *from v_score;
+--------------+----------------+--------------+
| 学生姓名 | 课程名称 | 考试成绩 |
+--------------+----------------+--------------+
| Shi Zhongyu | Kuihua Baodian | 88 |
| Shi Zhongyu | Weituo Zhang | 93 |
| Shi Potian | Kuihua Baodian | 47 |
| Shi Potian | Daiyu Zanghua | 97 |
| Xie Yanke | Kuihua Baodian | 88 |
| Xie Yanke | Weituo Zhang | 75 |
| Ding Dian | Daiyu Zanghua | 71 |
| Ding Dian | Kuihua Baodian | 89 |
| Yu Yutong | Hamo Gong | 39 |
| Yu Yutong | Dagou Bangfa | 63 |
| Shi Qing | Hamo Gong | 96 |
| Xi Ren | Hamo Gong | 86 |
| Xi Ren | Dagou Bangfa | 83 |
| Lin Daiyu | Taiji Quan | 57 |
| Lin Daiyu | Jinshe Jianfa | 93 |
+--------------+----------------+--------------+
15 rows in set (0.00 sec)




##问题:如果我更改了视图里某条信息,那么原来表里的信息会变化吗?(会的)
MariaDB [hellodb]> select *from v_score;
+--------------+----------------+--------------+
| 学生姓名 | 课程名称 | 考试成绩 |
+--------------+----------------+--------------+
| Shi Zhongyu | Kuihua Baodian | 88 |
| Shi Zhongyu | Weituo Zhang | 93 |
| Shi Potian | Kuihua Baodian | 47 |
| Shi Potian | Daiyu Zanghua | 97 |
| Xie Yanke | Kuihua Baodian | 88 |
| Xie Yanke | Weituo Zhang | 75 |
| Ding Dian | Daiyu Zanghua | 71 |
| Ding Dian | Kuihua Baodian | 89 |
| Yu Yutong | Hamo Gong | 39 |
| Yu Yutong | Dagou Bangfa | 63 |
| Shi Qing | Hamo Gong | 96 |
| Xi Ren | Hamo Gong | 86 |
| Xi Ren | Dagou Bangfa | 83 |
| Lin Daiyu | Taiji Quan | 57 |
| Lin Daiyu | Jinshe Jianfa | 93 |
+--------------+----------------+--------------+
15 rows in set (0.00 sec)

MariaDB [hellodb]> update v_score set 考试成绩=99 where 考试成绩=88;
Query OK, 2 rows affected (0.01 sec)
Rows matched: 2 Changed: 2 Warnings: 0

MariaDB [hellodb]> select *from v_score;
+--------------+----------------+--------------+
| 学生姓名 | 课程名称 | 考试成绩 |
+--------------+----------------+--------------+
| Shi Zhongyu | Kuihua Baodian | 99 |
| Shi Zhongyu | Weituo Zhang | 93 |
| Shi Potian | Kuihua Baodian | 47 |
| Shi Potian | Daiyu Zanghua | 97 |
| Xie Yanke | Kuihua Baodian | 99 |
| Xie Yanke | Weituo Zhang | 75 |
| Ding Dian | Daiyu Zanghua | 71 |
| Ding Dian | Kuihua Baodian | 89 |
| Yu Yutong | Hamo Gong | 39 |
| Yu Yutong | Dagou Bangfa | 63 |
| Shi Qing | Hamo Gong | 96 |
| Xi Ren | Hamo Gong | 86 |
| Xi Ren | Dagou Bangfa | 83 |
| Lin Daiyu | Taiji Quan | 57 |
| Lin Daiyu | Jinshe Jianfa | 93 |
+--------------+----------------+--------------+
15 rows in set (0.00 sec)

MariaDB [hellodb]> select *from scores;
+----+-------+----------+-------+
| ID | StuID | CourseID | Score |
+----+-------+----------+-------+
| 1 | 1 | 2 | 99 |
| 2 | 1 | 6 | 93 |
| 3 | 2 | 2 | 47 |
| 4 | 2 | 5 | 97 |
| 5 | 3 | 2 | 99 |
| 6 | 3 | 6 | 75 |
| 7 | 4 | 5 | 71 |
| 8 | 4 | 2 | 89 |
| 9 | 5 | 1 | 39 |
| 10 | 5 | 7 | 63 |
| 11 | 6 | 1 | 96 |
| 12 | 7 | 1 | 86 |
| 13 | 7 | 7 | 83 |
| 14 | 8 | 4 | 57 |
| 15 | 8 | 3 | 93 |
+----+-------+----------+-------+
15 rows in set (0.00 sec)



##注意:创建视图时,原来表的查询结果字段一定要不同,否则会导致创建视图失败的。
MariaDB [hellodb]> select s.name,t.name from students s inner join teachers t on s.teacherid=t.tid;
+-------------+---------------+
| name | name |
+-------------+---------------+
| Yu Yutong | Song Jiang |
| Shi Zhongyu | Miejue Shitai |
| Ding Dian | Lin Chaoying |
+-------------+---------------+
3 rows in set (0.00 sec)

MariaDB [hellodb]> create view v_testview as select s.name,t.name from students s inner join teachers t on s.teacherid=t.tid;
ERROR 1060 (42S21): Duplicate column name 'name' ##报错了
MariaDB [hellodb]>


##因此,这里通过创建别名来实现
MariaDB [hellodb]> select s.name stu_name,t.name tea_name from students s inner join teachers t on s.teacherid=t.tid;
+-------------+---------------+
| stu_name | tea_name |
+-------------+---------------+
| Yu Yutong | Song Jiang |
| Shi Zhongyu | Miejue Shitai |
| Ding Dian | Lin Chaoying |
+-------------+---------------+
3 rows in set (0.00 sec)

MariaDB [hellodb]> create view v_stu_tea_view as select s.name stu_name,t.name tea_name from students s inner join teachers t on s.teacherid=t.tid;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> select *from v_stu_tea_view;
+-------------+---------------+
| stu_name | tea_name |
+-------------+---------------+
| Yu Yutong | Song Jiang |
| Shi Zhongyu | Miejue Shitai |
| Ding Dian | Lin Chaoying |
+-------------+---------------+
3 rows in set (0.00 sec)




##视图本身不存放数据;
MariaDB [hellodb]> show tables;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes |
| coc |
| courses |
| emp |
| scores |
| students |
| teachers |
| teachers2 |
| teachers3 |
| toc |
| v_score |
| v_stu_tea_view |
+-------------------+
12 rows in set (0.00 sec)
MariaDB [hellodb]> desc v_stu_tea_view;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| stu_name | varchar(50) | NO | | NULL | |
| tea_name | varchar(100) | NO | | NULL | |
+----------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

image-20240507063635711

  • 范例:如何查看某张表是否是view呢?
MariaDB [hellodb]> show table  status like 'v_stu_tea_view'\G
*************************** 1. row ***************************
Name: v_stu_tea_view
Engine: NULL
Version: NULL
Row_format: NULL
Rows: NULL
Avg_row_length: NULL
Data_length: NULL
Max_data_length: NULL
Index_length: NULL
Data_free: NULL
Auto_increment: NULL
Create_time: NULL
Update_time: NULL
Check_time: NULL
Collation: NULL
Checksum: NULL
Create_options: NULL
Comment: VIEW ##look here 😜
1 row in set (0.00 sec)

MariaDB [hellodb]> show table status like 'students'\G
*************************** 1. row ***************************
Name: students
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 25
Avg_row_length: 655
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 9437184
Auto_increment: 26
Create_time: 2024-05-03 07:16:29
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
  • 范例:查看数据库下所有表/视图的状态
MariaDB [hellodb]> show table status from  hellodb\G
……
*************************** 10. row ***************************
Name: toc
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 0
Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 9437184
Auto_increment: 1
Create_time: 2024-05-03 07:16:29
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
*************************** 11. row ***************************
Name: v_score
Engine: NULL
Version: NULL
Row_format: NULL
Rows: NULL
Avg_row_length: NULL
Data_length: NULL
Max_data_length: NULL
Index_length: NULL
Data_free: NULL
Auto_increment: NULL
Create_time: NULL
Update_time: NULL
Check_time: NULL
Collation: NULL
Checksum: NULL
Create_options: NULL
Comment: VIEW
*************************** 12. row ***************************
Name: v_stu_tea_view
Engine: NULL
Version: NULL
Row_format: NULL
Rows: NULL
Avg_row_length: NULL
Data_length: NULL
Max_data_length: NULL
Index_length: NULL
Data_free: NULL
Auto_increment: NULL
Create_time: NULL
Update_time: NULL
Check_time: NULL
Collation: NULL
Checksum: NULL
Create_options: NULL
Comment: VIEW
12 rows in set (0.00 sec)

FUNCTION 函数

[!CAUTION]

测试环境里可以使用函数,但生产力不推荐使用函数来实现这么长的sql功能。

所以,在淘宝、阿里巴巴手册里,规定禁止使用函数、存储过程、视图等功能。

函数:分为系统内置函数和自定义函数

注意:是mysql数据库里的proc表。

创建UDF语法:

CREATE [AGGREGATE] FUNCTION function_name(parameter_name type,[parameter_name 
type,...])
  RETURNS {STRING|INTEGER|REAL}
runtime_body

说明:

  • 参数可以有多个,也可以没有参数;
  • 无论有无参数,小括号()是必须的;
  • 必须有且只有一个返回值;

查看函数列表:

SHOW FUNCTION STATUS;

查看函数定义:

SHOW CREATE FUNCTION function_name

删除删除UDF:

DROP FUNCTION function_name

调用自定义函数语法:

SELECT function_name(parameter_value,...)
  • 范例:统计一张表有多少条记录,count()函数 (内置函数)
MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
##或者加上主键,因为主键不允许为空。
MariaDB [hellodb]> select count(stuid) from students;
+--------------+
| count(stuid) |
+--------------+
| 25 |
+--------------+
1 row in set (0.00 sec)


##查询某张表有多少条记录
MariaDB [hellodb]> select count(*) from students;
+----------+
| count(*) |
+----------+
| 25 |
+----------+
1 row in set (0.00 sec)


##也可以查询表里面的某个字段
MariaDB [hellodb]> select count(stuid) from students;
+--------------+
| count(stuid) |
+--------------+
| 25 |
+--------------+
1 row in set (0.00 sec)

MariaDB [hellodb]> select count(classid) from students; ##注意:count函数这个是返回非空数据,空是不计数的。
+----------------+
| count(classid) |
+----------------+
| 23 |
+----------------+
1 row in set (0.00 sec)

MariaDB [hellodb]> select count(teacherid) from students;
+------------------+
| count(teacherid) |
+------------------+
| 5 |
+------------------+
1 row in set (0.00 sec)

  • 范例:无参UDF
MariaDB [hellodb]> SHOW FUNCTION STATUS;
Empty set (0.00 sec)

MariaDB [hellodb]> CREATE FUNCTION simpleFun() RETURNS VARCHAR(20) RETURN "Hello World";
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> SHOW FUNCTION STATUS\G
*************************** 1. row ***************************
Db: hellodb
Name: simpleFun
Type: FUNCTION
Definer: root@localhost
Modified: 2024-05-07 07:33:53
Created: 2024-05-07 07:33:53
Security_type: DEFINER
Comment:
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: utf8_general_ci
1 row in set (0.00 sec)


MariaDB [hellodb]> select simpleFun();
+-------------+
| simpleFun() |
+-------------+
| Hello World |
+-------------+
1 row in set (0.00 sec)


##函数是存放在mysql数据库的proc表里的
[root@test mysql]# pwd
/var/lib/mysql/mysql
[root@test mysql]# ll -t
total 1000
-rw-rw---- 1 mysql mysql 292 May 7 07:27 proc.MYD
-rw-rw---- 1 mysql mysql 4096 May 7 07:27 proc.MYI
MariaDB [mysql]> select *from mysql.proc\G
*************************** 1. row ***************************
db: mysql
name: simpleFun
type: FUNCTION
specific_name: simpleFun
language: SQL
sql_data_access: CONTAINS_SQL
is_deterministic: NO
security_type: DEFINER
param_list:
returns: varchar(20) CHARSET latin1
body: RETURN "Hello World"
definer: root@localhost
created: 2024-05-07 07:27:59
modified: 2024-05-07 07:27:59
sql_mode:
comment:
character_set_client: utf8
collation_connection: utf8_general_ci
db_collation: latin1_swedish_ci
body_utf8: RETURN "Hello World"
1 row in set (0.00 sec)


##注意:函数是有归属区分的
MariaDB [hellodb]> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [mysql]> select simpleFun();
ERROR 1305 (42000): FUNCTION mysql.simpleFun does not exist
MariaDB [mysql]> select hellodb.simpleFun();
+---------------------+
| hellodb.simpleFun() |
+---------------------+
| Hello World |
+---------------------+
1 row in set (0.00 sec)


##删除函数
MariaDB [hellodb]> d
Query OK, 0 rows aff


MariaDB [hellodb]> s
Empty set (0.00 sec)
  • 范例:有参UDF
#有参数UDF
DELIMITER //
CREATE FUNCTION deleteById(id SMALLINT UNSIGNED) RETURNS VARCHAR(20)
BEGIN
DELETE FROM students WHERE stuid = id;
RETURN (SELECT COUNT(*) FROM students);
END//
DELIMITER ;

##说明:DELIMITER // 是用来修改数据库分隔符的;
DELIMITER //
CREATE FUNCTION deleteById(id SMALLINT UNSIGNED) RETURNS VARCHAR(20)
BEGIN
DELETE FROM students WHERE stuid = id;
RETURN (SELECT COUNT(*) FROM students);
END//
DELIMITER ;


MariaDB [hellodb]> show function status\G
*************************** 1. row ***************************
Db: hellodb
Name: deleteById
Type: FUNCTION
Definer: root@localhost
Modified: 2024-05-07 07:50:35
Created: 2024-05-07 07:50:35
Security_type: DEFINER
Comment:
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: utf8_general_ci
1 row in set (0.00 sec)


##删除第25个同学
MariaDB [hellodb]> select deleteById(25);
+----------------+
| deleteById(25) |
+----------------+
| 24 |
+----------------+
1 row in set (0.00 sec)

MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
24 rows in set (0.00 sec)


##删除第10号同学
MariaDB [hellodb]> select deleteById(10);
+----------------+
| deleteById(10) |
+----------------+
| 23 |
+----------------+
1 row in set (0.01 sec)

MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
23 rows in set (0.00 sec)

MySQL中的变量

两种变量:系统内置变量和用户自定义变量

  • 系统变量:MySQL数据库中内置的变量,可用@@var_name引用

  • 用户自定义变量分为以下两种

    • 普通变量:在当前会话中有效,可用@var_name引用
    • 局部变量:在函数或存储过程内才有效,需要用DECLARE 声明,之后直接用 var_name引用
  • 范例:查看所有系统变量

MariaDB [hellodb]> show variables\G
……
*************************** 431. row ***************************
Variable_name: version_compile_os
Value: Linux
*************************** 432. row ***************************
Variable_name: wait_timeout
Value: 28800
*************************** 433. row ***************************
Variable_name: warning_count
Value: 0
433 rows in set (0.01 sec)
  • 范例:查询系统变量值
MariaDB [hellodb]> select @@port;
+--------+
| @@port |
+--------+
| 3306 |
+--------+
1 row in set (0.00 sec)

MariaDB [hellodb]> select @@hostname;
+-------------------------+
| @@hostname |
+-------------------------+
| iZbp1in7y9nitzcajdv0ufZ |
+-------------------------+
1 row in set (0.00 sec)
  • 范例:concat函数(用于连接2个字符串)
MariaDB [hellodb]> select concat('wang',100);
+--------------------+
| concat('wang',100) |
+--------------------+
| wang100 |
+--------------------+
1 row in set (0.00 sec)

MariaDB [hellodb]> select concat('wang',100,'xyy');
+--------------------------+
| concat('wang',100,'xyy') |
+--------------------------+
| wang100xyy |
+--------------------------+
1 row in set (0.00 sec)

自定义函数中定义局部变量语法

DECLARE 变量1[,变量2,... ]变量类型 [DEFAULT 默认值]

[!NOTE]

说明:局部变量的作用范围是在BEGIN...END程序中,而且定义局部变量语句必须在BEGIN...END的第一行定义。

  • 范例:自定义函数中定义局部变量语法
DELIMITER //
CREATE FUNCTION addTwoNumber(x SMALLINT UNSIGNED, y SMALLINT UNSIGNED)
RETURNS SMALLINT
BEGIN
DECLARE a, b SMALLINT UNSIGNED;
SET a = x, b = y;
RETURN a+b;
END//
DELIMITER ;


#测试过程
MariaDB [hellodb]> DELIMITER //
MariaDB [hellodb]> CREATE FUNCTION addTwoNumber(x SMALLINT UNSIGNED, y SMALLINT UNSIGNED)
-> RETURNS SMALLINT
-> BEGIN
-> DECLARE a, b SMALLINT UNSIGNED;
-> SET a = x, b = y;
-> RETURN a+b;
-> END//
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> DELIMITER ;
MariaDB [hellodb]>
MariaDB [hellodb]> select addTwoNumber(10,20);
+---------------------+
| addTwoNumber(10,20) |
+---------------------+
| 30 |
+---------------------+
1 row in set (0.00 sec)

MariaDB [hellodb]> select @@a;
ERROR 1193 (HY000): Unknown system variable 'a'
MariaDB [hellodb]> select @a;
+------+
| @a |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

MariaDB [hellodb]>

为变量赋值语法

SET parameter_name = value[,parameter_name = value...]
SELECT INTO parameter_name

范例:

.....
DECLARE x int;
SELECT COUNT(*) FROM tdb_name INTO x;
RETURN x;
END//
  • 范例:自定义的普通变量
MariaDB [hellodb]> select @a;
+------+
| @a |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

MariaDB [hellodb]> set @var1='hello';
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> select @var1;
+-------+
| @var1 |
+-------+
| hello |
+-------+
1 row in set (0.00 sec)

##另开一个终端:
MariaDB [hellodb]> select @var1;
+-------+
| @var1 |
+-------+
| NULL |
+-------+
1 row in set (0.00 sec)



MariaDB [hellodb]> select max(age) from students into @age;
Query OK, 1 row affected (0.00 sec)

MariaDB [hellodb]> select @age;
+------+
| @age |
+------+
| 53 |
+------+
1 row in set (0.00 sec)
MariaDB [hellodb]> set @age=100;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> select @age;
+------+
| @age |
+------+
| 100 |
+------+
1 row in set (0.00 sec)

PROCEDURE 存储过程

存储过程:多表SQL的语句的集合,可以独立执行,存储过程保存在mysql.proc表中

存储过程优势:

存储过程把经常使用的SQL语句或业务逻辑封装起来,预编译保存在数据库中,当需要时从数据库中直接调用,省去了编译的过程,提高了运行速度,同时降低网络数据传输量

存储过程与自定义函数的区别

存储过程实现的过程要复杂一些,而函数的针对性较强

存储过程可以有多个返回值,而自定义函数只有一个返回值

存储过程一般可独立执行,而函数往往是作为其他SQL语句的一部分来使用

创建存储过程

CREATE PROCEDURE sp_name ([ proc_parameter [,proc_parameter ...]])
routime_body
proc_parameter : [IN|OUT|INOUT] parameter_name type

说明:其中IN表示输入参数,OUT表示输出参数,INOUT表示既可以输入也可以输出;param_name表示参数名称;type表示参数的类型

查看存储过程列表

SHOW PROCEDURE  STATUS;

查看存储过程定义

SHOW CREATE PROCEDURE sp_name

调用存储过程

CALL sp_name ([ proc_parameter [,proc_parameter ...]])

说明:当无参时,可以省略"()",当有参数时,不可省略"()”

存储过程修改

ALTER语句修改存储过程只能修改存储过程的注释等无关紧要的东西,不能修改存储过程体,所以要修改

存储过程,方法就是删除重建

DROP PROCEDURE [IF EXISTS] sp_name
  • 范例:PROCEDURE 存储过程(创建无参存储过程)
# 创建无参存储过程
delimiter //
CREATE PROCEDURE showTime()
BEGIN
SELECT now();
END//
delimiter ;

CALL showTime;


##测试过程
MariaDB [hellodb]> delimiter //
MariaDB [hellodb]> CREATE PROCEDURE showTime()
-> BEGIN
-> SELECT now();
-> END//
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> delimiter ;

MariaDB [hellodb]> call showtime;
+---------------------+
| now() |
+---------------------+
| 2024-05-10 05:35:20 |
+---------------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)
  • 范例:PROCEDURE 存储过程(创建含参存储过程:只有一个IN参数)
#创建含参存储过程:只有一个IN参数
delimiter //
CREATE PROCEDURE selectById(IN id SMALLINT UNSIGNED)
BEGIN
SELECT * FROM students WHERE stuid = id;
END//
delimiter ;

call selectById(2);


##测试过程
MariaDB [hellodb]> delimiter //
MariaDB [hellodb]> CREATE PROCEDURE selectById(IN id SMALLINT UNSIGNED)
-> BEGIN
-> SELECT * FROM students WHERE stuid = id;
-> END//
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> delimiter ;
MariaDB [hellodb]>
MariaDB [hellodb]> call selectById(3);
+-------+-----------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-----------+-----+--------+---------+-----------+
| 3 | Xie Yanke | 53 | M | 2 | 16 |
+-------+-----------+-----+--------+---------+-----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)
  • 范例:
delimiter //
CREATE PROCEDURE dorepeat(n INT)
BEGIN
SET @i = 0;
SET @sum = 0;
REPEAT SET @sum = @sum+@i;
SET @i = @i + 1;
UNTIL @i > n END REPEAT;
END//
delimiter ;
CALL dorepeat(100);

SELECT @sum;

##测试过程
MariaDB [hellodb]> delimiter //
MariaDB [hellodb]> CREATE PROCEDURE dorepeat(n INT)
-> BEGIN
-> SET @i = 0;
-> SET @sum = 0;
-> REPEAT SET @sum = @sum+@i;
-> SET @i = @i + 1;
-> UNTIL @i > n END REPEAT;
-> END//
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> delimiter ;
MariaDB [hellodb]> CALL dorepeat(100);
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]>
MariaDB [hellodb]> select @sum;
+------+
| @sum |
+------+
| 5050 |
+------+
1 row in set (0.00 sec)

MariaDB [hellodb]> set @sum=200;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> select @sum;
+------+
| @sum |
+------+
| 200 |
+------+
1 row in set (0.00 sec)
  • 范例
#创建含参存储过程:包含IN参数和OUT参数
delimiter //
CREATE PROCEDURE deleteById(IN id SMALLINT UNSIGNED, OUT num SMALLINT UNSIGNED)
BEGIN
DELETE FROM students WHERE stuid >= id;
SELECT row_count() into num;
END//
delimiter ;
call deleteById(2,@Line);
SELECT @Line;

#说明:创建存储过程deleteById,包含一个IN参数和一个OUT参数.调用时,传入删除的ID和保存被修改的行
数值的用户变量@Line,select @Line;输出被影响行数
#row_count() 系统内置函数,用于存放前一条SQL修改过的表的记录数

测试过程:

MariaDB [hellodb]> delimiter //
MariaDB [hellodb]> CREATE PROCEDURE deleteById(IN id SMALLINT UNSIGNED, OUT num SMALLINT UNSIGNED)
-> BEGIN
-> DELETE FROM students WHERE stuid >= id;
-> SELECT row_count() into num;
-> END//
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> delimiter ;
MariaDB [hellodb]> call deleteById(2,@Line);
Query OK, 1 row affected (0.00 sec)

MariaDB [hellodb]> SELECT @Line;
+-------+
| @Line |
+-------+
| 22 |
+-------+
1 row in set (0.00 sec)

MariaDB [hellodb]>

流程控制

存储过程和函数中可以使用流程控制来控制语句的执行

  • IF:用来进行条件判断。根据是否满足条件,执行不同语句
  • CASE:用来进行条件判断,可实现比IF语句更复杂的条件判断
  • LOOP:重复执行特定的语句,实现一个简单的循环
  • LEAVE:用于跳出循环控制,相当于SHELL中break
  • ITERATE:跳出本次循环,然后直接进入下一次循环,相当于SHELL中continue
  • REPEAT:有条件控制的循环语句。当满足特定条件时,就会跳出循环语句
  • WHILE:有条件控制的循环语句

TRIGGER触发器

触发器的执行不是由程序调用,也不是由手工启动,而是由事件来触发、激活从而实现执行。

创建触发器

CREATE [DEFINER = { user | CURRENT_USER }]
   TRIGGER trigger_name
  trigger_time trigger_event
   ON tbl_name FOR EACH ROW
  trigger_body

说明:

trigger_name:触发器的名称

trigger_time:{ BEFORE | AFTER },表示在事件之前或之后触发

trigger_event::{ INSERT |UPDATE | DELETE },触发的具体事件

tbl_name:该触发器作用在表名

查看触发器

#在当前数据库对应的目录下,可以查看到新生成的相关文件:trigger_name.TRN,table_name.TRG
SHOW TRIGGERS;
#查询系统表information_schema.triggers的方式指定查询条件,查看指定的触发器信息。
USE information_schema;
SELECT * FROM triggers WHERE trigger_name='trigger_student_count_insert';

删除触发器

DROP TRIGGER trigger_name;
  • 范例
#创建触发器,在向学生表INSERT数据时,学生数增加,DELETE学生时,学生数减少
CREATE TABLE student_info (
stu_id INT(11) NOT NULL AUTO_INCREMENT ,
stu_name VARCHAR(255) DEFAULT NULL,
 PRIMARY KEY (stu_id)
);
CREATE TABLE student_count (
student_count  INT(11) DEFAULT 0
);

INSERT INTO student_count VALUES(0);



CREATE TRIGGER trigger_student_count_insert
AFTER INSERT
ON student_info FOR EACH ROW
UPDATE student_count SET student_count=student_count+1;

CREATE TRIGGER trigger_student_count_delete
AFTER DELETE
ON student_info FOR EACH ROW
UPDATE student_count SET student_count=student_count-1;

测试过程:

MariaDB [hellodb]> CREATE TABLE student_info (
-> stu_id INT(11) NOT NULL AUTO_INCREMENT ,
-> stu_name VARCHAR(255) DEFAULT NULL,
-> PRIMARY KEY (stu_id)
-> );
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> CREATE TABLE student_count (
-> student_count INT(11) DEFAULT 0
-> );
Query OK, 0 rows affected (0.01 sec)

MariaDB [hellodb]> select *from student_info;
Empty set (0.00 sec)

MariaDB [hellodb]> select *from student_count;
Empty set (0.00 sec)



MariaDB [hellodb]> INSERT INTO student_count VALUES(0);
Query OK, 1 row affected (0.00 sec)



##创建trigger
MariaDB [hellodb]>
MariaDB [hellodb]> CREATE TRIGGER trigger_student_count_insert
-> AFTER INSERT
-> ON student_info FOR EACH ROW
-> UPDATE student_count SET student_count=student_count+1;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]>
MariaDB [hellodb]> CREATE TRIGGER trigger_student_count_delete
-> AFTER DELETE
-> ON student_info FOR EACH ROW
-> UPDATE student_count SET student_count=student_count-1;
Query OK, 0 rows affected (0.00 sec)



##更新表
MariaDB [hellodb]> insert student_info (stu_name)values('hg');
Query OK, 1 row affected (0.00 sec)

MariaDB [hellodb]> select *from student_info;
+--------+----------+
| stu_id | stu_name |
+--------+----------+
| 1 | hg |
+--------+----------+
1 row in set (0.00 sec)

MariaDB [hellodb]> select *from student_count;
+---------------+
| student_count |
+---------------+
| 1 |
+---------------+
1 row in set (0.00 sec)
MariaDB [hellodb]> insert student_info (stu_name)values('hg');
Query OK, 1 row affected (0.00 sec)

MariaDB [hellodb]> select *from student_info;
+--------+----------+
| stu_id | stu_name |
+--------+----------+
| 1 | hg |
+--------+----------+
1 row in set (0.00 sec)

MariaDB [hellodb]> select *from student_count;
+---------------+
| student_count |
+---------------+
| 1 |
+---------------+
1 row in set (0.00 sec)



MariaDB [hellodb]> delete from student_info where stu_id>=3;
Query OK, 3 rows affected (0.00 sec)

MariaDB [hellodb]> select *from student_info;
+--------+----------+
| stu_id | stu_name |
+--------+----------+
| 1 | hg |
| 2 | xyy |
+--------+----------+
2 rows in set (0.00 sec)

MariaDB [hellodb]> select *from student_count;
+---------------+
| student_count |
+---------------+
| 2 |
+---------------+
1 row in set (0.00 sec)


##底层存储位置:
[root@test hellodb]# ll
total 168
-rw-rw---- 1 mysql mysql 8636 May 3 07:16 classes.frm
-rw-rw---- 1 mysql mysql 8630 May 3 07:16 coc.frm
-rw-rw---- 1 mysql mysql 8602 May 3 07:16 courses.frm
-rw-rw---- 1 mysql mysql 61 May 3 07:16 db.opt
-rw-rw---- 1 mysql mysql 8626 May 6 06:55 emp.frm
-rw-rw---- 1 mysql mysql 8658 May 3 07:16 scores.frm
-rw-rw---- 1 mysql mysql 8578 May 10 07:47 student_count.frm
-rw-rw---- 1 mysql mysql 8602 May 10 07:47 student_info.frm
-rw-rw---- 1 mysql mysql 560 May 10 07:47 student_info.TRG ##warning
-rw-rw---- 1 mysql mysql 8736 May 3 07:16 students.frm
-rw-rw---- 1 mysql mysql 8656 May 3 07:24 teachers2.frm
-rw-rw---- 1 mysql mysql 8650 May 3 07:32 teachers3.frm
-rw-rw---- 1 mysql mysql 8656 May 3 07:16 teachers.frm
-rw-rw---- 1 mysql mysql 8622 May 3 07:16 toc.frm
-rw-rw---- 1 mysql mysql 44 May 10 07:47 trigger_student_count_delete.TRN ##warning
-rw-rw---- 1 mysql mysql 44 May 10 07:47 trigger_student_count_insert.TRN ##warning
-rw-rw---- 1 mysql mysql 1016 May 7 06:09 v_score.frm
-rw-rw---- 1 mysql mysql 695 May 7 06:31 v_stu_tea_view.frm

[root@test hellodb]# cat student_info.TRG
TYPE=TRIGGERS
triggers='CREATE DEFINER=`root`@`localhost` TRIGGER trigger_student_count_insert\nAFTER INSERT\nON student_info FOR EACH ROW\nUPDATE student_count SET student_count=student_count+1' 'CREATE DEFINER=`root`@`localhost` TRIGGER trigger_student_count_delete\nAFTER DELETE\nON student_info FOR EACH ROW\nUPDATE student_count SET student_count=student_count-1'
sql_modes=0 0
definers='root@localhost' 'root@localhost'
client_cs_names='utf8' 'utf8'
connection_cl_names='utf8_general_ci' 'utf8_general_ci'
db_cl_names='utf8_general_ci' 'utf8_general_ci'
[root@test hellodb]# cat trigger_student_count_delete.TRN
TYPE=TRIGGERNAME
trigger_table=student_info
[root@test hellodb]# cat trigger_student_count_insert.TRN
TYPE=TRIGGERNAME
trigger_table=student_info

Event 事件

[!NOTE]

类似于shell里的crontab。

Event 事件介绍

事件(event)是MySQL在相应的时刻调用的过程式数据库对象。一个事件可调用一次,也可周期性的启动,它由一个特定的线程来管理的,也就是所谓的“事件调度器”。

事件和触发器类似,都是在某些事情发生的时候启动。当数据库上启动一条语句的时候,触发器就启动了,而事件是根据调度事件来启动的。由于它们彼此相似,所以事件也称为临时性触发器

事件取代了原先只能由操作系统的计划任务来执行的工作,而且MySQL的事件调度器可以精确到每秒钟执行一个任务,而操作系统的计划任务(如:Linux下的CRON或Windows下的任务计划)只能精确到每分钟执行一次。

事件的优缺点

优点:一些对数据定时性操作不再依赖外部程序,而直接使用数据库本身提供的功能,可以实现每秒钟执行一个任务,这在一些对实时性要求较高的环境下就非常实用

缺点:定时触发,不可以直接调用

Event 管理

相关变量和服务器选项

MySQL事件调度器event_scheduler负责调用事件,它默认是关闭的。这个调度器不断地监视一个事件是否要调用, 要创建事件,必须打开调度器

服务器系统变量和服务器选项:

event_scheduler:默认值为OFF,设置为ON才支持Event,并且系统自动打开专用的线程。

🍊 范例:开启和关闭event_scheduler

#默认事件调度功能是关闭的
MariaDB [hellodb]> select @@event_scheduler;
+-------------------+
| @@event_scheduler |
+-------------------+
| OFF |
+-------------------+
1 row in set (0.00 sec)


#临时开启事件调度功能
MariaDB [hellodb]> set global event_scheduler=1;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> show processlist;
+-----+-----------------+-----------+---------+---------+------+------------------------+------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+-----+-----------------+-----------+---------+---------+------+------------------------+------------------+----------+
| 402 | root | localhost | hellodb | Query | 0 | NULL | show processlist | 0.000 |
| 403 | event_scheduler | localhost | NULL | Daemon | 13 | Waiting on empty queue | NULL | 0.000 |
+-----+-----------------+-----------+---------+---------+------+------------------------+------------------+----------+
2 rows in set (0.00 sec)


#临时关闭事件调度功能
MariaDB [hellodb]> set global event_scheduler=0;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hellodb]> show processlist;
+-----+------+-----------+---------+---------+------+-------+------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+-----+------+-----------+---------+---------+------+-------+------------------+----------+
| 402 | root | localhost | hellodb | Query | 0 | NULL | show processlist | 0.000 |
+-----+------+-----------+---------+---------+------+-------+------------------+----------+
1 row in set (0.00 sec)


#持久开启事件调度
#持久开启事件调度
[root@centos8 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
event_scheduler=ON
[root@centos8 ~]#systemctl restart mariadb
管理事件

create event 语句创建一个事件。每个事件由两个主要部分组成,第一部分是事件调度(event schedule),表示事件何时启动以及按什么频率启动,第二部分是事件动作(event action ),这是事件启动时执行的代码,事件的动作包含一条SQL语句,它可能是一个简单地insert或者update语句,也可以使一个存储过程或者 benin...end语句块,这两种情况允许我们执行多条SQL

一个事件可以是活动(打开)的或停止(关闭)的,活动意味着事件调度器检查事件动作是否必须调用,停止意味着事件的声明存储在目录中,但调度器不会检查它是否应该调用。在一个事件创建之后,它立即变为活动的,一个活动的事件可以执行一次或者多次。

范例

🍊 范例:创建立即启动事件

#创建数据库
MariaDB [hellodb]> create database testdb;
Query OK, 1 row affected (0.01 sec)

MariaDB [hellodb]> use testdb;
Database changed


#创建一个表记录每次事件调度的名字和事件戳
MariaDB [testdb]> create table events_list(event_name varchar(20) not null, event_started timestamp not null);
Query OK, 0 rows affected (0.00 sec)

MariaDB [testdb]> select *from events_list;
Empty set (0.00 sec)


#临时关闭事件调度功能
MariaDB [testdb]> set global event_scheduler=0;
Query OK, 0 rows affected (0.00 sec)

MariaDB [testdb]> show variables like 'event_scheduler';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| event_scheduler | OFF |
+-----------------+-------+
1 row in set (0.00 sec)


#创建一次性事件
MariaDB [testdb]> create event event_now on schedule at now() do insert into events_list values('event_now', now());
Query OK, 0 rows affected (0.00 sec)


#因为事件调度功能禁用,所有表中无记录
MariaDB [testdb]> select *from events_list;
Empty set (0.00 sec)


#查看事件
MariaDB [testdb]> show events\G
*************************** 1. row ***************************
Db: testdb
Name: event_now
Definer: root@localhost
Time zone: SYSTEM
Type: ONE TIME
Execute at: 2024-05-12 07:38:12
Interval value: NULL
Interval field: NULL
Starts: NULL
Ends: NULL
Status: ENABLED
Originator: 0
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: latin1_swedish_ci
1 row in set (0.00 sec)
#任务计划存放在mysql.event表中
MariaDB [testdb]> select *from mysql.event\G
*************************** 1. row ***************************
db: testdb
name: event_now
body: insert into events_list values('event_now', now())
definer: root@localhost
execute_at: 2024-05-11 23:38:12
interval_value: NULL
interval_field: NULL
created: 2024-05-12 07:38:12
modified: 2024-05-12 07:38:12
last_executed: NULL
starts: NULL
ends: NULL
status: ENABLED
on_completion: DROP
sql_mode:
comment:
originator: 0
time_zone: SYSTEM
character_set_client: utf8
collation_connection: utf8_general_ci
db_collation: latin1_swedish_ci
body_utf8: insert into events_list values('event_now', now())
1 row in set (0.00 sec)
#查看mysql数据库下对应event文件
[root@test mysql]# ll -t
total 1004
-rw-rw---- 1 mysql mysql 216 May 12 07:38 event.MYD
-rw-rw---- 1 mysql mysql 4096 May 12 07:38 event.MYI
……


#开启事件调度功能
MariaDB [testdb]> set global event_scheduler=1;
Query OK, 0 rows affected (0.00 sec)
#事件立即执行,每秒插入一条记录
MariaDB [testdb]> select *from events_list;
+------------+---------------------+
| event_name | event_started |
+------------+---------------------+
| event_now | 2024-05-12 07:41:42 |
+------------+---------------------+
1 row in set (0.00 sec)


#事件执行完成后自动删除
MariaDB [testdb]> show events;
Empty set (0.00 sec)

🍊 范例:创建每秒启动的事件

#创建事件
MariaDB [testdb]> CREATE EVENT event_every_second ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_list VALUES('event_now', now());
Query OK, 0 rows affected (0.00 sec)


#查看事件
MariaDB [testdb]> SHOW EVENTS\G
*************************** 1. row ***************************
Db: testdb
Name: event_every_second
Definer: root@localhost
Time zone: SYSTEM
Type: RECURRING
Execute at: NULL
Interval value: 1
Interval field: SECOND
Starts: 2024-05-12 07:47:44
Ends: NULL
Status: ENABLED
Originator: 0
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: latin1_swedish_ci
1 row in set (0.01 sec)

MariaDB [testdb]> select *from mysql.event\G
*************************** 1. row ***************************
db: testdb
name: event_every_second
body: INSERT INTO events_list VALUES('event_now', now())
definer: root@localhost
execute_at: NULL
interval_value: 1
interval_field: SECOND
created: 2024-05-12 07:47:44
modified: 2024-05-12 07:47:44
last_executed: 2024-05-11 23:48:08
starts: 2024-05-11 23:47:44
ends: NULL
status: ENABLED
on_completion: DROP
sql_mode:
comment:
originator: 0
time_zone: SYSTEM
character_set_client: utf8
collation_connection: utf8_general_ci
db_collation: latin1_swedish_ci
body_utf8: INSERT INTO events_list VALUES('event_now', now())
1 row in set (0.00 sec)

MariaDB [testdb]> select *from events_list;
+------------+---------------------+
| event_name | event_started |
+------------+---------------------+
| event_now | 2024-05-12 07:41:42 |
| event_now | 2024-05-12 07:47:44 |
| event_now | 2024-05-12 07:47:45 |
| event_now | 2024-05-12 07:47:46 |
| event_now | 2024-05-12 07:47:47 |
| event_now | 2024-05-12 07:47:48 |
| event_now | 2024-05-12 07:47:49 |
| event_now | 2024-05-12 07:47:50 |
| event_now | 2024-05-12 07:47:51 |
| event_now | 2024-05-12 07:47:52 |
| event_now | 2024-05-12 07:47:53 |
| event_now | 2024-05-12 07:47:54 |
| event_now | 2024-05-12 07:47:55 |
| event_now | 2024-05-12 07:47:56 |
| event_now | 2024-05-12 07:47:57 |
| event_now | 2024-05-12 07:47:58 |
| event_now | 2024-05-12 07:47:59 |
| event_now | 2024-05-12 07:48:00 |
| event_now | 2024-05-12 07:48:01 |
| event_now | 2024-05-12 07:48:02 |
| event_now | 2024-05-12 07:48:03 |
| event_now | 2024-05-12 07:48:04 |
| event_now | 2024-05-12 07:48:05 |
| event_now | 2024-05-12 07:48:06 |
| event_now | 2024-05-12 07:48:07 |
| event_now | 2024-05-12 07:48:08 |
| event_now | 2024-05-12 07:48:09 |
| event_now | 2024-05-12 07:48:10 |
| event_now | 2024-05-12 07:48:11 |
| event_now | 2024-05-12 07:48:12 |
| event_now | 2024-05-12 07:48:13 |
| event_now | 2024-05-12 07:48:14 |
+------------+---------------------+
32 rows in set (0.00 sec)


#删除事件
MariaDB [testdb]> drop event event_every_second;
Query OK, 0 rows affected (0.00 sec)


#删除后确认事件是否为空
MariaDB [testdb]> SHOW EVENTS\G
Empty set (0.00 sec)
MariaDB [testdb]> select *from mysql.event\G
Empty set (0.00 sec)

🍊 范例:创建每分钟启动的事件

MariaDB [testdb]> show variables like 'event_scheduler';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| event_scheduler | ON   |
+-----------------+-------+
1 row in set (0.001 sec)


MariaDB [testdb]> create event testdb.event_every_minute   on schedule   every
1 minute    do insert into events_list values('event_now', now());
Query OK, 0 rows affected (0.001 sec)


MariaDB [testdb]> select now();
+---------------------+
| now()               |
+---------------------+
| 2019-12-02 22:39:12 |
+---------------------+
1 row in set (0.000 sec)
MariaDB [testdb]> select *from events_list;
+------------+---------------------+
| event_name | event_started       |
+------------+---------------------+
| event_now | 2019-12-02 22:39:10 |
+------------+---------------------+
MariaDB [testdb]> SHOW EVENTS\G
*************************** 1. row ***************************
  Db: testdb
              Name: event_every_minute
            Definer: root@localhost
          Time zone: SYSTEM
              Type: RECURRING
         Execute at: NULL
     Interval value: 1
     Interval field: MINUTE
             Starts: 2019-12-02 22:35:57
               Ends: NULL
             Status: ENABLED
        Originator: 1
character_set_client: utf8
collation_connection: utf8_general_ci
 Database Collation: latin1_swedish_ci
1 row in set (0.001 sec)
MariaDB [testdb]> select *from events_list;
+------------+---------------------+
| event_name | event_started       |
+------------+---------------------+
| event_now | 2019-12-02 22:39:10 |
| event_now | 2019-12-02 22:40:10 |
| event_now | 2019-12-02 22:41:10 |
| event_now | 2019-12-02 22:42:10 |
| event_now | 2019-12-02 22:43:10 |
| event_now | 2019-12-02 22:44:10 |
| event_now | 2019-12-02 22:45:10 |
+------------+---------------------+
7 rows in set (0.000 sec)

🍊 范例:创建定时调用存储过程的事件

MariaDB [testdb]> drop event event_every_minute;
Query OK, 0 rows affected (0.000 sec)
MariaDB [testdb]> truncate table events_list;
Query OK, 0 rows affected (0.010 sec)
MariaDB [testdb]> select *from events_list;
Empty set (0.000 sec)


MariaDB [testdb]> delimiter //
MariaDB [testdb]> create procedure sp_insert()  
  -> begin
  -> insert into events_list values('event_now', now());
  -> end//
Query OK, 0 rows affected (0.001 sec)
MariaDB [testdb]> delimiter ;


MariaDB [testdb]> CREATE DEFINER=`root`@`localhost` EVENT event_test ON SCHEDULE
EVERY 10 SECOND STARTS '2019-12-02 22:55:00' ON COMPLETION PRESERVE ENABLE DO
call sp_insert();
Query OK, 0 rows affected (0.001 sec)
MariaDB [testdb]> select now();
+---------------------+
| now()               |
+---------------------+
| 2019-12-02 22:51:57 |
+---------------------+
1 row in set (0.000 sec)


MariaDB [testdb]> select *from events_list;
+------------+---------------------+
| event_name | event_started       |
+------------+---------------------+
| event_now | 2019-12-02 22:55:00 |
| event_now | 2019-12-02 22:55:10 |
| event_now | 2019-12-02 22:55:20 |
| event_now | 2019-12-02 22:55:30 |
+------------+---------------------+
4 rows in set (0.000 sec)
MariaDB [testdb]>

🍊 范例:修改事件

MariaDB [testdb]> ALTER DEFINER=`root`@`localhost EVENT event_test ON SCHEDULE
EVERY 30 SECOND  ON COMPLETION PRESERVE ENABLE DO call sp_insert();

MariaDB [testdb]> select *from events_list;
+------------+---------------------+
| event_name | event_started       |
+------------+---------------------+
| event_now | 2019-12-02 22:55:00 |
| event_now | 2019-12-02 22:55:10 |
| event_now | 2019-12-02 22:55:20 |
| event_now | 2019-12-02 22:55:30 |
| event_now | 2019-12-02 22:55:40 |
| event_now | 2019-12-02 22:55:50 |
| event_now | 2019-12-02 22:56:00 |
| event_now | 2019-12-02 22:56:10 |
| event_now | 2019-12-02 22:56:20 |
| event_now | 2019-12-02 22:56:30 |
| event_now | 2019-12-02 22:56:40 |
| event_now | 2019-12-02 22:56:50 |
| event_now | 2019-12-02 22:57:00 |
| event_now | 2019-12-02 22:57:10 |
| event_now | 2019-12-02 22:57:20 |
| event_now | 2019-12-02 22:57:30 |
| event_now | 2019-12-02 22:57:40 |
| event_now | 2019-12-02 22:57:50 |
| event_now | 2019-12-02 22:58:00 |
| event_now | 2019-12-02 22:58:10 |
| event_now | 2019-12-02 22:58:20 |
| event_now | 2019-12-02 22:58:30 |
| event_now | 2019-12-02 22:58:40 |
| event_now | 2019-12-02 22:58:50 |
| event_now | 2019-12-02 22:59:00 |
| event_now | 2019-12-02 22:59:10 |
| event_now | 2019-12-02 22:59:18 |
| event_now | 2019-12-02 22:59:48 |
| event_now | 2019-12-02 23:00:18 |
| event_now | 2019-12-02 23:00:48 |
| event_now | 2019-12-02 23:01:18 |
| event_now | 2019-12-02 23:01:48 |
| event_now | 2019-12-02 23:02:18 |
| event_now | 2019-12-02 23:02:48 |
+------------+---------------------+
34 rows in set (0.001 sec)


#禁用事件
MariaDB [testdb]> alter event testdb.event_test disable;
MariaDB [testdb]> show events\G
*************************** 1. row ***************************
                Db: testdb
              Name: event_test
            Definer: root@localhost
          Time zone: SYSTEM
              Type: RECURRING
         Execute at: NULL
     Interval value: 30
     Interval field: SECOND
             Starts: 2019-12-02 22:59:18
               Ends: NULL
             Status: DISABLED
        Originator: 1
character_set_client: utf8
collation_connection: utf8_general_ci
 Database Collation: latin1_swedish_ci
1 row in set (0.001 sec)
MariaDB [testdb]> select now();
+---------------------+
| now()               |
+---------------------+
| 2019-12-02 23:09:02 |
+---------------------+
1 row in set (0.001 sec)
MariaDB [testdb]> select *from events_list;
+------------+---------------------+
| event_name | event_started       |
+------------+---------------------+
| event_now | 2019-12-02 22:55:00 |
| event_now | 2019-12-02 22:55:10 |
| event_now | 2019-12-02 22:55:20 |
| event_now | 2019-12-02 22:55:30 |
| event_now | 2019-12-02 22:55:40 |
| event_now | 2019-12-02 22:55:50 |
| event_now | 2019-12-02 22:56:00 |
| event_now | 2019-12-02 22:56:10 |
| event_now | 2019-12-02 22:56:20 |
| event_now | 2019-12-02 22:56:30 |
| event_now | 2019-12-02 22:56:40 |
| event_now | 2019-12-02 22:56:50 |
| event_now | 2019-12-02 22:57:00 |
| event_now | 2019-12-02 22:57:10 |
| event_now | 2019-12-02 22:57:20 |
| event_now | 2019-12-02 22:57:30 |
| event_now | 2019-12-02 22:57:40 |
| event_now | 2019-12-02 22:57:50 |
| event_now | 2019-12-02 22:58:00 |
| event_now | 2019-12-02 22:58:10 |
| event_now | 2019-12-02 22:58:20 |
| event_now | 2019-12-02 22:58:30 |
| event_now | 2019-12-02 22:58:40 |
| event_now | 2019-12-02 22:58:50 |
| event_now | 2019-12-02 22:59:00 |
| event_now | 2019-12-02 22:59:10 |
| event_now | 2019-12-02 22:59:18 |
| event_now | 2019-12-02 22:59:48 |
| event_now | 2019-12-02 23:00:18 |
| event_now | 2019-12-02 23:00:48 |
| event_now | 2019-12-02 23:01:18 |
| event_now | 2019-12-02 23:01:48 |
| event_now | 2019-12-02 23:02:18 |
| event_now | 2019-12-02 23:02:48 |
+------------+---------------------+
34 rows in set (0.001 sec)


#启用事件
MariaDB [testdb]> alter event testdb.event_test enable;
Query OK, 0 rows affected (0.000 sec)
MariaDB [testdb]> show events\G
*************************** 1. row ***************************
                Db: testdb
              Name: event_test
            Definer: root@localhost
          Time zone: SYSTEM
              Type: RECURRING
         Execute at: NULL
     Interval value: 30
     Interval field: SECOND
             Starts: 2019-12-02 22:59:18
               Ends: NULL
             Status: ENABLED
        Originator: 1
character_set_client: utf8
collation_connection: utf8_general_ci
 Database Collation: latin1_swedish_ci
1 row in set (0.001 sec)
MariaDB [testdb]> select *from events_list;
+------------+---------------------+
| event_name | event_started       |
+------------+---------------------+
| event_now | 2019-12-02 22:55:00 |
| event_now | 2019-12-02 22:55:10 |
| event_now | 2019-12-02 22:55:20 |
| event_now | 2019-12-02 22:55:30 |
| event_now | 2019-12-02 22:55:40 |
| event_now | 2019-12-02 22:55:50 |
| event_now | 2019-12-02 22:56:00 |
| event_now | 2019-12-02 22:56:10 |
| event_now | 2019-12-02 22:56:20 |
| event_now | 2019-12-02 22:56:30 |
| event_now | 2019-12-02 22:56:40 |
| event_now | 2019-12-02 22:56:50 |
| event_now | 2019-12-02 22:57:00 |
| event_now | 2019-12-02 22:57:10 |
| event_now | 2019-12-02 22:57:20 |
| event_now | 2019-12-02 22:57:30 |
| event_now | 2019-12-02 22:57:40 |
| event_now | 2019-12-02 22:57:50 |
| event_now | 2019-12-02 22:58:00 |
| event_now | 2019-12-02 22:58:10 |
| event_now | 2019-12-02 22:58:20 |
| event_now | 2019-12-02 22:58:30 |
| event_now | 2019-12-02 22:58:40 |
| event_now | 2019-12-02 22:58:50 |
| event_now | 2019-12-02 22:59:00 |
| event_now | 2019-12-02 22:59:10 |
| event_now | 2019-12-02 22:59:18 |
| event_now | 2019-12-02 22:59:48 |
| event_now | 2019-12-02 23:00:18 |
| event_now | 2019-12-02 23:00:48 |
| event_now | 2019-12-02 23:01:18 |
| event_now | 2019-12-02 23:01:48 |
| event_now | 2019-12-02 23:02:18 |
| event_now | 2019-12-02 23:02:48 |
| event_now | 2019-12-02 23:11:48 |
| event_now | 2019-12-02 23:12:18 |
+------------+---------------------+
36 rows in set (0.000 sec)


#修改事件名称
MariaDB [testdb]> alter event testdb.event_test  rename to event_test2;
Query OK, 0 rows affected (0.001 sec)
MariaDB [testdb]> show events\G
*************************** 1. row ***************************
                Db: testdb
              Name: event_test2
            Definer: root@localhost
          Time zone: SYSTEM
              Type: RECURRING
         Execute at: NULL
     Interval value: 30
     Interval field: SECOND
             Starts: 2019-12-02 22:59:18
               Ends: NULL
             Status: ENABLED
        Originator: 1
character_set_client: utf8
collation_connection: utf8_general_ci
 Database Collation: latin1_swedish_ci
1 row in set (0.001 sec)
MariaDB [testdb]> drop event event_test2;
Query OK, 0 rows affected (0.000 sec)
MariaDB [testdb]> show events;
Empty set (0.001 sec)

MySQL用户管理

相关数据库和表

元数据数据库:mysql
系统授权表:db, host, user,columns_priv, tables_priv, procs_priv, proxies_priv

用户帐号

'USERNAME'@'HOST'

@'HOST':
主机名: user1@'web1.magedu.org'

IP地址或Network
通配符: %   _
示例:172.16.%.% user2@'192.168.1.%'

创建用户

CREATE USER 'USERNAME'@'HOST' [IDENTIFIED BY 'password']

新建用户的默认权限:USAGE

用户重命名

RENAME USER old_user_name TO new_user_name;

删除用户

DROP USER 'USERNAME'@'HOST‘

🍊 范例:删除默认的空用户

DROP USER ''@'localhost';

修改密码

[!NOTE]

  • 新版mysql中用户密码可以保存在mysql.user表的authentication_string字段中
  • 如果mysql.user表的authentication_string和password字段都保存密码,authentication_string优先生效;
#方法1
SET PASSWORD FOR 'user'@'host' = PASSWORD('password'); #这个命令会直接生效的,如果更新表的话,需要执行`FLUSH PRIVILEGES;`才会生效;


#方法2
UPDATE mysql.user SET password=PASSWORD('password') WHERE clause;
或者
UPDATE mysql.user SET authentication_string=PASSWORD('password') WHERE clause;


#mariadb 10.3
update mysql.user set authentication_string=password('ubuntu') where user='mage';
#此方法需要执行下面指令才能生效:
FLUSH PRIVILEGES;


##方法3:
mysql -u root -p
USE mysql;
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';

🍊 范例:修改用户密码

方法1
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('xyy520'); #推荐:

方法2
update mysql.user set password=password('xyy520') where user='root';
FLUSH PRIVILEGES;
或者
update mysql.user set authentication_string=password('magedu') where user='root';
FLUSH PRIVILEGES;

忘记管理员密码的解决办法

  1. 启动mysqld进程时,为其使用如下选项:

    --skip-grant-tables 
    --skip-networking
  2. 使用UPDATE命令修改管理员密码

  3. 关闭mysqld进程,移除上述两个选项,重启mysqld

🍊 范例:破解root密码

[root@centos8 ~]#vim /etc/my.cnf
[mysqld]
skip-grant-tables                                                              
skip-networking

[root@centos8 ~]#systemctl restart mariadb
[root@centos8 ~]#mysql

#mariadb 新版
MariaDB [(none)]> update mysql.user set authentication_string=password('ubuntu') where user='root';
#mariadb 旧版
MariaDB [(none)]> update mysql.user set password=password('ubuntu') where user='root';


[root@centos8 ~]#systemctl restart mariadb
[root@centos8 ~]#vim /etc/my.cnf
[mysqld]
#skip-grant-tables                                                              
#skip-networking
[root@centos8 ~]#systemctl restart mariadb
[root@centos8 ~]#mysql -uroot -pubuntu

权限管理和DCL语句

权限类别:

  • 管理类
  • 程序类
  • 数据库级别
  • 表级别
  • 字段级别

管理类:

  • CREATE USER
  • FILE
  • SUPER
  • SHOW DATABASES
  • RELOAD
  • SHUTDOWN
  • REPLICATION SLAVE 能实现数据库的复制;
  • REPLICATION CLIENT
  • LOCK TABLES
  • PROCESS
  • CREATE TEMPORARY TABLES

程序类:针对 FUNCTION、PROCEDURE、TRIGGER

  • CREATE
  • ALTER
  • DROP
  • EXCUTE

库和表级别:针对 DATABASE、TABLE

  • ALTER
  • CREATE
  • CREATE VIEW
  • DROP INDEX
  • SHOW VIEW
  • WITH GRANT OPTION:能将自己获得的权限转赠给其他用户

数据操作

  • SELECT
  • INSERT
  • DELETE
  • UPDATE

字段级别

  • SELECT(col1,col2,...)
  • UPDATE(col1,col2,...)
  • INSERT(col1,col2,...)

所有权限

  • ALL PRIVILEGES 或 ALL

授权:GRANT

GRANT priv_type [(column_list)],... ON [object_type] priv_level TO 'user'@'host' 
[IDENTIFIED BY 'password'] [WITH GRANT OPTION];
priv_type: ALL [PRIVILEGES]
object_type:TABLE | FUNCTION | PROCEDURE
priv_level: *(所有库) |*.*   | db_name.* | db_name.tbl_name | tbl_name(当前库
的表) | db_name.routine_name(指定库的函数,存储过程,触发器)
with_option: GRANT OPTION
| MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count

参考:https://dev.mysql.com/doc/refman/5.7/en/grant.html

🍊 范例:

GRANT SELECT (col1), INSERT (col1,col2) ON mydb.mytbl TO 'someuser'@'somehost‘;
GRANT ALL ON wordpress.* TO wordpress@'192.168.8.%' IDENTIFIED BY 'magedu';

GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.8.%' IDENTIFIED BY 'magedu' WITH GRANT OPTION;


GRANT ALL ON hellodb.* TO test@'192.168.8.%';



#生产里推荐,一条命令完成创建用户+赋予用户权限事项。
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'172.29.9.%' IDENTIFIED BY 'magedu' WITH GRANT OPTION;

查看指定用户获得的授权

Help SHOW GRANTS

SHOW GRANTS FOR 'user'@'host';
SHOW GRANTS FOR CURRENT_USER[()];

取消授权:REVOKE

REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ... ON
[object_type] priv_level FROM user [, user] ...

参考:https://dev.mysql.com/doc/refman/5.7/en/revoke.html

范例:

REVOKE DELETE ON testdb.* FROM 'testuser'@‘172.16.0.%;

[!NOTE]

注意:MariaDB服务进程启动时会读取mysql库中所有授权表至内存

(1) GRANT或REVOKE等执行权限操作会保存于系统表中,MariaDB的服务进程通常会自动重读授权表,使之生效

(2) 对于不能够或不能及时重读授权表的命令,可手动让MariaDB的服务进程重读授权表:mysql> FLUSH PRIVILEGES;

MySQL的图形化的远程管理工具

在MySQL数据库中创建用户并授权后,可以使用相关图形化工具进行远程的管理。

常见的图形化管理工具:

  • Navicat
  • SQLyog

image-20240514063144349

image-20240514063157929

SQLyog 工具

image-20240514064935314

image-20240514064720187

4、MySQL架构和性能优化

image-20240514070532072

thread reuse 线程复用
optimizer 优化器

MySQL是C/S 架构的,connectors是连接器;可供Native C API、JDBC、ODBC、NET、PHP、Perl、Python、Ruby、Cobol等连接mysql;ODBC叫开放数据库(系统)互联,open database connection;JDBC是主要用于java语言利用较为底层的驱动连接数据库;

以上这些,站在编程角度可以理解为连入数据库管理系统的驱动,站在mysql角度称作专用语言对应的链接器。任何链接器连入mysql以后,mysql是单进程多线程模型的,因此,每个用户连接,都会创建一个单独的连接线程;其实mysql连接也有长短连接两种方式,使用mysql客户端连入数据库后,直到使用quit命令才退出,可认为是长连接;使用mysql中的-e选项,在mysql客户端向服务器端申请运行一个命令后则立即退出,也就意味着连接会立即断开;所以,mysql也支持长短连接类似于两种类型;

所以,用户连入mysql后,创建一个连接线程,完成之后,能够通过这个链接线程完成接收客户端发来的请求,为其处理请求,构建响应报文并发给客户端;由于是单进程模型,就意味着必须要维持一个线程池,跟之前介绍过的varnish很接近,需要一个线程池来管理这众多线程是如何对众多客户端的并发请求,完成并发响应的,组件connection pool就是实现样功能;

connection pool对于mysql而言,它所实现的功能,包括authentication认证,用户发来的账号密码是否正确要完成认证功能;thread reuse线程重用功能,一般当一个用户连接进来以后要用一个线程来响应它,而后当用户退出这个线程有可能并非被销毁,而是把它清理完以后,重新收归到线程池当中的空闲线程中去,以完成所谓的线程重用;connection limit 线程池的大小决定了连接并发数量的上限,例如,最多容纳100线程,一旦到达此上限后续到达的连接请求则只能排队或拒绝连接;check memory用来检测内存,caches实现线程缓存;整个都属于线程池的功能.当用户请求之后,通过线程池建立一个用户连接,这个线程一直存在,然后用户就通过这个会话,发送对应的SQL语句到服务器端.

服务器收到SQL语句后,要对语句完成执行,首先要能理解sql语句需要有sql解释器或叫sql接口sql interface就可理解为是整个mysql的外壳,就像shell是linux操作系统的外壳一样道理;用户无论通过哪种链接器发来的基本的SQL请求,当然,事实上通过native C API也有发过来的不是SQL 请求,而仅仅是对API中的传递参数后的调用;不是SQL语句不过都统统理解为sql语句罢了;对SQL而言分为DDL 和DML两种类型,但是无论哪种类型,提交以后必须交给内核,让内核来运行,在这之前必须要告诉内核哪个是命令,哪个是选项,哪些是参数,是否存在语法错误等等;因此,这个整个SQL 接口就是一个完完整整的sql命令的解释器,并且这个sql接口还有提供完整的sql接口应该具备的功能,比如支持所谓过程式编程,支持代码块的实现像存储过程、存储函数,触发器、必要时还要实现部署一个关系型数据库应该具备的基本组件例如视图等等,其实都在sql interface这个接口实现的;SQL接口做完词法分析、句法分析后,要分析语句如何执行让parser解析器或分析器实现,parser是专门的分析器,这个分析器并不是分析语法问题的,语法问题在sql接口时就能发现是否有错误了,一个语句没有问题,就要做执行分析,所谓叫查询翻译,把一个查询语句给它转换成对应的能够在本地执行的特定操作;比如说看上去是语句而背后可能是执行的一段二进制指令,这个时候就完成对应的指令,还要根据用户请求的对象,比如某一字段查询内容是否有对应数据的访问权限,或叫对象访问权限;在数据库中库、表、字段、字段中的数据有时都称为object,叫一个数据库的对象,用户认证的通过,并不意味着就能一定能访问数据库上的所有数据,所以说,mysql的认证大概分为两过程都要完成,第一是连入时需要认证账号密码是否正确这是authentication,然后,验证成功后用户发来sql语句还要验证用户是否有权限获取它期望请求获取的数据;这个称为object privilege,这一切都是有parser分析器进行的。

分析器分析完成之后,可能会生成多个执行树,这意味着为了能够达到访问期望访问到的目的,可能有多条路径都可实现,就像文件系统一样可以使用相对路径也可使用绝对路径;它有多种方式,在多种路径当中一定有一个是最优的,类似路由选择,因此,优化器就要去衡量多个访问路径中哪一个代价或开销是最小的,这个开销的计算要依赖于索引等各种内部组件来进行评估;而且这个评估的只是近似值,同时还要考虑到当前mysql内部在实现资源访问时统计数据,比如,根据判断认为是1号路径的开销最小的,但是众多统计数据表明发往1号路径的访问的资源开销并不小,并且比3号路径大的多,因此,可能会依据3号路径访问;这就是所谓的优化器它负责检查多条路径,每条路径的开销,然后评估开销,这个评估根据内部的静态数据,索引,根域根据动态生成的统计数据来判定每条路径的开销大小,因此这里还有statics;一旦优化完成之后,还要生成统计数据,这就是优化器的作用;如果没有优化器mysql执行语句是最慢的,其实优化还包括一种功能,一旦选择完一条路径后,例如用户给的这个命令执行起来,大概需要100个开销,如果通过改写语句能够达到同样目的可能只需要30个开销;于是,优化器还要试图改写sql语句;所以优化本身还包括查询语句的改写;一旦优化完成,接下来就交给存储引擎完成.

mysql是插件式存储引擎,它就能够替换使用选择多种不同的引擎,MyISAM是MySQL 经典的存储引擎之一,InnoDB是由Innobase Oy公司所开发,2006年五月由甲骨文公司并购提供给MySQL的,NDB主要用于MySQL Cluster 分布式集群环境,archive做归档的等等,还有许多第三方开发的存储引擎;存储引擎负责把具体分析的结果完成对磁盘上文件路径访问的转换,数据库中的行数据都是存储在磁盘块上的,因此存储引擎要把数据库数据映射为磁盘块,并把磁盘块加载至内存中;进程实现数据处理时,是不可能直接访问磁盘上的数据的,因为它没有权限,只有让内核来把它所访问的数据加载至内存中以后,进程在内存中完成修改,由内核再负责把数据存回磁盘;对于文件系统而言,数据的存储都是以磁盘块方式存储的,但是,mysql在实现数据组织时,不完全依赖于磁盘,而是把磁盘块再次组织成更大一级的逻辑单位,类似于lvm中的PE或LE的形式;其实,MySQL的存储引擎在实现数据管理时,也是在文件系统之上布设文件格式,对于文件而言在逻辑层上还会再次组织成一个逻辑单位,这个逻辑单位称为mysql的数据块datablock 一般为16k ,对于关系型数据库,数据是按行存储的;一般一行数据都是存储在一起的,因此,MySQL 在内部有一个数据块datablock,在datablock就存储一行数据,一个数据块里可能存放了n行数据;将来在查询加载一行数据时,内核会把整个一个数据数据块加载至内存中,而mysql存储引擎,就从中挑出来某一行返回给查询者,是这样实现的;所以整个存储是以datablock在底层为其最终级别的.

事实上,整个存取过程,尤其是访问比较热点的数据,也不可能每一次当用户访问时或当某SQL语句用到时再临时从磁盘加载到内存中,因此,为了能够加上整个性能,mysql的有些存储引擎可以实现,把频繁访问到的热点数据,统统装入内存,用户访问、修改时直接在内存中操作,只不过周期性的写入磁盘上而已,比如像InnoDB,所以caches和buffers组件就是实现此功能的;MySQL为了执行加速,因为它会不断访问数据,而随计算机来说io是最慢的一环,尤其是磁盘io,所以为了加速都载入内存中管理;这就需要MySQL 维护cache和buffer缓存或缓冲;这是由MySQL 服务器自己维护的;有很多存储引擎自己也有cache和buffer;一个数据库提供了3种视图,物理视图就是看到的对应的文件系统存储为一个个的文件,MySQL的数据文件类型,常见的有redo log重做日志,undo log撤销日志,data是真正的数据文件,index是索引文件,binary log是二进制日志文件,error log错误日志,query log查询日志,slow query log慢查询日志,在复制架构中还存在中继日志文件,跟二进制属于同种格式;这是mysql数据文件类型,也就是物理视图;逻辑视图这是在mysql接口上通过存储引擎把mysql文件尤其是data文件,给它映射为一个个关系型数据库应该具备组成部分,比如表,一张表在底层是一个数据文件而已,里面组织的就是datablock,最终映射为磁盘上文件系统的block,然后再次映射为本地扇区的存储,但是整个mysql需要把他们映射成一个二维关系表的形式,需要依赖sql接口以及存储引擎共同实现;所以,把底层数据文件映射成关系型数据库的组件就是逻辑视图;DBA 就是关注内部组件是如何运作的,并且定义、配置其运作模式,而链接器都是终端用户通过链接器的模式进入数据库来访问数据;数据集可能非常大,每一类用户可能只有一部分数据的访问权限,这个时候,最终的终端用户所能访问到的数据集合称作用户视图;为了保证MySQL运作还提供了管理和服务工具,例如:备份恢复工具,安全工具,复制工具,集群服务,管理、配置、迁移、元数据等工具。

存储引擎

image-20240514070649532

MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力,此种技术称为存储擎,MySQL 支持多种存储引擎其中目前应用最广泛的是InnoDB和MyISAM两种。

官方参考资料https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/storage-engines.html

image-20240515065651560

image-20240515065702806

1.MyISAM存储引擎

面试:总爱问MyISAM和InnoDB 两种存储引擎的区别。

MyISAM引擎特点

  • 不支持事务表级锁定
  • 读写相互阻塞,写入不能读,读时不能写
  • 只缓存索引
  • 不支持外键约束
  • 不支持聚簇索引
  • 读取数据较快,占用资源较少
  • 不支持MVCC(多版本并发控制机制)高并发
  • 崩溃恢复性较差
  • MySQL5.5.5前默认的数据库引擎

MyISAM****存储引擎适用场景

  • 只读(或者写较少)
  • 表较小(可以接受长时间进行修复操作)

MyISAM引擎文件

  • tbl_name.frm 表格式定义
  • tbl_name.MYD 数据文件
  • tbl_name.MYI 索引文件

image-20240515065418281

2.InnoDB引擎

InnoDB引擎特点

  • 行级锁
  • 支持事务,适合处理大量短期事务
  • 读写阻塞与事务隔离级别相关
  • 可缓存数据和索引
  • 支持聚簇索引
  • 崩溃恢复性更好
  • 支持MVCC高并发
  • 从MySQL5.5后支持全文索引
  • 从MySQL5.5.5开始为默认的数据库引擎

InnoDB数据库文件

image-20240515071737917

  • 所有InnoDB表的数据和索引放置于同一个表空间中
数据文件:ibdata1, ibdata2,存放在datadir定义的目录下
表格式定义:tb_name.frm,存放在datadir定义的每个数据库对应的目录下
  • 每个表单独使用一个表空间存储表的数据和索引
两类文件放在对应每个数据库独立目录中
数据文件(存储数据和索引):tb_name.ibd
表格式定义:tb_name.frm

启用:innodb_file_per_table=ON (MariaDB 5.5以后版是默认值)

参看:https://mariadb.com/kb/en/library/xtradbinnodb-server-system-variables/#innodb_file_per_table

07:27:05(root@localhost) [(none)]> show variables like 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
1 row in set (0.001 sec)

其它存储引擎

  • Performance_Schema:Performance_Schema数据库使用。

  • Memory :将所有数据存储在RAM中,以便在需要快速查找参考和其他类似数据的环境中进行快速访问。适用存放临时数据。引擎以前被称为HEAP引擎。

  • MRG_MyISAM:使MySQL DBA或开发人员能够对一系列相同的MyISAM表进行逻辑分组,并将它们作为一个对象引用。适用于VLDB(Very Large Data Base)环境,如数据仓库。

  • Archive :为存储和检索大量很少参考的存档或安全审核信息,只支持SELECT和INSERT操作;支持行级锁和专用缓存区

  • Federated联合:用于访问其它远程MySQL服务器一个代理,它通过创建一个到远程MySQL服务器的客户端连接,并将查询传输到远程服务器执行,而后完成数据存取,提供链接单独MySQL服务器的能力,以便从多个物理服务器创建一个逻辑数据库。非常适合分布式或数据集市环境

  • BDB:可替代InnoDB的事务引擎,支持COMMIT、ROLLBACK和其他事务特性

  • Cluster/NDB:MySQL的簇式数据库引擎,尤其适合于具有高性能查找要求的应用程序,这类查找需求还要求具有最高的正常工作时间和可用性

  • CSV:CSV存储引擎使用逗号分隔值格式将数据存储在文本文件中。可以使用CSV引擎以CSV格式导入和导出其他软件和应用程序之间的数据交换

  • BLACKHOLE :黑洞存储引擎接受但不存储数据,检索总是返回一个空集。该功能可用于分布式数据库设计,数据自动复制,但不是本地存储

  • example:“stub”引擎,它什么都不做。可以使用此引擎创建表,但不能将数据存储在其中或从中检索。目的是作为例子来说明如何开始编写新的存储引擎

管理存储引擎

  • 查看mysql支持的存储引擎
SHOW ENGINES;
  • 查看当前默认的存储引擎
05:15:56(root@localhost) [(none)]> show variables like '%storage_engine%';
+----------------------------+--------+
| Variable_name | Value |
+----------------------------+--------+
| default_storage_engine | InnoDB |
| default_tmp_storage_engine | |
| enforce_storage_engine | |
| storage_engine | InnoDB |
+----------------------------+--------+
4 rows in set (0.001 sec)
  • 设置默认的存储引擎
vim /etc/my.cnf
[mysqld]
default_storage_engine= InnoDB
  • 查看库中所有表使用的存储引擎
show table status from mysql\G
……
*************************** 30. row ***************************
Name: transaction_registry
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 0
Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
Index_length: 49152
Data_free: 0
Auto_increment: NULL
Create_time: 2024-03-29 06:02:16
Update_time: NULL
Check_time: NULL
Collation: utf8_bin
Checksum: NULL
Create_options: stats_persistent=0
Comment:
Max_index_length: 0
Temporary: N
……
  • 查看库中指定表的存储引擎
show table status like  'tb_name';
show create table tb_name;
  • 设置表的存储引擎:
CREATE TABLE tb_name(... ) ENGINE=InnoDB;
ALTER TABLE tb_name ENGINE=InnoDB;

MySQL中的系统数据库

  • mysql数据库

    是mysql的核心数据库,类似于Sql Server中的master库,主要负责存储数据库的用户、权限设置、关键字等mysql自己需要使用的控制和管理信息

  • performance_schema数据库

    MySQL 5.5开始新增的数据库,主要用于收集数据库服务器性能参数,库里表的存储引擎均为PERFORMANCE_SCHEMA,用户不能创建存储引擎为PERFORMANCE_SCHEMA的表

  • information_schema数据库

    MySQL 5.0之后产生的,一个虚拟数据库,物理上并不存在information_schema数据库,类似与“数据字典”,提供了访问数据库元数据的方式,即数据的数据。比如数据库名或表名,列类型,访问权限(更加细化的访问方式)

  • sys数据库

    MySQL5.7之后新增加的数据库,库中所有数据源来自performance_schema。目标是把performance_schema的把复杂度降低,让DBA能更好的阅读这个库里的内容。让DBA更快的了解DB的运行情况

服务器配置和状态

可以通过mysqld选项,服务器系统变量和服务器状态变量进行MySQL的配置和查看状态

官方帮助:

https://dev.mysql.com/doc/refman/5.7/en/server-option-variable-reference.html

https://mariadb.com/kb/en/library/full-list-of-mariadb-options-system-and-status-variables/

mysql:

image-20240517075634637

mariadb:

image-20240520054535443

注意

  • 其中有些参数支持运行时修改,会立即生效
  • 有些参数不支持动态修改,且只能通过修改配置文件,并重启服务器程序生效
  • 有些参数作用域是全局的,为所有会话设置
  • 有些可以为每个用户提供单独(会话)的设置

1.服务器选项

这2行是yes的就是服务器选项:

image-20240520053016532

获取mysqld的可用选项列表:

#查看mysqld可用选项列表和及当前值
mysqld --verbose --help

#获取mysqld当前启动选项
mysqld --print-defaults
  • 范例:
[root@test ~]# mysqld --verbose --help|grep datadir
……
datadir /var/lib/mysql/


[root@test ~]# mysqld --verbose --help|grep skip-grant-tables
skip-grant-tables FALSE

设置服务器选项方法:

  1. 在命令行中设置

    shell> /usr/bin/mysqld_safe --skip-name-resolve=1
    shell> /usr/libexec/mysqld --basedir=/usr
  2. 在配置文件my.cnf中设置

    范例:

    #vim /etc/my.cnf

    [mysqld]
    skip_name_resolve=1
    skip-grant-tables
  • 范例: skip-grant-tables是服务器选项,但不是系统变量
[root@test ~]# mysqladmin variables |grep skip-grant-tables
[root@test ~]# mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 270
Server version: 10.5.24-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show variables like 'skip-grant-variables';
Empty set (0.001 sec)

MariaDB [(none)]>

image-20240520053503137

2.服务器系统变量

服务器系统变量:可以分全局和会话两种

获取系统变量:

SHOW GLOBAL VARIABLES; #只查看global变量
SHOW [SESSION] VARIABLES;#查看所有变量(包括global和session)


#查看指定的系统变量
SHOW VARIABLES LIKE 'VAR_NAME';
SELECT @@VAR_NAME;


#查看选项和部分变量
[root@centos8 ~]#mysqladmin variables
[root@test ~]# mysql -e 'show variables'|wc -l
668
[root@test ~]# mysql -e 'show global variables'|wc -l
649
[root@test ~]# mysql -e 'show session variables'|wc -l
668

修改服务器变量的值:

help SET

修改全局变量:仅对修改后新创建的会话有效;对已经建立的会话无效

SET GLOBAL system_var_name=value;
SET @@global.system_var_name=value;

修改会话变量:

SET [SESSION] system_var_name=value;
SET @@[session.]system_var_name=value;

范例:修改变量server_id的值

[root@test ~]# mysql -e 'show global variables'|grep server_id
server_id 1
[root@test ~]# mysql -e 'show session variables'|grep server_id
server_id 1



MariaDB [(none)]> set global server_id=200;
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 200 |
+-------------+
1 row in set (0.000 sec)

MariaDB [(none)]> set session server_id=300;
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 300 |
+-------------+
1 row in set (0.000 sec)

image-20240520060050756

范例:查看系统变量的值

MariaDB [(none)]> show variables like 'datadir'; #这个变量不支持动态修改。
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| datadir | /var/lib/mysql/ |
+---------------+-----------------+
1 row in set (0.001 sec)

MariaDB [(none)]> set global datadir='/data';
ERROR 1238 (HY000): Variable 'datadir' is a read only variable

image-20240520060811504

范例:修改mysql的最大并发连接数

MariaDB [(none)]> show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
1 row in set (0.001 sec)

MariaDB [(none)]> set max_connections=5000;
ERROR 1229 (HY000): Variable 'max_connections' is a GLOBAL variable and should be set with SET GLOBAL
MariaDB [(none)]> set global max_connections=5000;
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 5000 |
+-----------------+-------+
1 row in set (0.001 sec)

image-20240520061729828

这个max_connections既是服务器选项,又是全局系统变量,因此支持写到系统配置文件的。vim /etc/my.cnf

#vim /etc/my.cnf
[mysqld]
max_connections = 8000

[root@centos8 ~]#systemctl restart mariadb
[root@centos8 ~]#mysql -uroot -p
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 9
Server version: 10.3.11-MariaDB-log MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> select @@max_connections;
+-------------------+
| @@max_connections |
+-------------------+
|               594 |
+-------------------+
1 row in set (0.000 sec)


##还需要配置如下设置:
#方法1
[root@centos8 ~]#vim /usr/lib/systemd/system/mariadb.service
[Service]
#加下面一行
LimitNOFILE=65535

#方法2
[root@centos8 ~]#mkdir /etc/systemd/system/mariadb.service.d/
[root@node3 ~]#vim /etc/systemd/system/mariadb.service.d/limits.conf
[Service]
LimitNOFILE=65535

[root@centos8 ~]#systemctl daemon-reload
[root@centos8 ~]#systemctl restart mariadb
[root@centos8 ~]#mysql -uroot -p -e "select @@max_connections"
Enter password:
+-------------------+
| @@max_connections |
+-------------------+
|              8000 |
+-------------------+

范例: character_set_results是系统变量并非服务器选项

MariaDB [(none)]> show variables like 'character%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.001 sec)

MariaDB [(none)]> set character_set_results='utf8mb4';
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> show variables like 'character%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.001 sec)


#character_set_results不是服务器选项,写入配置文件将导致无法启动
[root@test ~]# vim /etc/my.cnf
[mysqld]
character_set_results=utf8mb4


[root@test ~]# systemctl restart mariadb
Job for mariadb.service failed because the control process exited with error code. See "systemctl status mariadb.service" and "journalctl -xe" for details.
[root@test ~]# systemctl status mariadb
● mariadb.service - MariaDB 10.5.24 database server
Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; vendor preset: disabled)
Drop-In: /etc/systemd/system/mariadb.service.d
└─migrated-from-my.cnf-settings.conf
Active: failed (Result: exit-code) since Mon 2024-05-20 06:54:43 CST; 5s ago
Docs: man:mariadbd(8)
https://mariadb.com/kb/en/library/systemd/
……
id 1331
May 20 06:54:42 test mariadbd[29643]: 2024-05-20 6:54:42 0 [Note] Plugin 'FEEDBACK' is disabled.
May 20 06:54:42 test mariadbd[29643]: 2024-05-20 6:54:42 0 [ERROR] /usr/sbin/mariadbd: unknown variable 'character_set_results=utf8mb4'
May 20 06:54:42 test mariadbd[29643]: 2024-05-20 6:54:42 0 [ERROR] Aborting
May 20 06:54:43 test systemd[1]: mariadb.service: main process exited, code=exited, status=7/NOTRUNNING
May 20 06:54:43 test systemd[1]: Failed to start MariaDB 10.5.24 database server.
May 20 06:54:43 test systemd[1]: Unit mariadb.service entered failed state.
May 20 06:54:43 test systemd[1]: mariadb.service failed.
Hint: Some lines were ellipsized, use -l to show in full.

image-20240520065623904

范例:修改页大小

参看:https://mariadb.com/kb/en/innodb-system-variables/#innodb_page_size

说明:初始化数据目录后,不能更改此系统变量的值。 在MariaDB实例启动时设置InnoDB的页面大小,此后保持不变。

[root@centos8 ~]#mysqladmin variables |grep innodb_page_size
| innodb_page_size                                       | 16384
[root@centos8 ~]#mysql
MariaDB [(none)]> show variables like "innodb_page_size";
+------------------+-------+
| Variable_name   | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
1 row in set (0.001 sec)


[root@centos8 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
innodb_page_size=64k
[root@centos8 ~]#rm -rf /var/lib/mysql/*
[root@centos8 ~]#systemctl restart mariadb


[root@centos8 ~]#mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 9
Server version: 10.3.11-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> show variables like "innodb_page_size";
+------------------+-------+
| Variable_name   | Value |
+------------------+-------+
| innodb_page_size | 65536 |
+------------------+-------+
1 row in set (0.001 sec)

image-20240520072714262

3.服务器状态变量

服务器状态变量:分全局和会话两种

状态变量(只读):用于保存mysqld运行中的统计数据的变量,不可更改

SHOW GLOBAL STATUS;
SHOW [SESSION] STATUS;

范例:

注意:这个系统变量只对本地当前终端会话有效果。

[root@test2 ~]#mysql -e 'show variables'|grep -i com_select
[root@test2 ~]#mysql -e 'show status'|grep -i com_select
Com_select 0


07:40:55(root@localhost) [(none)]> show global status like 'com_select';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_select | 6 |
+---------------+-------+
1 row in set (0.000 sec)

07:40:58(root@localhost) [(none)]> select user,host from mysql.user;
+-------------+-------------+
| User | Host |
+-------------+-------------+
| admin | 172.29.%.% |
| admin | 172.29.9.% |
| test | 172.29.9.% |
| admin | 192.168.8.% |
| mariadb.sys | localhost |
| mysql | localhost |
| root | localhost |
+-------------+-------------+
7 rows in set (0.018 sec)

07:41:08(root@localhost) [(none)]> show global status like 'com_select';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_select | 7 |
+---------------+-------+
1 row in set (0.001 sec)

07:41:11(root@localhost) [(none)]>

服务器变量 SQL_MODE

SQL_MODE:对其设置可以完成一些约束检查的工作,可分别进行全局的设置或当前会话的设置

参考:

https://mariadb.com/kb/en/library/sql-mode/

https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_sql-mode

常见MODE:

NO_AUTO_CREATE_USER: 禁止GRANT创建密码为空的用户

NO_ZERO_DATE:在严格模式,不允许使用‘0000-00-00’的时间

ONLY_FULL_GROUP_BY: 对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY

中出现,那么将认为这个SQL是不合法的

NO_BACKSLASH_ESCAPES: 反斜杠“\”作为普通字符而非转义字符

PIPES_AS_CONCAT: 将"||"视为连接操作符而非“或”运算符

范例:CentOS 7 修改SQL_MODE变量实现分组语句控制

06:30:20(root@localhost) [hellodb]> select @@sql_mode;
+-------------------------------------------------------------------------------------------+
| @@sql_mode |
+-------------------------------------------------------------------------------------------+
| STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------+
1 row in set (0.000 sec)

06:30:42(root@localhost) [hellodb]> select classid,count(*) from students group by classid;
+---------+----------+
| classid | count(*) |
+---------+----------+
| NULL | 2 |
| 1 | 4 |
| 2 | 3 |
| 3 | 4 |
| 4 | 4 |
| 5 | 1 |
| 6 | 4 |
| 7 | 3 |
+---------+----------+
8 rows in set (0.011 sec)
06:30:42(root@localhost) [hellodb]> select classid,count(*) from students group by classid;
+---------+----------+
| classid | count(*) |
+---------+----------+
| NULL | 2 |
| 1 | 4 |
| 2 | 3 |
| 3 | 4 |
| 4 | 4 |
| 5 | 1 |
| 6 | 4 |
| 7 | 3 |
+---------+----------+
8 rows in set (0.011 sec)


#修改SQL_MODE
06:32:54(root@localhost) [hellodb]> set sql_mode="ONLY_FULL_GROUP_BY";
Query OK, 0 rows affected (0.000 sec)

06:33:01(root@localhost) [hellodb]> show variables like 'sql_mode';
+---------------+--------------------+
| Variable_name | Value |
+---------------+--------------------+
| sql_mode | ONLY_FULL_GROUP_BY |
+---------------+--------------------+
1 row in set (0.001 sec)


06:33:10(root@localhost) [hellodb]> select classid,count(*) from students group by classid;^C
06:33:10(root@localhost) [hellodb]> select stuid,classid,count(*) from students group by classid;
ERROR 1055 (42000): 'hellodb.students.StuID' isn't in GROUP BY
06:33:46(root@localhost) [hellodb]> select classid,count(*) from students group by classid;
+---------+----------+
| classid | count(*) |
+---------+----------+
| NULL | 2 |
| 1 | 4 |
| 2 | 3 |
| 3 | 4 |
| 4 | 4 |
| 5 | 1 |
| 6 | 4 |
| 7 | 3 |
+---------+----------+
8 rows in set (0.000 sec)

范例:CentOS 7 修改SQL_MODE变量

06:33:53(root@localhost) [hellodb]> create table test (id int ,name varchar(3));
Query OK, 0 rows affected (0.016 sec)

06:40:59(root@localhost) [hellodb]> insert test values(1,'abcde');
Query OK, 1 row affected, 1 warning (0.001 sec)

06:41:06(root@localhost) [hellodb]> show warnings;
+---------+------+-------------------------------------------+
| Level | Code | Message |
+---------+------+-------------------------------------------+
| Warning | 1265 | Data truncated for column 'name' at row 1 |
+---------+------+-------------------------------------------+
1 row in set (0.000 sec)

06:41:11(root@localhost) [hellodb]> select * from test;
+------+------+
| id | name |
+------+------+
| 1 | abc |
+------+------+
1 row in set (0.000 sec)

06:41:17(root@localhost) [hellodb]> show variables like 'SQL_MODE';
+---------------+--------------------+
| Variable_name | Value |
+---------------+--------------------+
| sql_mode | ONLY_FULL_GROUP_BY |
+---------------+--------------------+
1 row in set (0.001 sec)

06:41:23(root@localhost) [hellodb]> SET SQL_MODE=TRADITIONAL;
Query OK, 0 rows affected (0.000 sec)

06:41:28(root@localhost) [hellodb]> show variables like 'SQL_MODE';
+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
| sql_mode | STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)

06:41:29(root@localhost) [hellodb]> insert test values(2,'magedu');
ERROR 1406 (22001): Data too long for column 'name' at row 1

Query Cache 查询缓存

查询缓存原理

查询执行路径

image-20240521065630329

查询缓存原理 哈希运算

缓存SELECT操作或预处理查询的结果集和SQL语句,当有新的SELECT语句或预处理查询语句请求,先去查询缓存,判断是否存在可用的记录集,判断标准:与缓存的SQL语句,是否完全一样,区分大小写

优缺点

不需要对SQL语句做任何解析和执行,当然语法解析必须通过在先,直接从Query Cache中获得查询结果,提高查询性能;

查询缓存的判断规则,不够智能,也即提高了查询缓存的使用门槛,降低效率;

查询缓存的使用,会增加检查和清理Query Cache中记录集的开销;

哪些查询可能不会被缓存

  • 查询语句中加了SQL_NO_CACHE参数
  • 查询语句中含有获得值的函数,包含:自定义函数,如:NOW() ,CURDATE()、GET_LOCK()、RAND()、CONVERT_TZ()等
  • 对系统数据库的查询:mysql、information_schema 查询语句中使用SESSION级别变量或存储过程中的局部变量
  • 查询语句中使用了LOCK IN SHARE MODE、FOR UPDATE的语句,查询语句中类似SELECT …
  • INTO 导出数据的语句
  • 对临时表的查询操作
  • 存在警告信息的查询语句
  • 不涉及任何表或视图的查询语句
  • 某用户只有列级别权限的查询语句
  • 事务隔离级别为Serializable时,所有查询语句都不能缓存

查询缓存相关的服务器变量

  • query_cache_min_res_unit:查询缓存中内存块的最小分配单位,默认4k,较小值会减少浪费,但会导致更频繁的内存分配操作,较大值会带来浪费,会导致碎片过多,内存不足;
  • query_cache_limit:单个查询结果能缓存的最大值,单位字节,默认为1M,对于查询结果过大而无法缓存的语句,建议使用SQL_NO_CACHE
  • query_cache_size:查询缓存总共可用的内存空间;单位字节,必须是1024的整数倍,最小值40KB,低于此值有警报
  • query_cache_wlock_invalidate:如果某表被其它的会话锁定,是否仍然可以从查询缓存中返回结果,默认值为OFF,表示可以在表被其它会话锁定的场景中继续从缓存返回数据;ON则表示不允许
  • query_cache_type:是否开启缓存功能,取值为ON, OFF, DEMAND(按需开启,看select语句是否加sql_cache参数)

范例:配置文件配置服务器选项

06:41:40(root@localhost) [hellodb]>  show variables like 'query_cache%';
+------------------------------+---------+
| Variable_name | Value |
+------------------------------+---------+
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 1048576 |
| query_cache_strip_comments | OFF |
| query_cache_type | OFF |
| query_cache_wlock_invalidate | OFF |
+------------------------------+---------+
6 rows in set (0.001 sec)


#vim /etc/my.cnf
[mysqld]
query_cache_type=ON
query_cache_size=200M

systemctl restart mariadb


[root@test2 ~]#mysql hellodb
07:42:09(root@localhost) [hellodb]> show variables like 'query_cache%';
+------------------------------+-----------+
| Variable_name | Value |
+------------------------------+-----------+
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 209715200 |
| query_cache_strip_comments | OFF |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
+------------------------------+-----------+
6 rows in set (0.001 sec)

SELECT语句的缓存控制

查询缓存相关的状态变量

07:44:25(root@localhost) [hellodb]> show global status like 'Qcache%%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 209697192 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 2 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+-----------+
8 rows in set (0.001 sec)
  • Qcache_free_blocks:处于空闲状态 Query Cache中内存 Block 数
  • Qcache_total_blocks:Query Cache 中总Block ,当Qcache_free_blocks相对此值较大时,可能用内存碎片,执行FLUSH QUERY CACHE清理碎片
  • Qcache_free_memory:处于空闲状态的 Query Cache 内存总量
  • Qcache_hits:Query Cache 命中次数
  • Qcache_inserts:向 Query Cache 中插入新的 Query Cache 的次数,即没有命中的次数
  • Qcache_lowmem_prunes:记录因为内存不足而被移除出查询缓存的查询数
  • Qcache_not_cached:没有被 Cache 的 SQL 数,包括无法被 Cache 的 SQL 以及由于
  • query_cache_type 设置的不会被 Cache 的 SQL语句
  • Qcache_queries_in_cache:在 Query Cache 中的 SQL 数量

范例:Query Cache测试

07:44:25(root@localhost) [hellodb]> show global status like 'Qcache%%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 209697192 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 2 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+-----------+
8 rows in set (0.001 sec)

07:44:31(root@localhost) [hellodb]> select *from students where stuid=1;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
+-------+-------------+-----+--------+---------+-----------+
1 row in set (0.001 sec)

07:55:49(root@localhost) [hellodb]> show global status like 'Qcache%%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 209695656 |
| Qcache_hits | 0 |
| Qcache_inserts | 1 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 2 |
| Qcache_queries_in_cache | 1 |
| Qcache_total_blocks | 4 |
+-------------------------+-----------+
8 rows in set (0.001 sec)

07:55:53(root@localhost) [hellodb]> select *from students where stuid=2;
+-------+------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+------------+-----+--------+---------+-----------+
| 2 | Shi Potian | 22 | M | 1 | 7 |
+-------+------------+-----+--------+---------+-----------+
1 row in set (0.000 sec)

07:56:03(root@localhost) [hellodb]> show global status like 'Qcache%%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 209694632 |
| Qcache_hits | 0 |
| Qcache_inserts | 2 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 2 |
| Qcache_queries_in_cache | 2 |
| Qcache_total_blocks | 6 |
+-------------------------+-----------+
8 rows in set (0.000 sec)


07:56:04(root@localhost) [hellodb]> select *from students where stuid=1;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
+-------+-------------+-----+--------+---------+-----------+
1 row in set (0.000 sec)

07:56:28(root@localhost) [hellodb]> show global status like 'Qcache%%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 209694632 |
| Qcache_hits | 1 |
| Qcache_inserts | 2 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 2 |
| Qcache_queries_in_cache | 2 |
| Qcache_total_blocks | 6 |
+-------------------------+-----------+
8 rows in set (0.000 sec)

07:56:30(root@localhost) [hellodb]> select *from students where stuid=1;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
+-------+-------------+-----+--------+---------+-----------+
1 row in set (0.000 sec)

07:56:38(root@localhost) [hellodb]> show global status like 'Qcache%%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 209694632 |
| Qcache_hits | 2 |
| Qcache_inserts | 2 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 2 |
| Qcache_queries_in_cache | 2 |
| Qcache_total_blocks | 6 |
+-------------------------+-----------+
8 rows in set (0.001 sec)

大小写有区别;

空格在sql语句中间有区别,但在sql语句前面或者最后面是可以的;

查询的优化

image-20240522064940748

命中率和内存使用率估算

  • 查询缓存中内存块的最小分配单位query_cache_min_res_unit :

    (query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache
  • 查询缓存命中率 :

    Qcache_hits / ( Qcache_hits + Qcache_inserts ) * 100%
  • 查询缓存内存使用率:

    (query_cache_size – qcache_free_memory) / query_cache_size * 100%

MySQL 8.0 变化

MySQL8.0 取消查询缓存的功能

尽管MySQL Query Cache旨在提高性能,但它存在严重的可伸缩性问题,并且很容易成为严重的瓶颈

自MySQL 5.6(2013)以来,默认情况下已禁用查询缓存,其不能与多核计算机上在高吞吐量工作负载情况下进行扩展。

另外有时因为查询缓存往往弊大于利。比如:查询缓存的失效非常频繁,只要有对一个表的更新,这个表上的所有的查询缓存都会被清空。因此很可能你费劲地把结果存起来,还没使用呢,就被一个更新全清空了。对于更新压力大的数据库来说,查询缓存的命中率会非常低。除非你的业务有一张静态表,很长时间更新一次,比如系统配置表,那么这张表的查询才适合做查询缓存。

目前大多数应用都把缓存做到了应用逻辑层,比如:使用redis或者memcache

INDEX 索引

很重要。

索引介绍

索引:是排序的快速查找的特殊数据结构,定义作为查找条件的字段上,又称为键key,索引通过存储引擎实现

优点:

  • 索引可以降低服务需要扫描的数据量,减少了IO次数
  • 索引可以帮助服务器避免排序和使用临时表
  • 索引可以帮助将随机I/O转为顺序I/O

缺点:

  • 占用额外空间,影响插入速度

索引类型:

  • B+ TREE、HASH、R TREE、FULL TEXT
  • 聚簇(集)索引、非聚簇索引:数据和索引是否存储在一起
  • 主键索引、二级(辅助)索引
  • 稠密索引、稀疏索引:是否索引了每一个数据项
  • 简单索引、组合索引
  • 左前缀索引:取前面的字符做索引
  • 覆盖索引:从索引中即可取出要查询的数据,性能高

索引结构

二叉树

image-20240522070844333

红黑树

image-20240522070925162

B Tree 索引

image-20240522071218056

B+Tree索引

image-20240522071743947

B+Tree索引:按顺序存储,每一个叶子节点到根结点的距离是相同的;左前缀索引,适合查询范围类的数据

可以使用B+Tree索引的查询类型

  • 全值匹配:精确所有索引列,如:姓wang,名xiaochun,年龄30

  • 匹配最左前缀:即只使用索引的第一列,如:姓wang

  • 匹配列前缀:只匹配一列值开头部分,如:姓以w开头的

  • 匹配范围值:如:姓ma和姓wang之间

  • 精确匹配某一列并范围匹配另一列:如:姓wang,名以x开头的

  • 只访问索引的查询

B+Tree索引的限制

  • 如不从最左列开始,则无法使用索引,如:查找名为xiaochun,或姓为g结尾
  • 不能跳过索引中的列:如:查找姓wang,年龄30的,只能使用索引第一列

特别提示:

索引列的顺序和查询语句的写法应相匹配,才能更好的利用索引

为优化性能,可能需要针对相同的列但顺序不同创建不同的索引来满足不同类型的查询需求

Hash索引

Hash索引:基于哈希表实现,只有精确匹配索引中的所有列的查询才有效,索引自身只存储索引列对

应的哈希值和数据指针,索引结构紧凑,查询性能好

Memory存储引擎支持显式hash索引,InnoDB和MyISAM存储引擎不支持

适用场景:只支持等值比较查询,包括=, <=>, IN()

不适合使用hash索引的场景

不适用于顺序查询:索引存储顺序的不是值的顺序

不支持模糊匹配

不支持范围查询

不支持部分索引列匹配查找:如A,B列索引,只查询A列索引无效

空间数据索引R-Tree( Geospatial indexing )

MyISAM支持地理空间索引,可使用任意维度组合查询,使用特有的函数访问,常用于做地理数据存

储,使用不多

InnoDB从MySQL5.7之后也开始支持

全文索引(FULLTEXT)

在文本中查找关键词,而不是直接比较索引中的值,类似搜索引擎

InnoDB从MySQL 5.6之后也开始支持

聚簇和非聚簇索引,主键和二级索引

image-20240524075645319

image-20240527051354574

冗余和重复索引:

冗余索引:(A),(A,B)

重复索引:已经有索引,再次建立索引

索引优化

  • 独立地使用列:尽量避免其参与运算,独立的列指索引列不能是表达式的一部分,也不能是函数的参数,在where条件中,始终将索引列单独放在比较符号的一侧,尽量不要在列上进行运算(函数操作和表达式操作)
  • 左前缀索引:构建指定索引字段的左侧的字符数,要通过索引选择性(不重复的索引值和数据表的
  • 记录总数的比值)来评估,尽量使用短索引,如果可以,应该制定一个前缀长度
  • 多列索引:AND操作时更适合使用多列索引,而非为每个列创建单独的索引
  • 选择合适的索引列顺序:无排序和分组时,将选择性最高放左侧
  • 只要列中含有NULL值,就最好不要在此列设置索引,复合索引如果有NULL值,此列在使用时也不会使用索引
  • 对于经常在where子句使用的列,最好设置索引
  • 对于有多个列where或者order by子句,应该建立复合索引
  • 对于like语句,以 % 或者 _ 开头的不会使用索引,以 % 结尾会使用索引
  • 尽量不要使用not in和<>操作,虽然可能使用索引,但性能不高
  • 不要使用RLIKE正则表达式会导致索引失效
  • 查询时,能不要就不用,尽量写全字段名,比如:select id,name,age from students;
  • 大部分情况连接效率远大于子查询
  • 在有大量记录的表分页时使用limit
  • 对于经常使用的查询,可以开启查询缓存
  • 多使用explain和profile分析查询语句
  • 查看慢查询日志,找出执行时间长的sql语句优化

管理索引

创建索引:

CREATE [UNIQUE] INDEX index_name ON tbl_name (index_col_name[(length)],...);

ALTER TABLE tbl_name ADD INDEX index_name(index_col_name[(length)]);

help CREATE INDEX;

删除索引:

DROP INDEX index_name ON tbl_name;

ALTER TABLE tbl_name DROP INDEX index_name(index_col_name);

查看索引:

SHOW INDEXES FROM [db_name.]tbl_name;

优化表空间:

OPTIMIZE TABLE tb_name;

查看索引的使用

SET GLOBAL userstat=1;
SHOW INDEX_STATISTICS;

范例

MariaDB [hellodb]> show index from students\G
*************************** 1. row ***************************
Table: students
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: StuID
Collation: A
Cardinality: 25
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.001 sec)

MariaDB [hellodb]> desc students;
#这里的key就是索引,建主键的时候同时就自动建立了索引。
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| StuID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| Name | varchar(50) | NO | | NULL | |
| Age | tinyint(3) unsigned | NO | | NULL | |
| Gender | enum('F','M') | NO | | NULL | |
| ClassID | tinyint(3) unsigned | YES | | NULL | |
| TeacherID | int(10) unsigned | YES | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.001 sec)


#手动建立索引
MariaDB [hellodb]> create index idx_name on students(name(10));
Query OK, 0 rows affected (0.007 sec)
Records: 0 Duplicates: 0 Warnings: 0

MariaDB [hellodb]> show index from students\G
*************************** 1. row ***************************
Table: students
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: StuID
Collation: A
Cardinality: 25
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 2. row ***************************
Table: students
Non_unique: 1
Key_name: idx_name
Seq_in_index: 1
Column_name: Name
Collation: A
Cardinality: 25
Sub_part: 10
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
2 rows in set (0.001 sec)
MariaDB [hellodb]> desc students;
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| StuID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| Name | varchar(50) | NO | MUL | NULL | |
| Age | tinyint(3) unsigned | NO | | NULL | |
| Gender | enum('F','M') | NO | | NULL | |
| ClassID | tinyint(3) unsigned | YES | | NULL | |
| TeacherID | int(10) unsigned | YES | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.001 sec)



#删除索引
MariaDB [hellodb]> drop index idx_name on students;
Query OK, 0 rows affected (0.004 sec)
Records: 0 Duplicates: 0 Warnings: 0

MariaDB [hellodb]> desc students;
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| StuID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| Name | varchar(50) | NO | | NULL | |
| Age | tinyint(3) unsigned | NO | | NULL | |
| Gender | enum('F','M') | NO | | NULL | |
| ClassID | tinyint(3) unsigned | YES | | NULL | |
| TeacherID | int(10) unsigned | YES | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.001 sec)
MariaDB [hellodb]> show index from students\G
*************************** 1. row ***************************
Table: students
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: StuID
Collation: A
Cardinality: 25
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.000 sec)
MariaDB [hellodb]> select @@userstat;
+------------+
| @@userstat |
+------------+
| 0 |
+------------+
1 row in set (0.000 sec)

MariaDB [hellodb]> show variables like 'userstat';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| userstat | OFF |
+---------------+-------+
1 row in set (0.001 sec)


#开启
MariaDB [hellodb]> set global userstat=1;
Query OK, 0 rows affected (0.000 sec)

MariaDB [hellodb]> show variables like 'userstat';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| userstat | ON |
+---------------+-------+
1 row in set (0.001 sec)


#再次建立下之前的索引
MariaDB [hellodb]> create index idx_name on students(name(10));
Query OK, 0 rows affected (0.004 sec)
Records: 0 Duplicates: 0 Warnings: 0

MariaDB [hellodb]> desc students;
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| StuID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| Name | varchar(50) | NO | MUL | NULL | |
| Age | tinyint(3) unsigned | NO | | NULL | |
| Gender | enum('F','M') | NO | | NULL | |
| ClassID | tinyint(3) unsigned | YES | | NULL | |
| TeacherID | int(10) unsigned | YES | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.001 sec)



#MariaDB [hellodb]> show index_statistics;
Empty set (0.000 sec)


#直接查,是没有利用索引的
MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.001 sec)

MariaDB [hellodb]> show index_statistics;
Empty set (0.000 sec)



#模拟使用索引
MariaDB [hellodb]> select *from students where stuid=10;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
+-------+--------------+-----+--------+---------+-----------+
1 row in set (0.001 sec)

MariaDB [hellodb]> show index_statistics;
+--------------+------------+------------+-----------+
| Table_schema | Table_name | Index_name | Rows_read |
+--------------+------------+------------+-----------+
| hellodb | students | PRIMARY | 1 |
+--------------+------------+------------+-----------+
1 row in set (0.000 sec)

MariaDB [hellodb]> select *from students where stuid=10;
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
+-------+--------------+-----+--------+---------+-----------+
1 row in set (0.001 sec)

MariaDB [hellodb]> show index_statistics;
+--------------+------------+------------+-----------+
| Table_schema | Table_name | Index_name | Rows_read |
+--------------+------------+------------+-----------+
| hellodb | students | PRIMARY | 2 |
+--------------+------------+------------+-----------+
1 row in set (0.000 sec)


MariaDB [hellodb]> select *from students where name='Yue Lingshan';
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
+-------+--------------+-----+--------+---------+-----------+
1 row in set (0.001 sec)

MariaDB [hellodb]> show index_statistics;
+--------------+------------+------------+-----------+
| Table_schema | Table_name | Index_name | Rows_read |
+--------------+------------+------------+-----------+
| hellodb | students | idx_name | 1 |
| hellodb | students | PRIMARY | 2 |
+--------------+------------+------------+-----------+
2 rows in set (0.000 sec)

MariaDB [hellodb]> select *from students where name='Yue Lingshan';
+-------+--------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+--------------+-----+--------+---------+-----------+
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
+-------+--------------+-----+--------+---------+-----------+
1 row in set (0.001 sec)

MariaDB [hellodb]> show index_statistics;
+--------------+------------+------------+-----------+
| Table_schema | Table_name | Index_name | Rows_read |
+--------------+------------+------------+-----------+
| hellodb | students | idx_name | 2 |
| hellodb | students | PRIMARY | 2 |
+--------------+------------+------------+-----------+
2 rows in set (0.000 sec)
#可以通过这个简单的方法来统计索引用没用。
#以上命令只能粗略地看到是否使用索引,而不能看到她的细节。

EXPLAIN 工具

可以通过EXPLAIN来分析索引的有效性,获取查询执行计划信息,用来查看查询优化器如何执行查询

参考资料: https://dev.mysql.com/doc/refman/5.7/en/explain-output.html

语法:

EXPLAIN SELECT clause

EXPLAIN输出信息说明:

image-20240527074036210

说明: type显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL ,一般来说,得保证查询至少达到range级别,最好能达到ref

image-20240527074127090

一般,达到range基本算是优化可以的了,如果出现index或者all,就说明这个索引还是有优化的空间。

范例:

MariaDB [hellodb]> explain select *from students;
+------+-------------+----------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 25 | |
+------+-------------+----------+------+---------------+------+---------+------+------+-------+
1 row in set (0.000 sec)

MariaDB [hellodb]> select *from students where name like 'x%';
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
+-------+-------------+-----+--------+---------+-----------+
6 rows in set (0.001 sec)


MariaDB [hellodb]> explain select *from students where name like 's%';
+------+-------------+----------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+----------+---------+------+------+-------------+
| 1 | SIMPLE | students | range | idx_name | idx_name | 32 | NULL | 4 | Using where |
+------+-------------+----------+-------+---------------+----------+---------+------+------+-------------+
1 row in set (0.001 sec)

image-20240527063804276

#左模糊、全模糊是无法使用索引的
MariaDB [hellodb]> select *from students where name like '%o';
+-------+-----------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-----------+-----+--------+---------+-----------+
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
+-------+-----------+-----+--------+---------+-----------+
2 rows in set (0.001 sec)

MariaDB [hellodb]> explain select *from students where name like '%o';
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 25 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.000 sec)


#以下是可以利用索引的
MariaDB [hellodb]> explain select *from students where stuid > 20;
+------+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | students | range | PRIMARY | PRIMARY | 4 | NULL | 5 | Using where |
+------+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.000 sec)

MariaDB [hellodb]> explain select *from students where stuid > 10 and stuid < 20;
+------+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | students | range | PRIMARY | PRIMARY | 4 | NULL | 9 | Using where |
+------+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.001 sec)

image-20240527064813983

#正则表达式是不使用索引的,很少简单where后面跟正则表达式的
MariaDB [hellodb]> explain select *from students where name rlike '^w';
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 25 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.001 sec)

MariaDB [hellodb]> explain select *from students where name rlike '^W';
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 25 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.001 sec)
#创建复合索引
MariaDB [hellodb]> create index idx_name_age on students(name,age);
Query OK, 0 rows affected (0.006 sec)
Records: 0 Duplicates: 0 Warnings: 0


MariaDB [hellodb]> show index from students;
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| students | 0 | PRIMARY | 1 | StuID | A | 25 | NULL | NULL | | BTREE | | |
| students | 1 | idx_name | 1 | Name | A | 25 | 10 | NULL | | BTREE | | |
| students | 1 | idx_name_age | 1 | Name | A | 25 | NULL | NULL | | BTREE | | |
| students | 1 | idx_name_age | 2 | Age | A | 25 | NULL | NULL | | BTREE | | |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+


#删除冗余索引
MariaDB [hellodb]> drop index idx_name on students;
Query OK, 0 rows affected (0.004 sec)
Records: 0 Duplicates: 0 Warnings: 0



MariaDB [hellodb]> explain select *from students where name = "Xu Zhu";
+------+-------------+----------+------+---------------+--------------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+--------------+---------+-------+------+-----------------------+
| 1 | SIMPLE | students | ref | idx_name_age | idx_name_age | 152 | const | 1 | Using index condition |
+------+-------------+----------+------+---------------+--------------+---------+-------+------+-----------------------+
1 row in set (0.001 sec)

#索引失效
MariaDB [hellodb]> explain select *from students where age = 20;
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 25 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.001 sec)

#索引失效(做模糊)
MariaDB [hellodb]> explain select *from students where name like '%s' and age = 20;
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 25 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.001 sec)

MariaDB [hellodb]> explain select *from students where name = 'Ma Chao' and age = 20;
+------+-------------+----------+------+---------------+--------------+---------+-------------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+--------------+---------+-------------+------+-----------------------+
| 1 | SIMPLE | students | ref | idx_name_age | idx_name_age | 153 | const,const | 1 | Using index condition |
+------+-------------+----------+------+---------------+--------------+---------+-------------+------+-----------------------+
1 row in set (0.001 sec)

并发控制

锁机制

锁:

​ 读锁:共享锁,也称为 S 锁,只读不可写(包括当前事务) ,多个读互不阻塞

​ 写锁:独占锁,排它锁,也称为 X 锁,写锁会阻塞其它事务(不包括当前事务)的读和写

S 锁和 S 锁是兼容的,X 锁和其它锁都不兼容,举个例子,事务 T1 获取了一个行 r1 的 S 锁,另外事务 T2 可以立即获得行 r1 的 S 锁,此时 T1 和 T2 共同获得行 r1 的 S 锁,此种情况称为锁兼容,但是另外一个事务 T2 此时如果想获得行 r1 的 X 锁,则必须等待 T1 对行 r 锁的释放,此种情况也成为锁冲突

锁粒度

  • 表级锁:MyISAM
  • 行级锁:InnodB

实现

存储引擎:自行实现其锁策略和锁粒度

服务器级:实现了锁,表级锁,用户可显式请求

分类

隐式锁:由存储引擎自动施加锁

显式锁:用户手动请求

锁策略:在锁粒度及数据安全性寻求的平衡机制

显式使用锁

帮助:https://mariadb.com/kb/en/lock-tables/

加锁:

LOCK TABLES tbl_name [[AS] alias] lock_type [, tbl_name [[AS] alias] 
lock_type] ...

lock_type:
READ
WRITE

解锁

UNLOCK TABLES

关闭正在打开的表(清除查询缓存),通常在备份前加全局读锁

FLUSH TABLES [tb_name[,...]] [WITH READ LOCK]  

#范例
FLUSH TABLES WITH READ LOCK;

查询时加写或读锁

SELECT clause [FOR UPDATE | LOCK IN SHARE MODE]

范例: 加读锁

mysql> lock tables students read ;
Query OK, 0 rows affected (0.00 sec)

mysql> update students set classid=2 where stuid=24;
ERROR 1099 (HY000): Table 'students' was locked with a READ lock and can't be updated

mysql> unlock tables ;
mysql> update students set classid=2 where stuid=24;
Query OK, 1 row affected (1 min 45.52 sec)
Rows matched: 1 Changed: 1 Warnings: 0

范例: 同时在两个终端对同一行记录修改

#同时对同一行记录执行update
#在第一终端提示1行成功
MariaDB [hellodb]> update students set classid=1 where stuid=24;
Query OK, 1 row affected (0.002 sec)
Rows matched: 1 Changed: 1 Warnings: 0

#在第二终端提示0行修改
MariaDB [hellodb]> update students set classid=1 where stuid=24;
Query OK, 0 rows affected (0.000 sec)
Rows matched: 1 Changed: 0 Warnings: 0

范例:如果加锁终端被关闭了,那么锁自然也不存在了。

#终端1
MariaDB [hellodb]> FLUSH TABLES WITH READ LOCK;

#终端2
MariaDB [hellodb]> show processlist;
+----+------+-----------+---------+---------+------+----------+------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+----+------+-----------+---------+---------+------+----------+------------------+----------+
| 68 | root | localhost | hellodb | Sleep | 10 | | NULL | 0.000 |
| 69 | root | localhost | hellodb | Query | 0 | starting | show processlist | 0.000 |
+----+------+-----------+---------+---------+------+----------+------------------+----------+
2 rows in set (0.000 sec)

MariaDB [hellodb]> \s
--------------
mysql Ver 15.1 Distrib 10.5.25-MariaDB, for Linux (x86_64) using readline 5.1

Connection id: 69
Current database: hellodb
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server: MariaDB
Server version: 10.5.25-MariaDB MariaDB Server
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: latin1
Db characterset: utf8
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 1 day 1 hour 39 min 43 sec

Threads: 2 Questions: 303 Slow queries: 0 Opens: 52 Open tables: 0 Queries per second avg: 0.003
--------------

MariaDB [hellodb]> update students set classid=2 where stuid=24;
Query OK, 1 row affected (3.299 sec)
Rows matched: 1 Changed: 1 Warnings: 0

MariaDB [hellodb]>

事务

事务Transactions:一组原子性的SQL语句,或一个独立工作单元

事务日志:记录事务信息,实现undo,redo等故障恢复功能

事务特性

ACID特性

  • A:atomicity原子性:整个事务中的所有操作要么全部成功执行,要么全部失败后回滚
  • C:consistency一致性:数据库总是从一个一致性状态转换为另一个一致性状态
  • I:Isolation隔离性:一个事务所做出的操作在提交之前,是不能为其它事务所见;隔离有多种隔离级别,实现并发
  • D:durability持久性:一旦事务提交,其所做的修改会永久保存于数据库中

Transaction生命周期

image-20240529045949117

管理事务

显式启动事务:

BEGIN
BEGIN WORK
START TRANSACTION

结束事务:

#提交
COMMIT
#回滚
ROLLBACK

注意:只有事务型存储引擎中的DML语句方能支持此类操作

事务不是万能的!有些指令,并不受事务的约束。 DML语句:insert、update、delete

但注意:truncate、drop等语句本身就是一条提交事务,不走事务机制的,删除就真难得被删除了。

drop table teachers;

truncate table students;

自动提交:

set autocommit={1|0}

默认为1,为0时设为非自动提交

建议:显式请求和提交事务,而不要使用“自动提交”功能。

事务支持保存点:

SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier

查看事务

#查看当前正在进行的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
#查看当前锁定的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
#查看当前等锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

范例:测试事务

#查看测试表
MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | 2 | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.000 sec)


#在一个会话里显示开启一个事务
MariaDB [hellodb]> begin;
Query OK, 0 rows affected (0.000 sec)


#执行2条DML语句
MariaDB [hellodb]> update students set classid=1 where stuid=25;
Query OK, 1 row affected (0.001 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MariaDB [hellodb]> delete from students where stuid=24;
Query OK, 1 row affected (0.001 sec)

#在当前会话里是可以正常看到执行效果的

MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 25 | Sun Dasheng | 100 | M | 1 | NULL |
+-------+---------------+-----+--------+---------+-----------+
24 rows in set (0.001 sec)


#但是重新打开一个会话后,发现students表是没任何变化的

MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | 2 | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.001 sec)

#这是为什么呢?--事务的隔离性
# I:Isolation隔离性:一个事务所做出的操作在提交之前,是不能为其它事务所见;隔离有多种隔离级别,实现并发


#那么我们在原来会话里可以执行rollback
MariaDB [hellodb]> rollback;
Query OK, 0 rows affected (0.001 sec)

#执行之后,本会话看,students里的数据已经恢复到更改前端的状态了。
MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | 2 | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.001 sec)


#再测试
#开启一个事务,然后执行2条DML语句
MariaDB [hellodb]> begin;
Query OK, 0 rows affected (0.000 sec)

MariaDB [hellodb]> update students set classid=1 where stuid=25;
Query OK, 1 row affected (0.001 sec)
Rows matched: 1 Changed: 1 Warnings: 0

MariaDB [hellodb]> delete from students where stuid=24;
Query OK, 1 row affected (0.001 sec)


#当我吧当前会话关闭后,重新打开一个会话后,那么查看表的现象是什么样的呢?
MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | 2 | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.001 sec)
#会发现表的状态依然是未发生改变的
#这是由事务的 原子性来决定的。
#A:atomicity原子性:整个事务中的所有操作要么全部成功执行,要么全部失败后回滚


#再测试
#开启一个事务,然后执行2条DML语句
MariaDB [hellodb]> begin;
Query OK, 0 rows affected (0.000 sec)

MariaDB [hellodb]> update students set classid=1 where stuid=25;
Query OK, 1 row affected (0.001 sec)
Rows matched: 1 Changed: 1 Warnings: 0

MariaDB [hellodb]> delete from students where stuid=24;
Query OK, 1 row affected (0.001 sec)

#自己执行下commit
MariaDB [hellodb]> commit;
Query OK, 0 rows affected


MariaDB [hellodb]> select
+-------+---------------+-
| StuID | Name |
+-------+---------------+-
| 1 | Shi Zhongyu |
| 2 | Shi Potian |
| 3 | Xie Yanke |
| 4 | Ding Dian |
| 5 | Yu Yutong |
| 6 | Shi Qing |
| 7 | Xi Ren |
| 8 | Lin Daiyu |
| 9 | Ren Yingying |
| 10 | Yue Lingshan |
| 11 | Yuan Chengzhi |
| 12 | Wen Qingqing |
| 13 | Tian Boguang |
| 14 | Lu Wushuang |
| 15 | Duan Yu |
| 16 | Xu Zhu |
| 17 | Lin Chong |
| 18 | Hua Rong |
| 19 | Xue Baochai |
| 20 | Diao Chan |
| 21 | Huang Yueying |
| 22 | Xiao Qiao |
| 23 | Ma Chao |
| 25 | Sun Dasheng |
+-------+---------------+-
24 rows in set (0.001 sec)
#会发现自己当前会话里数据是发行了改变。关闭当前会话,再重新打开一个会话查看,发现数据已经被改变了的,符合预期。
MariaDB [hellodb]> select *from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 25 | Sun Dasheng | 100 | M | 1 | NULL |
+-------+---------------+-----+--------+---------+-----------+
24 rows in set (0.001 sec)

范例:事务支持保存点

MariaDB [hellodb]> select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.001 sec)


#开始事务:
MariaDB [hellodb]> begin;insert teachers (name,age,gender)value('a',20,'M');
Query OK, 0 rows affected (0.000 sec)

Query OK, 1 row affected (0.000 sec)

MariaDB [hellodb]> savepoint a;
Query OK, 0 rows affected (0.000 sec)

MariaDB [hellodb]> insert teachers (name,age,gender)value('b',30,'F');
Query OK, 1 row affected (0.000 sec)

MariaDB [hellodb]> savepoint b;
Query OK, 0 rows affected (0.000 sec)

MariaDB [hellodb]> insert teachers (name,age,gender)value('c',40,'F');
Query OK, 1 row affected (0.000 sec)


MariaDB [hellodb]> select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 5 | a | 20 | M |
| 6 | b | 30 | F |
| 7 | c | 40 | F |
+-----+---------------+-----+--------+
7 rows in set (0.000 sec)


#撤销
MariaDB [hellodb]> rollback to b;
Query OK, 0 rows affected (0.000 sec)

MariaDB [hellodb]> select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 5 | a | 20 | M |
| 6 | b | 30 | F |
+-----+---------------+-----+--------+
6 rows in set (0.001 sec)

MariaDB [hellodb]> rollback to a;
Query OK, 0 rows affected (0.000 sec)

MariaDB [hellodb]> select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 5 | a | 20 | M |
+-----+---------------+-----+--------+
5 rows in set (0.001 sec)
MariaDB [hellodb]> rollback;
Query OK, 0 rows affected (0.001 sec)

MariaDB [hellodb]> select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.000 sec)


#不能反撤销:
MariaDB [hellodb]> rollback to c;
ERROR 1305 (42000): SAVEPOINT c does not exist

范例:查看事务

MariaDB [hellodb]> begin;
Query OK, 0 rows affected (0.000 sec)

MariaDB [hellodb]> SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
Empty set (0.000 sec)

MariaDB [hellodb]> select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.000 sec)

MariaDB [hellodb]> SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
+-----------------+-----------+---------------------+-----------------------+------------------+------------+---------------------+---------------------------------------------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+------------------+----------------------------+
| trx_id | trx_state | trx_started | trx_requested_lock_id | trx_wait_started | trx_weight | trx_mysql_thread_id | trx_query | trx_operation_state | trx_tables_in_use | trx_tables_locked | trx_lock_structs | trx_lock_memory_bytes | trx_rows_locked | trx_rows_modified | trx_concurrency_tickets | trx_isolation_level | trx_unique_checks | trx_foreign_key_checks | trx_last_foreign_key_error | trx_is_read_only | trx_autocommit_non_locking |
+-----------------+-----------+---------------------+-----------------------+------------------+------------+---------------------+---------------------------------------------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+------------------+----------------------------+
| 421262868086992 | RUNNING | 2024-05-31 06:15:02 | NULL | NULL | 0 | 162 | SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX | | 0 | 0 | 0 | 1128 | 0 | 0 | 0 | REPEATABLE READ | 1 | 1 | NULL | 0 | 0 |
+-----------------+-----------+---------------------+-----------------------+------------------+------------+---------------------+---------------------------------------------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+------------------+----------------------------+
1 row in set (0.000 sec)


MariaDB [hellodb]> SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX\G
*************************** 1. row ***************************
trx_id: 421262868086992
trx_state: RUNNING
trx_started: 2024-05-31 06:15:02
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 0
trx_mysql_thread_id: 162
trx_query: SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX
trx_operation_state:
trx_tables_in_use: 0
trx_tables_locked: 0
trx_lock_structs: 0
trx_lock_memory_bytes: 1128
trx_rows_locked: 0
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_is_read_only: 0
trx_autocommit_non_locking: 0
1 row in set (0.000 sec)


MariaDB [hellodb]> update teachers set age=50 where tid=4;
Query OK, 1 row affected (0.001 sec)
Rows matched: 1 Changed: 1 Warnings: 0

MariaDB [hellodb]> SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX\G
*************************** 1. row ***************************
trx_id: 936
trx_state: RUNNING
trx_started: 2024-05-31 06:15:02
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 3
trx_mysql_thread_id: 162
trx_query: SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX
trx_operation_state:
trx_tables_in_use: 0
trx_tables_locked: 1
trx_lock_structs: 2
trx_lock_memory_bytes: 1128
trx_rows_locked: 1
trx_rows_modified: 1
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_is_read_only: 0
trx_autocommit_non_locking: 0
1 row in set (0.000 sec)


#再另开一个窗口,更改同一行数据,观察是否能修改成功?
MariaDB [hellodb]> select *from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.000 sec)

MariaDB [hellodb]> update teachers set gender='M' where tid=4;
……#卡顿,无法更改
#是因为innodb加了行级锁,导致另一个用户就无法修改这行的数据



MariaDB [hellodb]> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
+------------+-------------+-----------+-----------+----------------------+------------+------------+-----------+----------+-----------+
| lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data |
+------------+-------------+-----------+-----------+----------------------+------------+------------+-----------+----------+-----------+
| 937:15:3:5 | 937 | X | RECORD | `hellodb`.`teachers` | PRIMARY | 15 | 3 | 5 | 4 |
| 936:15:3:5 | 936 | X | RECORD | `hellodb`.`teachers` | PRIMARY | 15 | 3 | 5 | 4 |
+------------+-------------+-----------+-----------+----------------------+------------+------------+-----------+----------+-----------+
2 rows in set (0.001 sec)


MariaDB [hellodb]> SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX\G
*************************** 1. row ***************************
trx_id: 937
trx_state: LOCK WAIT
trx_started: 2024-05-31 06:22:49
trx_requested_lock_id: 937:15:3:5
trx_wait_started: 2024-05-31 06:25:41
trx_weight: 2
trx_mysql_thread_id: 163 #线程id
trx_query: update teachers set gender='M' where tid=4
trx_operation_state: starting index read
trx_tables_in_use: 1
trx_tables_locked: 1
trx_lock_structs: 2
trx_lock_memory_bytes: 1128
trx_rows_locked: 2
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_is_read_only: 0
trx_autocommit_non_locking: 0
*************************** 2. row ***************************
trx_id: 936
trx_state: RUNNING
trx_started: 2024-05-31 06:15:02
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 3
trx_mysql_thread_id: 162 #线程id
trx_query: SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX
trx_operation_state:
trx_tables_in_use: 0
trx_tables_locked: 1
trx_lock_structs: 2
trx_lock_memory_bytes: 1128
trx_rows_locked: 1
trx_rows_modified: 1
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_is_read_only: 0
trx_autocommit_non_locking: 0
2 rows in set (0.001 sec)


#超时,回滚(50s的超时时长)
MariaDB [hellodb]> update teachers set gender='M' where tid=4;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction


#查看当前等锁的事务
MariaDB [hellodb]> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
+-------------------+-------------------+-----------------+------------------+
| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |
+-------------------+-------------------+-----------------+------------------+
| 937 | 937:15:3:5 | 936 | 936:15:3:5 |
+-------------------+-------------------+-----------------+------------------+
1 row in set (0.000 sec)


MariaDB [hellodb]> show processlist;
+-----+------+-----------+---------+---------+------+----------+--------------------------------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+-----+------+-----------+---------+---------+------+----------+--------------------------------------------+----------+
| 162 | root | localhost | hellodb | Sleep | 44 | | NULL | 0.000 |
| 163 | root | localhost | hellodb | Query | 48 | Updating | update teachers set gender='M' where tid=4 | 0.000 |
| 164 | root | localhost | hellodb | Query | 0 | starting | show processlist | 0.000 |
+-----+------+-----------+---------+---------+------+----------+--------------------------------------------+----------+
3 rows in set (0.000 sec)

范例:找到未完成的导致阻塞的事务

#在第一会话中执行
MariaDB [hellodb]> begin;
Query OK, 0 rows affected (0.000 sec)
MariaDB [hellodb]> update students set classid=10;

#在第二个会话中执行
MariaDB [hellodb]> update students set classid=20;


#在第三个会话中执行
MariaDB [hellodb]> show engine innodb status;
...省略...
---TRANSACTION 120, ACTIVE 673 sec
2 lock struct(s), heap size 1136, 28 row lock(s), undo log entries 27
MySQL thread id 13, OS thread handle 139719808595712, query id 206 localhost
root

...省略...
MariaDB [hellodb]> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
+-----------+-------------+-----------+-----------+----------------------+------
------+------------+-----------+----------+-----------+
| lock_id   | lock_trx_id | lock_mode | lock_type | lock_table           |
lock_index | lock_space | lock_page | lock_rec | lock_data |
+-----------+-------------+-----------+-----------+----------------------+------
------+------------+-----------+----------+-----------+
| 123:9:3:2 | 123         | X         | RECORD   | `hellodb`.`students` |
PRIMARY   |          9 |         3 |        2 | 1         |
| 120:9:3:2 | 120         | X         | RECORD   | `hellodb`.`students` |
PRIMARY   |          9 |         3 |        2 | 1         |
+-----------+-------------+-----------+-----------+----------------------+------
------+------------+-----------+----------+-----------+
2 rows in set (0.001 sec)
MariaDB [hellodb]> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
+-------------------+-------------------+-----------------+------------------+
| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |
+-------------------+-------------------+-----------------+------------------+
| 123               | 123:9:3:2         | 120             | 120:9:3:2       |
+-------------------+-------------------+-----------------+------------------+
1 row in set (0.000 sec)

#查看正在进行的事务
MariaDB [hellodb]> SELECT * FROM information_schema.INNODB_TRX\G
*************************** 1. row ***************************
                  trx_id: 123
                trx_state: LOCK WAIT
              trx_started: 2019-11-22 19:17:06
    trx_requested_lock_id: 123:9:3:2
        trx_wait_started: 2019-11-22 19:18:50
              trx_weight: 2
      trx_mysql_thread_id: 15 #线程ID
                trx_query: update students set classid=20
      trx_operation_state: starting index read
        trx_tables_in_use: 1
        trx_tables_locked: 1
        trx_lock_structs: 2
    trx_lock_memory_bytes: 1136
          trx_rows_locked: 2
        trx_rows_modified: 0
  trx_concurrency_tickets: 0
      trx_isolation_level: REPEATABLE READ
        trx_unique_checks: 1
  trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
        trx_is_read_only: 0
trx_autocommit_non_locking: 0
*************************** 2. row ***************************
                  trx_id: 120
                trx_state: RUNNING
              trx_started: 2019-11-22 19:08:51
    trx_requested_lock_id: NULL
        trx_wait_started: NULL
              trx_weight: 29
      trx_mysql_thread_id: 13                                    #线程ID
                trx_query: NULL
      trx_operation_state: NULL
        trx_tables_in_use: 0
        trx_tables_locked: 1
        trx_lock_structs: 2
    trx_lock_memory_bytes: 1136
          trx_rows_locked: 28
        trx_rows_modified: 27
  trx_concurrency_tickets: 0
      trx_isolation_level: REPEATABLE READ
        trx_unique_checks: 1
  trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
        trx_is_read_only: 0
trx_autocommit_non_locking: 0
2 rows in set (0.000 sec)


MariaDB [hellodb]> show processlist;

+----+-------------+-----------+---------+---------+------+---------------------
-----+------------------+----------+
| Id | User       | Host     | db     | Command | Time | State              
    | Info             | Progress |
+----+-------------+-----------+---------+---------+------+---------------------
-----+------------------+----------+
|  1 | system user |           | NULL   | Daemon | NULL | InnoDB purge
coordinator | NULL             |    0.000 |
|  3 | system user |           | NULL   | Daemon | NULL | InnoDB purge worker
    | NULL             |    0.000 |
|  4 | system user |           | NULL   | Daemon | NULL | InnoDB purge worker
    | NULL             |    0.000 |
|  2 | system user |           | NULL   | Daemon | NULL | InnoDB purge worker
    | NULL             |    0.000 |
|  5 | system user |           | NULL   | Daemon | NULL | InnoDB shutdown
handler | NULL             |    0.000 |
| 11 | root       | localhost | hellodb | Query   |    0 | Init                
    | show processlist |    0.000 |
| 13 | root       | localhost | hellodb | Sleep   |   38 |                    
    | NULL             |    0.000 |
+----+-------------+-----------+---------+---------+------+---------------------
-----+------------------+----------+
7 rows in set (0.000 sec)


#杀掉未完成的事务
MariaDB [hellodb]> kill 13;
Query OK, 0 rows affected (0.000 sec)
#查看事务锁的超时时长,默认50s
MariaDB [hellodb]> show global variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name           | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 50   |
+--------------------------+-------+
1 row in set (0.001 sec)
事务隔离级别

面试重点。

MySQL 支持四种隔离级别,事务隔离级别:从上至下更加严格

image-20240531070841099

  • READ UNCOMMITTED

可读取到未提交数据,产生脏读

  • READ COMMITTED

可读取到提交数据,但未提交数据不可读,产生不可重复读,即可读取到多个提交数据,导致每次读取数据不一致

  • REPEATABLE READ

可重复读,多次读取数据都一致,产生幻读,即读取过程中,即使有其它提交的事务修改数据,仍只能读取到未修改前的旧数据。此为MySQL默认设置

  • SERIALIZABLE

可串行化,未提交的读事务阻塞修改事务(加读锁,但不阻塞读事务),或者未提交的修改事务阻塞读事务(加写锁,其它事务的读,写都不可以执行)。会导致并发性能差。

MVCC和事务的隔离级别

MVCC(多版本并发控制机制)只在REPEATABLE READ和READ COMMITTED两个隔离级别下工作。其他两个隔离级别都和MVCC不兼容,因为READ UNCOMMITTED总是读取最新的数据行,而不是符合当前事务版本的数据行。而SERIALIZABLE则会对所有读取的行都加锁。

指定事务隔离级别:

  • 服务器变量tx_isolation指定,默认为REPEATABLE-READ,可在GLOBAL和SESSION级进行设置

    SET tx_isolation='READ-UNCOMMITTED|READ-COMMITTED|REPEATABLE-READ|SERIALIZABLE'
  • 服务器选项中指定

    vim /etc/my.cnf
    [mysqld]
    transaction-isolation=SERIALIZABLE

死锁:

两个或多个事务在同一资源相互占用,并请求锁定对方占用的资源的状态。

死锁问题,数据库会自动解决。

日志管理

MySQL 支持丰富的日志类型,如下:

  • 事务日志:transaction log

    事务日志的写入类型为“追加”,因此其操作为“顺序IO”;通常也被称为:预写式日志 write ahead logging

    事务日志文件: ib_logfile0, ib_logfile1

  • 错误日志 error log

  • 通用日志 general log

  • 慢查询日志 slow query log

  • 二进制日志 binary log

  • 中继日志 reley log,在主从复制架构中,从服务器用于保存从主服务器的二进制日志中读取的事

事务日志

事务日志:transaction log

事务型存储引擎自行管理和使用,建议和数据文件分开存放,redo log和undo log

Innodb事务日志相关配置

show variables like '%innodb_log%';

MariaDB [hellodb]> show variables like '%innodb_log%';
+-----------------------------+-----------+
| Variable_name | Value |
+-----------------------------+-----------+
| innodb_log_buffer_size | 16777216 |
| innodb_log_checksums | ON |
| innodb_log_compressed_pages | ON |
| innodb_log_file_size | 100663296 |
| innodb_log_files_in_group | 1 |
| innodb_log_group_home_dir | ./ |
| innodb_log_optimize_ddl | OFF |
| innodb_log_write_ahead_size | 8192 |
+-----------------------------+-----------+
8 rows in set (0.001 sec)

说明:

innodb_log_file_size   50331648   #每个日志文件大小 #50M
innodb_log_files_in_group  2     #日志组成员个数
innodb_log_group_home_dir ./ #事务文件路径
innodb_flush_log_at_trx_commit #默认为1(尤其这个值)

配置文件里修改事务日志选项:(修改成功)

[root@test ~]# mkdir -p /data/trans_log
[root@test ~]# chown mysql.mysql /data/trans_log/


# vim /etc/my.cnf.d/server.cnf
[mysqld]
……
innodb_log_group_home_dir=/data/trans_log
innodb_log_files_in_group=3
innodb_log_file_size=200M


[root@test ~]# systemctl restart mariadb

image-20240612073952034

事务日志性能优化:

innodb_flush_log_at_trx_commit=0|1|2

image-20240612072610525

1 此为默认值,日志缓冲区将写入日志文件,并在每次事务后执行刷新到磁盘。 这是完全遵守ACID特性

0 提交时没有写磁盘的操作; 而是每秒执行一次将日志缓冲区的提交的事务写入刷新到磁盘。 这样可提供更好的性能,但服务器崩溃可能丢失最后一秒的事务

2 每次提交后都会写入OS的缓冲区,但每秒才会进行一次刷新到磁盘文件中。 性能比0略差一些,但操作系统或停电可能导致最后一秒的交易丢失

高并发业务行业最佳实践,是使用第三种折衷配置(=2):

1.配置为2和配置为0,性能差异并不大,因为将数据从Log Buffer拷贝到OS cache,虽然跨越用户态与内核态,但毕竟只是内存的数据拷贝,速度很快

2.配置为2和配置为0,安全性差异巨大,操作系统崩溃的概率相比MySQL应用程序崩溃的概率,小很多,设置为2,只要操作系统不奔溃,也绝对不会丢数据

说明:

设置为1,同时sync_binlog = 1表示最高级别的容错

innodb_use_global_flush_log_at_trx_commit=0 时,将不能用SET语句重置此变量( MariaDB 10.2.6 后废弃)

错误日志

错误日志

mysqld启动和关闭过程中输出的事件信息

mysqld运行中产生的错误信息

event scheduler运行一个event时产生的日志信息

在主从复制架构中的从服务器上启动从服务器线程时产生的信息

错误文件路径

SHOW GLOBAL VARIABLES LIKE 'log_error';

范例:

MariaDB [hellodb]> SHOW GLOBAL VARIABLES LIKE 'log_error'; 
+---------------+------------------------------+
| Variable_name | Value                       |
+---------------+------------------------------+
| log_error     | /var/log/mariadb/mariadb.log |
+---------------+------------------------------+
1 row in set (0.001 sec)

image-20240909091920194

记录哪些警告信息至错误日志文件

#CentOS7 mariadb 5.5 默认值为1
#CentOS8 mariadb 10.3 默认值为2
log_warnings=0|1|2|3...

范例:

MariaDB [hellodb]> SHOW GLOBAL VARIABLES LIKE 'log_warnings'; 
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_warnings | 2     |
+---------------+-------+
1 row in set (0.001 sec)

image-20240909092832230

通用日志

通用日志:记录对数据库的通用操作,包括:错误的SQL语句

通用日志可以保存在:file(默认值)或 table(mysql.general_log表

通用日志相关设置

general_log=ON|OFF
general_log_file=HOSTNAME.log

log_output=TABLE|FILE|NONE

范例:

#修改通用日志,记录通用日志至mysql.general_log表中
MariaDB [mysql]> set global log_output="table";
MariaDB [mysql]> SHOW GLOBAL VARIABLES LIKE 'log_output';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output   | TABLE |
+---------------+-------+
1 row in set (0.002 sec)
MariaDB [mysql]> select * from mysql.general_log\G
...省略...
*************************** 6. row ***************************
event_time: 2019-11-25 11:03:41.163896
  user_host: root[root] @ localhost []
  thread_id: 9
  server_id: 1
command_type: Query
  argument: xxx
*************************** 7. row ***************************
event_time: 2019-11-25 11:03:44.549211
  user_host: root[root] @ localhost []
  thread_id: 8
  server_id: 1
command_type: Query
  argument: select * from general_log
7 rows in set (0.000 sec)

范例:对访问的语句进行排序

[root@centos8 ~]#mysql -e 'select argument from mysql.general_log' | awk 
'{sql[$0]++}END{for(i in sql){print sql[i],i}}'|sort -nr

[root@centos8 ~]#mysql -e 'select argument from mysql.general_log' |sort |uniq -
c |sort -nr

image-20240909095554961

image-20240909095538233

image-20240909095614208

慢查询日志

慢查询日志:记录执行查询时长超出指定时长的操作

慢查询相关变量

slow_query_log=ON|OFF #开启或关闭慢查询,支持全局和会话,只有全局设置才会生成慢查询文件
long_query_time=N #慢查询的阀值,单位秒(默认是10s)
slow_query_log_file=HOSTNAME-slow.log  #慢查询日志文件


log_slow_filter = admin,filesort,filesort_on_disk,full_join,full_scan,
query_cache,query_cache_miss,tmp_table,tmp_table_on_disk
#上述查询类型且查询时长超过long_query_time,则记录日志

log_queries_not_using_indexes=ON  #不使用索引或使用全索引扫描,不论是否达到慢查询阀值的语句是否记录日志,默认OFF,即不记录
log_slow_rate_limit = 1 #多少次查询才记录,mariadb特有
log_slow_verbosity= Query_plan,explain #记录内容
log_slow_queries = OFF    #同slow_query_log,MariaDB 10.0/MySQL 5.6.1 版后已删除

范例:模拟慢查询情况

这个事务得30-40s:

image-20240909112156641

image-20240909112302697

范例:模拟慢查询情况

1s查询1行。

image-20240909112512640

image-20240909112541195

范例:未使用索引,慢查询记录

log_queries_not_using_indexes=ON  #不使用索引或使用全索引扫描,不论是否达到慢查询阀值的语句是否记录日志,默认OFF,即不记录

image-20240909113939289

创建索引:

image-20240909114008079

再次查询:

image-20240909114048645

可以看到,本次未触发慢日志功能:

image-20240909114113479

慢查询分析工具

mysqldumpslow -s c -t 10 /data/mysql/slow.log

使用profile工具

#打开后,会显示语句执行详细的过程
set profiling = ON
#查看语句,注意结果中的query_id值
show profiles ;
MariaDB [hellodb]> show profiles ;
+----------+------------+-------------------------------------+
| Query_ID | Duration   | Query                               |
+----------+------------+-------------------------------------+
|        1 | 0.00019238 | select  @@profiling                 |
|        2 | 0.00115590 | select * from students where age=20 |
|        3 | 0.00006616 | show profiles for query 2           |
|        4 | 4.00319568 | select sleep(1) from teachers       |
+----------+------------+-------------------------------------+
4 rows in set (0.000 sec)
#显示语句的详细执行步骤和时长
Show profile for query #  
MariaDB [hellodb]> show profile for query 4;
+------------------------+----------+
| Status                 | Duration |
+------------------------+----------+
| Starting               | 0.000157 |
| Checking permissions   | 0.000009 |
| Opening tables         | 0.000025 |
| After opening tables   | 0.000005 |
| System lock           | 0.000004 |
| Table lock             | 0.000006 |
| Init                   | 0.000017 |
| Optimizing             | 0.000009 |
| Statistics             | 0.000018 |
| Preparing             | 0.000028 |
| Executing             | 0.000003 |
| Sending data           | 0.000070 |
| User sleep             | 1.001128 |
| User sleep             | 1.000313 |
| User sleep             | 1.000834 |
| User sleep             | 1.000348 |
| End of update loop     | 0.000032 |
| Query end             | 0.000003 |
| Commit                 | 0.000014 |
| Closing tables         | 0.000004 |
| Unlocking tables       | 0.000003 |
| Closing tables         | 0.000012 |
| Starting cleanup       | 0.000003 |
| Freeing items         | 0.000056 |
| Updating status       | 0.000024 |
| Logging slow query     | 0.000069 |
| Reset for next command | 0.000004 |
+------------------------+----------+
27 rows in set (0.000 sec)



MariaDB [hellodb]>
#显示cpu使用情况
Show profile cpu for query #
MariaDB [hellodb]> Show profile cpu for query 4;
+------------------------+----------+----------+------------+
| Status                 | Duration | CPU_user | CPU_system |
+------------------------+----------+----------+------------+
| Starting               | 0.000157 | 0.000090 |   0.000065 |
| Checking permissions   | 0.000009 | 0.000005 |   0.000004 |
| Opening tables         | 0.000025 | 0.000014 |   0.000010 |
| After opening tables   | 0.000005 | 0.000003 |   0.000002 |
| System lock           | 0.000004 | 0.000002 |   0.000002 |
| Table lock             | 0.000006 | 0.000004 |   0.000002 |
| Init                   | 0.000017 | 0.000010 |   0.000007 |
| Optimizing             | 0.000009 | 0.000005 |   0.000004 |
| Statistics             | 0.000018 | 0.000010 |   0.000007 |
| Preparing             | 0.000028 | 0.000016 |   0.000012 |
| Executing             | 0.000003 | 0.000002 |   0.000002 |
| Sending data           | 0.000070 | 0.000059 |   0.000000 |
| User sleep             | 1.001128 | 0.000665 |   0.000000 |
| User sleep             | 1.000313 | 0.000716 |   0.000000 |
| User sleep             | 1.000834 | 0.000379 |   0.000100 |
| User sleep             | 1.000348 | 0.000319 |   0.000231 |
| End of update loop     | 0.000032 | 0.000017 |   0.000012 |
| Query end             | 0.000003 | 0.000002 |   0.000002 |
| Commit                 | 0.000014 | 0.000008 |   0.000005 |
| Closing tables         | 0.000004 | 0.000002 |   0.000002 |
| Unlocking tables       | 0.000003 | 0.000002 |   0.000001 |
| Closing tables         | 0.000012 | 0.000007 |   0.000005 |
| Starting cleanup       | 0.000003 | 0.000001 |   0.000001 |
| Freeing items         | 0.000056 | 0.000034 |   0.000024 |
| Updating status       | 0.000024 | 0.000013 |   0.000010 |
| Logging slow query     | 0.000069 | 0.000040 |   0.000029 |
| Reset for next command | 0.000004 | 0.000002 |   0.000001 |
+------------------------+----------+----------+------------+
27 rows in set (0.000 sec)
MariaDB [hellodb]>

二进制日志(备份)(很重要)

在工作中肯定是要启用二进制日志的。(增删改操作都会记录到)

  • 记录导致数据改变或潜在导致数据改变的SQL语句
  • 记录已提交的日志
  • 不依赖于存储引擎类型

功能:通过“重放”日志文件中的事件来生成数据副本

注意:建议二进制日志和数据文件分开存放

二进制日志记录三种格式

  • 基于“语句”记录:statement,记录语句,默认模式( MariaDB 10.2.3 版本以下 ),日志量较少
  • 基于“行”记录:row,记录数据,日志量较大,更加安全,建议使用的格式
  • 混合模式:mixed, 让系统自行判定该基于哪种方式进行,默认模式( MariaDB 10.2.4及版本以上)

格式配置

MariaDB [hellodb]> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | MIXED |
+---------------+-------+
1 row in set (0.001 sec)



#MySQL 8.0 默认使用ROW方式
mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set (0.07 sec)

二进制日志文件的构成

有两类文件
1.日志文件:mysql|mariadb-bin.文件名后缀,二进制格式,如: mariadb-bin.000001
2.索引文件:mysql|mariadb-bin.index,文本格式

二进制日志相关的服务器变量:

sql_log_bin=ON|OFF:#是否记录二进制日志,默认ON,支持动态修改,系统变量,而非服务器选项(是一个sesson变量)
log_bin=/PATH/BIN_LOG_FILE:#指定文件位置;默认OFF,表示不启用二进制日志功能,上述两项都开启才可以


binlog_format=STATEMENT|ROW|MIXED:#二进制日志记录的格式,默认STATEMENT
max_binlog_size=1073741824#单个二进制日志文件的最大体积,到达最大值会自动滚动,默认为1G
#说明:文件达到上限时的大小未必为指定的精确值
#事务日志:默认是2个

binlog_cache_size=4m #此变量确定在每次事务中保存二进制日志更改记录的缓存的大小(每次连接)
max_binlog_cache_size=512m #限制用于缓存多事务查询的字节大小。

sync_binlog=1|0#设定是否启动二进制日志即时同步磁盘功能,默认0,由操作系统负责同步日志到磁盘
expire_logs_days=N:#二进制日志可以自动删除的天数。 默认为0,即不自动删除

范例:

image-20240909142741505

image-20240909143145695


二进制日志相关配置

查看mariadb自行管理使用中的二进制日志文件列表,及大小

SHOW {BINARY | MASTER} LOGS

image-20240909150706337

查看使用中的二进制日志文件

SHOW MASTER STATUS

image-20240915072035595

在线查看二进制文件中的指定内容

SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]

范例:

show binlog events in 'mysql-bin.000001' from 6516 limit 2,3

image-20240915072208293


清除指定二进制日志

PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr }

范例:

PURGE BINARY LOGS TO 'mariadb-bin.000003'; #删除mariadb-bin.000003之前的日志
PURGE BINARY LOGS BEFORE '2017-01-23';
PURGE BINARY LOGS BEFORE '2017-03-22 09:25:30';

删除所有二进制日志,index文件重新记数

RESET MASTER [TO #]; #删除所有二进制日志文件,并重新生成日志文件,文件名从#开始记数,默认从
1开始,一般是master主机第一次启动时执行,MariaDB 10.1.6开始支持TO #

刷新二进制日志文件的方法:

方法1:重启服务,可以生成一个新的二进制日志文件

方法2:切换日志文件:

FLUSH LOGS;

image-20240917103749278

方法3:

mysqladmin flush-logs

image-20240917104516878

5、备份和恢复

5.1 备份恢复概述

image-20240917105452922

5.1.1 为什么要备份

灾难恢复:硬件故障、软件故障、自然灾害、黑客攻击、误操作测试等数据丢失场景。

5.1.2 备份类型

  • 完全备份,部分备份

    完全备份:整个数据集

​ 部分备份:只备份数据子集,如部分库或表

  • 完全备份、增量备份、差异备份

​ 增量备份:仅备份最近一次完全备份或增量备份(如果存在增量)以来变化的数据,备份较快,还原复杂。

image-20240917105834407

​ 差异备份:仅备份最近一次完全备份以来变化的数据,备份较慢,还原简单

image-20240917105856311

注意:二进制日志文件不应该与数据文件放在同一磁盘。

  • 冷、温、热备份

冷备:读、写操作均不可进行,数据库停止服务

温备:读操作可执行;但写操作不可执行

热备:读、写操作均可执行

MyISAM:温备,不支持热备

InnoDB:都支持

事务具有隔离性。(可重复读)

  • 物理和逻辑备份

物理备份:直接复制数据文件进行备份,与存储引擎有关,占用较多的空间,速度快

逻辑备份:从数据库中“导出”数据另存而进行的备份,与存储引擎无关,占用空间少,速度慢,可能丢失精度

5.1.3 备份什么

  • 数据
  • 二进制日志、InnoDB的事务日志
  • 用户帐号,权限设置,程序代码(存储过程、函数、触发器、事件调度器)
  • 服务器的配置文件

5.1.4 备份注意要点

  • 能容忍最多丢失多少数据
  • 备份产生的负载
  • 备份过程的时长
  • 温备的持锁多久
  • 恢复数据需要在多长时间内完成
  • 需要备份和恢复哪些数据

5.1.5 还原要点

  • 做还原测试,用于测试备份的可用性
  • 还原演练,写成规范的技术文档

5.1.6 备份工具

  • cp, tar等复制归档工具:物理备份工具,适用所有存储引擎;只支持冷备;完全和部分备份

  • LVM的快照:先加读锁,做快照后解锁,几乎热备;借助文件系统工具进行备份;--(工作里用的极少)

  • mysqldump:逻辑备份工具,适用所有存储引擎,对MyISAM存储引擎进行温备;支持完全或部分备份;对InnoDB存储引擎支持热备,结合binlog的增量备份。

  • xtrabackup:由Percona提供支持对InnoDB做热备(物理备份)的工具,支持完全备份、增量备份--(大型公司可能会用到)

  • MariaDB Backup: 从MariaDB 10.1.26开始集成,基于Percona XtraBackup 2.3.8实现

  • mysqlbackup:热备份, MySQL Enterprise Edition组件

  • mysqlhotcopy:PERL 语言实现,几乎冷备,仅适用于MyISAM存储引擎,使用LOCK TABLES、FLUSH TABLES和cp或scp来快速备份数据库--(用的少)

5.1.6 基于 LVM 的快照备份

前提:你的数据库要存放在lvm里。

(1) 请求锁定所有表
mysql> FLUSH TABLES WITH READ LOCK; (这里不要关窗口哦)

(2) 记录二进制日志文件及事件位置
mysql> FLUSH LOGS;
mysql> SHOW MASTER STATUS;
mysql -e 'SHOW MASTER STATUS' > /PATH/TO/SOMEFILE

(3) 创建快照
lvcreate -L # -s -p r -n NAME /DEV/VG_NAME/LV_NAME

(4) 释放锁
mysql> UNLOCK TABLES;
(5) 挂载快照卷,执行数据备份
(6) 备份完成后,删除快照卷
(7) 制定好策略,通过原卷备份二进制日志

5.1.7 实战案例:数据库冷备份和还原

#在目标服务器(10.0.0.18)安装mariadb-server,不启动服务
[root@centos8 ~]#dnf install mariadb-server


#在源主机(10.0.0.8)执行
[root@centos8 ~]# systemctl stop mariadb

#复制相关文件
[root@centos8 ~]# scp /etc/my.cnf.d/mariadb-server.cnf 10.0.0.18:/etc/my.cnf.d/
[root@centos8 ~]# scp -r /var/lib/mysql/* 10.0.0.18:/var/lib/mysql/
[root@centos8 ~]# scp -r /data/logbin/ 10.0.0.18:/data/   #10.0.0.18事先存在/data/目录

#保留属性:可以用rsync
[root@centos8 ~]#rsync -av /var/lib/mysql/ 10.0.0.18:/var/lib/mysql/


#在目标主机(10.0.0.18)执行
[root@centos8 ~]#chown -R mysql.mysql /var/lib/mysql/
[root@centos8 ~]#chown -R mysql.mysql /data/logbin/
[root@centos8 ~]#systemctl start mariadb

5.2 mysqldump备份工具

5.3 xtrabackup备份工具

6、MySQL 集群 Cluster

7、性能优化

关于我

我的博客主旨:

  • 排版美观,语言精炼;
  • 文档即手册,步骤明细,拒绝埋坑,提供源码;
  • 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!

🍀 微信二维码 x2675263825 (舍得), qq:2675263825。

image-20230107215114763

🍀 微信公众号 《云原生架构师实战》

image-20230107215126971

🍀 个人博客站点

https://onedayxyy.cn

image-20240514065615678

🍀 csdn https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

image-20230107215149885

🍀 知乎 https://www.zhihu.com/people/foryouone

image-20230107215203185

最后

好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!


0%