# MySQL
## 简介
### 数据库
数据库:DataBase,简称 DB,用于存储和管理数据的仓库,它的存储空间很大,可以存放百万上亿条数据。
数据库的优势:
- 可以持久化存储数据
- 方便存储和管理数据
- 使用了统一的方式操作数据库 SQL
数据库、数据表、数据的关系介绍:
- 数据库
- 用于存储和管理数据的仓库
- 一个库中可以包含多个数据表
- 数据表
- 数据库最重要的组成部分之一
- 它由纵向的列和横向的行组成(类似 excel 表格)
- 可以指定列名、数据类型、约束等
- 一个表中可以存储多条数据
- 数据
- 想要永久化存储的数据

参考视频:https://www.bilibili.com/video/BV1zJ411M7TB(推荐观看)
***
### MySQL
MySQL数据库是一个最流行的关系型数据库管理系统之一
关系型数据库是将数据保存在不同的数据表中,而且表与表之间可以有关联关系,提高了灵活性。
缺点:数据存储在磁盘中,导致读写性能差,而且数据关系复杂,扩展性差
MySQL所使用的SQL语句是用于访问数据库最常用的标准化语言。
MySQL配置:
* MySQL 安装:https://www.jianshu.com/p/ba48f1e386f0
* MySQL 配置:
* 修改 MySQL 默认字符集:安装 MySQL 之后第一件事就是修改字符集编码
```mysql
vim /etc/mysql/my.cnf
添加如下内容:
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
[client]
default-character-set=utf8
```
* 启动 MySQL 服务:
```shell
systemctl start/restart mysql
```
* 登录 MySQL:
```shell
mysql -u root -p 敲回车,输入密码
初始密码查看:cat /var/log/mysqld.log
在root@localhost: 后面的就是初始密码
```
* 查看默认字符集命令:
```mysql
SHOW VARIABLES LIKE 'char%';
```
* 修改MySQL登录密码:
```mysql
set global validate_password_policy=0;
set global validate_password_length=1;
set password=password('密码');
```
* 授予远程连接权限(MySQL 内输入):
```mysql
-- 授权
grant all privileges on *.* to 'root' @'%' identified by '密码';
-- 刷新
flush privileges;
```
* 修改 MySQL 绑定 IP:
```shell
cd /etc/mysql/mysql.conf.d
sudo chmod 666 mysqld.cnf
vim mysqld.cnf
#bind-address = 127.0.0.1注释该行
```
* 关闭 Linux 防火墙
```shell
systemctl stop firewalld.service
放行3306端口
```
***
### 常用工具
#### mysql
mysql 不是指 mysql 服务,而是指 mysql 的客户端工具
```sh
mysql [options] [database]
```
* -u --user=name:指定用户名
* -p --password[=name]:指定密码
* -h --host=name:指定服务器IP或域名
* -P --port=#:指定连接端口
* -e --execute=name:执行SQL语句并退出,在控制台执行SQL语句,而不用连接到数据库执行
示例:
```sh
mysql -h 127.0.0.1 -P 3306 -u root -p
mysql -uroot -p2143 db01 -e "select * from tb_book";
```
***
#### admin
mysqladmin 是一个执行管理操作的客户端程序,用来检查服务器的配置和当前状态、创建并删除数据库等
通过 `mysqladmin --help` 指令查看帮助文档
```sh
mysqladmin -uroot -p2143 create 'test01';
```
***
#### binlog
服务器生成的日志文件以二进制格式保存,如果需要检查这些文本,就要使用 mysqlbinlog 日志管理工具
```sh
mysqlbinlog [options] log-files1 log-files2 ...
```
* -d --database=name:指定数据库名称,只列出指定的数据库相关操作
* -o --offset=#:忽略掉日志中的前n行命令。
* -r --result-file=name:将输出的文本格式日志输出到指定文件。
* -s --short-form:显示简单格式, 省略掉一些信息。
* --start-datatime=date1 --stop-datetime=date2:指定日期间隔内的所有日志。
* --start-position=pos1 --stop-position=pos2:指定位置间隔内的所有日志。
***
#### dump
##### 命令介绍
mysqldump 客户端工具用来备份数据库或在不同数据库之间进行数据迁移,备份内容包含创建表,及插入表的SQL语句
```sh
mysqldump [options] db_name [tables]
mysqldump [options] --database/-B db1 [db2 db3...]
mysqldump [options] --all-databases/-A
```
连接选项:
* -u --user=name:指定用户名
* -p --password[=name]:指定密码
* -h --host=name:指定服务器IP或域名
* -P --port=#:指定连接端口
输出内容选项:
* --add-drop-database:在每个数据库创建语句前加上 Drop database 语句
* --add-drop-table:在每个表创建语句前加上 Drop table 语句 , 默认开启 ; 不开启 (--skip-add-drop-table)
* -n --no-create-db:不包含数据库的创建语句
* -t --no-create-info:不包含数据表的创建语句
* -d --no-data:不包含数据
* -T, --tab=name:自动生成两个文件:一个.sql文件,创建表结构的语句;一个.txt文件,数据文件,相当于select into outfile
示例:
```sh
mysqldump -uroot -p2143 db01 tb_book --add-drop-database --add-drop-table > a
mysqldump -uroot -p2143 -T /tmp test city
```
***
##### 数据备份
命令行方式:
* 备份命令:mysqldump -u root -p 数据库名称 > 文件保存路径
* 恢复
1. 登录MySQL数据库:`mysql -u root p`
2. 删除已经备份的数据库
3. 重新创建与备份数据库名称相同的数据库
4. 使用该数据库
5. 导入文件执行:`source 备份文件全路径`
图形化界面:
* 备份

* 恢复

***
#### import
mysqlimport 是客户端数据导入工具,用来导入mysqldump 加 -T 参数后导出的文本文件
```sh
mysqlimport [options] db_name textfile1 [textfile2...]
```
示例:
```sh
mysqlimport -uroot -p2143 test /tmp/city.txt
```
导入 sql 文件,可以使用 MySQL 中的 source 指令 :
```mysql
source 文件全路径
```
***
#### show
mysqlshow 客户端对象查找工具,用来很快地查找存在哪些数据库、数据库中的表、表中的列或者索引
```sh
mysqlshow [options] [db_name [table_name [col_name]]]
```
* --count:显示数据库及表的统计信息(数据库,表 均可以不指定)
* -i:显示指定数据库或者指定表的状态信息
示例:
```sh
#查询每个数据库的表的数量及表中记录的数量
mysqlshow -uroot -p1234 --count
#查询test库中每个表中的字段书,及行数
mysqlshow -uroot -p1234 test --count
#查询test库中book表的详细情况
mysqlshow -uroot -p1234 test book --count
```
***
## 体系结构
体系结构详解:
* 第一层:网络连接层
* 一些客户端和链接服务,包含本地 socket 通信和大多数基于客户端/服务端工具实现的 TCP/IP 通信,主要完成一些类似于连接处理、授权认证、及相关的安全方案
* 在该层上引入了线程池 Connection Pool 的概念,管理缓冲用户连接,线程处理等需要缓存的需求
* 在该层上实现基于 SSL 的安全链接,服务器也会为安全接入的每个客户端验证它所具有的操作权限
- 第二层:核心服务层
* 完成大多数核心服务功能,如 SQL接口,并完成缓存的查询,SQL的分析和优化:
* Management Serveices & Utilities:系统管理和控制工具,备份、安全、复制、集群等
* SQL Interface:接受用户的 SQL 命令,并且返回用户需要查询的结果
* Parser:SQL 语句解析器
* Optimizer:查询优化器,SQL 语句在查询之前会使用查询优化器进行优化,优化客户端查找请求,根据客户端请求的 query 语句和数据库中的一些统计信息进行分析,得出一个最优策略
* Caches & Buffers:查询缓存,服务器会查询内部的缓存,如果缓存空间足够大,可以在大量读操作的环境中提升系统的性能
* 所有**跨存储引擎**的功能在这一层实现,如存储过程、触发器、视图等
* 在该层服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化如确定表的查询顺序,是否利用索引等, 最后生成相应的执行操作
* MySQL 中服务器层不管理事务,**事务是由存储引擎实现的**
- 第三层:存储引擎层
- Pluggable Storage Engines:存储引擎接口,MySQL 区别于其他数据库的最重要的特点就是其插件式的表存储引擎(**存储引擎是基于表的,而不是数据库**)
- 存储引擎真正的负责了 MySQL 中数据的存储和提取,服务器通过 API 和存储引擎进行通信
- 不同的存储引擎具有不同的功能,可以根据开发的需要,来选取合适的存储引擎
- 第四层:系统文件层
- 数据存储层,主要是将数据存储在文件系统之上,并完成与存储引擎的交互
- File System:文件系统,保存配置文件、数据文件、日志文件、错误文件、二进制文件等

***
## 单表操作
### SQL
- SQL
- Structured Query Language:结构化查询语言
- 定义了操作所有关系型数据库的规则,每种数据库操作的方式可能会存在不一样的地方,称为“方言”
- SQL通用语法
- SQL 语句可以单行或多行书写,以**分号结尾**。
- 可使用空格和缩进来增强语句的可读性。
- MySQL 数据库的 SQL 语句不区分大小写,**关键字建议使用大写**。
- 数据库的注释:
- 单行注释:-- 注释内容 #注释内容(mysql特有)
- 多行注释:/* 注释内容 */
- SQL分类
- DDL(Data Definition Language)数据定义语言
- 用来定义数据库对象:数据库,表,列等。关键字:create、drop,、alter 等
- DML(Data Manipulation Language)数据操作语言
- 用来对数据库中表的数据进行增删改。关键字:insert、delete、update 等
- DQL(Data Query Language)数据查询语言
- 用来查询数据库中表的记录(数据)。关键字:select、where 等
- DCL(Data Control Language)数据控制语言
- 用来定义数据库的访问权限和安全级别,及创建用户。关键字:grant, revoke等

***
### DDL
#### 数据库
* R(Retrieve):查询
* 查询所有数据库:
```mysql
SHOW DATABASES;
```
* 查询某个数据库的创建语句
```sql
SHOW CREATE DATABASE 数据库名称; -- 标准语法
SHOW CREATE DATABASE mysql; --查看mysql数据库的创建格式
```
* C(Create):创建
* 创建数据库
```mysql
CREATE DATABASE 数据库名称;-- 标准语法
CREATE DATABASE db1; -- 创建db1数据库
```
* 创建数据库(判断,如果不存在则创建)
```mysql
CREATE DATABASE IF NOT EXISTS 数据库名称;
```
* 创建数据库,并指定字符集
```mysql
CREATE DATABASE 数据库名称 CHARACTER SET 字符集名称;
```
* 例如:创建db4数据库、如果不存在则创建,指定字符集为gbk
```mysql
-- 创建db4数据库、如果不存在则创建,指定字符集为gbk
CREATE DATABASE IF NOT EXISTS db4 CHARACTER SET gbk;
-- 查看db4数据库的字符集
SHOW CREATE DATABASE db4;
```
* U(Update):修改
* 修改数据库的字符集
```mysql
ALTER DATABASE 数据库名称 CHARACTER SET 字符集名称;
```
* 常用字符集:
```mysql
--查询所有支持的字符集
SHOW CHARSET;
--查看所有支持的校对规则
SHOW COLLATION;
-- 字符集: utf8,latinI,GBK,,GBK是utf8的子集
-- 校对规则: ci 大小定不敏感,cs或bin大小写敏感
```
* D(Delete):删除
* 删除数据库:
```mysql
DROP DATABASE 数据库名称;
```
* 删除数据库(判断,如果存在则删除):
```mysql
DROP DATABASE IF EXISTS 数据库名称;
```
* 使用数据库:
* 查询当前正在使用的数据库名称
```mysql
SELECT DATABASE();
```
* 使用数据库
```mysql
USE 数据库名称; -- 标准语法
USE db4; -- 使用db4数据库
```
#### 数据表
- R(Retrieve):查询
- 查询数据库中所有的数据表
```mysql
USE mysql;-- 使用mysql数据库
SHOW TABLES;-- 查询库中所有的表
```
- 查询表结构
```mysql
DESC 表名;
```
- 查询表字符集
```mysql
SHOW TABLE STATUS FROM 库名 LIKE '表名';
```
- C(Create):创建
- 创建数据表
```mysql
CREATE TABLE 表名(
列名1 数据类型1,
列名2 数据类型2,
....
列名n 数据类型n
);
-- 注意:最后一列,不需要加逗号
```
- 复制表
```mysql
CREATE TABLE 表名 LIKE 被复制的表名; -- 标准语法
CREATE TABLE product2 LIKE product; -- 复制product表到product2表
```
- 数据类型
| 数据类型 | 说明 |
| --------- | ------------------------------------------------------------ |
| INT | 整数类型 |
| DOUBLE | 小数类型 |
| DATE | 日期,只包含年月日:yyyy-MM-dd |
| DATETIME | 日期,包含年月日时分秒:yyyy-MM-dd HH:mm:ss |
| TIMESTAMP | 时间戳类型,包含年月日时分秒:yyyy-MM-dd HH:mm:ss
如果不给这个字段赋值或赋值为null,则默认使用当前的系统时间 |
| VARCHAR | 字符串
name varchar(20):姓名最大20个字符:zhangsan8个字符,张三2个字符 |
`INT(n)`:n代表位数
* 3:int(9)显示结果为000000010
* 3:int(3)显示结果为010
`varchar(n)`:n表示的是字符数
- 例如:
```mysql
-- 使用db3数据库
USE db3;
-- 创建一个product商品表
CREATE TABLE product(
id INT, -- 商品编号
NAME VARCHAR(30), -- 商品名称
price DOUBLE, -- 商品价格
stock INT, -- 商品库存
insert_time DATE -- 上架时间
);
```
- U(Update):修改
- 修改表名
```mysql
ALTER TABLE 表名 RENAME TO 新的表名;
```
- 修改表的字符集
```mysql
ALTER TABLE 表名 CHARACTER SET 字符集名称;
```
- 添加一列
```mysql
ALTER TABLE 表名 ADD 列名 数据类型;
```
- 修改列数据类型
```mysql
ALTER TABLE 表名 MODIFY 列名 新数据类型;
```
- 修改列名称和数据类型
```mysql
ALTER TABLE 表名 CHANGE 列名 新列名 新数据类型;
```
- 删除列
```mysql
ALTER TABLE 表名 DROP 列名;
```
- D(Delete):删除
- 删除数据表
```mysql
DROP TABLE 表名;
```
- 删除数据表(判断,如果存在则删除)
```mysql
DROP TABLE IF EXISTS 表名;
```
***
### DML
#### INSERT
* 新增表数据
* 新增格式1:给指定列添加数据
```mysql
INSERT INTO 表名(列名1,列名2...) VALUES (值1,值2...);
```
* 新增格式2:默认给全部列添加数据
```mysql
INSERT INTO 表名 VALUES (值1,值2,值3,...);
```
* 新增格式3:批量添加数据
```mysql
-- 给指定列批量添加数据
INSERT INTO 表名(列名1,列名2,...) VALUES (值1,值2,...),(值1,值2,...)...;
-- 默认给所有列批量添加数据
INSERT INTO 表名 VALUES (值1,值2,值3,...),(值1,值2,值3,...)...;
```
* 字符串拼接
```mysql
CONCAT(string1,string2,'',...)
```
* 注意事项
- 列名和值的数量以及数据类型要对应
- 除了数字类型,其他数据类型的数据都需要加引号(单引双引都可以,推荐单引)
#### UPDATE
* 修改表数据语法
* 标准语法
```mysql
UPDATE 表名 SET 列名1 = 值1,列名2 = 值2,... [where 条件];
```
* 修改电视的价格为1800、库存为36
```mysql
UPDATE product SET price=1800,stock=36 WHERE NAME='电视';
SELECT * FROM product;-- 查看所有商品信息
```
* 注意事项
- 修改语句中必须加条件
- 如果不加条件,则将所有数据都修改
#### DELETE
* 删除表数据语法
```mysql
DELETE FROM 表名 [WHERE 条件];
```
* 注意事项
* 删除语句中必须加条件
* 如果不加条件,则将所有数据删除
***
### DQL
#### 查询语法
数据库查询遵循条件在前的原则
```mysql
SELECT DISTINCT