理解mysql数据库

1.MySQL 在 Centos 7环境安装 

1.1 卸载不要的环境

  • ps ajx |grep mariadb # 先检查是否有 mariadb 存在
  • systemctl stop mariadb.service # 停⽌ mariadb 服务
  • ps ajx |grep mariadb # 再 检查是否有 mariadb 存在

1.2 删除多余的安装包

  • rpm -qa | grep mysql  #查看默认安装包
  • rpm -qa | grep mysql | xargs yum -y remove #删除所有默认安装包 

1.3 获取mysql官⽅yum源

  • Index of /232905
  • cat /etc/redhat-release #查看版本
  • 找到一个和自己的系统一致的并安装

1.4 安装mysql yum 源,对⽐前后yum源

理解mysql数据库_第1张图片

  •  rpm -Uvh 安装包 #安装mysql yum源

1.5 查看是否能正常工作

理解mysql数据库_第2张图片

  •  yum list | grep mysql #查看所有的mysql文件

1.6 安装mysql服务

  • yum install -y mysql-community-serve #安装mysql服务
  • Failing package is: mysql-community-client-5.7.39-1.el7.x86_64
    GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
    • rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 #解决秘钥过期问题

1.7 数据存储位置 查看配置⽂件

  • ls /var/lib/mysql#查看数据存储位置 
  • ls /etc/my.cnf #查看配置文件

1.8 启动服务

  • systemctl start mysqld.service #启动服务
1.9 配置 && 登录
  •  vim /etc/my.cnf #打开配置文件
  • skip-grant-tables 选项 , 并保存退出
  • systemctl restart mysqld #重启mysqld服务
理解mysql数据库_第3张图片
  • root直接使用:mysql -uroot
  • mysql -h 127.0.0.1 -P 3306 -u root -p 

理解mysql数据库_第4张图片

  •  其他用户可以使用: mysql -h 127.0.0.1 -P 3306

2. 数据库基础

2.1 什么是数据库

理解mysql数据库_第5张图片

  •  已特定的格式保存好的文件,我们叫做数据库,
    • 默认存放路径 /var/lib/mysql
  • 提供较为便捷的数据的存取服务的软件集合,解决方案 -- mysql数据库

 2.1 为什么有数据库

理解mysql数据库_第6张图片

  • 文件或者数据库,其实都可以进行数据的存储
  • 如果用文件,数据内容的管理工作,需要程序员自己做!
  • 数据库的本质: 是对文件的内容提供基本的内容操作,不用程序员(用户)手动的进行数据管理
  •  数据库也是"文件系统"

 2.2 创建一个数据库的本质

图形化界面的访问数据库的软件 -- client

mysql的生态中,也会提供第三方库,让语言也能直接访问mysql --  client

理解mysql数据库_第7张图片

  • 建立一个数据库 create database XXX本质是在linux下建立了一个目录
  • 建一张表 的本质是在linux下创建对应的文件

 2.3 MySQL架构 

理解mysql数据库_第8张图片

  •  MySQL 是一个可移植的数据库,几乎能在当前所有的操作系统上运行,如 Unix/LinuxWindowsMac Solaris
  • 各种系统在底层实现方面各有不同,但是 MySQL 基本上能保证在各个平台上的物理体系结构的一致性。

2.4 SQL分类

  • DDLdata definition language数据定义语言,用来维护存储数据的结构 代表指令: create, drop, alter
  • DMLdata manipulation language数据操纵语言,用来对数据进行操作 代表指令: insertdeleteupdate
    • DML中又单独分了一个DQL,数据查询语言,代表指令: select
  • DCLData Control Language数据控制语言,主要负责权限管理和事务 代表指令: grantrevokecommit

2.5 存储引擎

理解mysql数据库_第9张图片

  •  show engines;// 查看存储引擎的命令

3. 库的操作

3.1 创建数据库

理解mysql数据库_第10张图片

  •  create database 名字;// 创建库
  • crate database '特殊名字';// 创建特殊名字的库,''会起到转移字符的作用

3.2 字符集和校验规则

字符集->将数据按照特定的编码存储 == mysql的数据

校验规则->读取数据时候的校验编码 == mysql的数据

一般字符集和校验规则(集) 匹配的

 理解mysql数据库_第11张图片

3.2.1 查看系统默认字符集以及校验规则  

理解mysql数据库_第12张图片

  •  show variables like 'character_set_database';查看系统默认字符集
  • show variables like 'collation_database';查看系统默认校验规则

3.3.2 查看数据库支持的字符集 && 校验规则

  • show charset;// 字符集

  • show collation;// 效验集

3.4 校验规则对数据库的影响 

理解mysql数据库_第13张图片

理解mysql数据库_第14张图片

  •  数据库的编码和效验规则,本质会影响对应的数据库内部的,比如查数据,比较数据

 3.5 补充数据库的创建

理解mysql数据库_第15张图片

  •  create database 库名字 character set 字符集 collate 效验规则
  • create database 库名字  charset=字符集 collate 效验规则

3.6  操纵数据库 

3.6.1 查看数据库 && 显示创建语句

理解mysql数据库_第16张图片

  •  show databases; //查看数据库
  • show create database 数据库名;// 显示创建语句
  • MySQL 建议我们关键字使用大写,但是不是必须的。
    数据库名字的 反引号`` , 是为了防止使用的数据库名刚好是关键字
    /*!40100 default.... */ 这个 不是注释 ,表示当前 mysql 版本大于 4.01 版本,就执行这句话

3.6.2 修改数据库

理解mysql数据库_第17张图片

  • alter database 名字 charset=字符集 collation 效验规则
  •  对数据库的修改主要指的是修改数据库的字符集,校验规则

3.6.3 数据库删除  

  • drop database 名字;
  • 对应的数据库文件夹被删除级联删除,里面的数据表全部被删
  • 建议不要随便的删除库

 3.6.4 备份和恢复

  • 备份: mysqldump -P3306 -u root -p 密码 -B 数据库名 > 数据库备份存储的文件路径
    • 一般备份是历史上所有的命令语句
  • 恢复: mysql> source 数据库备份存储的文件路径

单独备份数据库的表 

  • mysqldump -u root -p 数据库名 表名1 表名2 > 数据库备份存储的文件路径

备份多个数据库

  • mysqldump -u root -p -B 数据库名1 数据库名 2 ... > 数据库存放路径

3.6 查看连接情况

理解mysql数据库_第18张图片

  •  use 库名字; // 进入这个库 或 使用这个库
  • show processlist;// 查看数据库连接情况

4.表的操作

4.1 创建表

理解mysql数据库_第19张图片

理解mysql数据库_第20张图片

理解mysql数据库_第21张图片

  • t2 表存储引擎是mysiam,在数据目录中有三个不同的文件
  • t2.frm: 表结构
  • t2.MYD: 表数据
  • t2.MYI: 表索引

4.2 查看表

理解mysql数据库_第22张图片

  •  Field           Type           Null           Default   Extra    
  •  字段名字 字段类型 是否允许为空  默认值     扩充

4.3 修改表 

4.3.1 添加字段

理解mysql数据库_第23张图片

理解mysql数据库_第24张图片

  •  alter table 表名字 add 
  • 插入新字段后,对原来表中的数据没有影响: 

4.3.2 修改字段 

 理解mysql数据库_第25张图片

  • 修改name,将其长度改成60 
  •  alter table 表名字 modify 

4.3.3 删除字段  

理解mysql数据库_第26张图片

  •  alter table 表名字 drop
  • 注意: 但删除到只有一个字段的时候就不能删除了
            除非使用删除表的命令

4.4 删除表 

理解mysql数据库_第27张图片

  •  drop table 表名

5.  数据类型

5.1 数据类型分类

理解mysql数据库_第28张图片

  • 数据类型本质就是一种约束 

5.2 数值类型 

5.2.1 tinyint类型  

 理解mysql数据库_第29张图片

理解mysql数据库_第30张图片

  • MySQL 中,整型可以指定是 有符号 的和 无符号 的,默认是有符号的。
  •  mysql中是不会发生数据截断的,超过范围就会直接报错
注意 尽量不使用unsigned,对于int类型可能存放不下的数据,int unsigned同样可能存放不
下,与其如此,还不如设计时,将int类型提升为bigint类型

5.2.2 bit类型  

理解mysql数据库_第31张图片

  • bit 字段在 显示 时,是按照 ASCII 码对应的值显示

5.2.3 float类型

float [(m, d)] [ unsigned ] : M 指定显示 长度 d 指定小数 位数 ,占用空间 4 个字节

理解mysql数据库_第32张图片

  •  在mysql中是不会发生取整规则的,但它会在保存值时会进行四舍五入
  •  当然float类型也有无符号类型,float unsigned

5.2.4 decimal类型 

decimal (m, d) [ unsigned ] : 定点数 m 指定 长度 d 表示小数点的 位数

理解mysql数据库_第33张图片

  •  decimal整数最大位数m65。支持小数最大位数d30
    如果
    d被省略,默认为0.如果m被省略,默认是10
  • decimal和float很像,也有无符号decimal unsigned,
    但是二者的精度是不一样的,float的
    精度是7

5.3 文本 && 二进制类型 

5.3.1 char类型 

char (L): 固定长度字符串, L 是可以 存储的长度 ,单位为字符,最大长度值可以为 255

理解mysql数据库_第34张图片

  •  char(2) 表示可以存放两个字符,可以是字母或汉字,但是不能超过2个, 最多只能是255

5.3.2 varchar类型

varchar (L): 可变长度字符串, L 表示 字符长度 ,最大长度 65535个字节

 理解mysql数据库_第35张图片

  •  varchar长度可以指定为065535之间的值,但是有1 - 3 个字节用于记录数据大小,所以说有效字节数是65532
  • 当我们的表的编码是utf8时,varchar(n)的参数n最大值是65532/3=21844[因为utf中,一个字符占3个字节)
  • 如果编码是gbkvarchar(n)的参数n最大是65532/2=32766(因为gbk中,一个字符占用2字节

5.3.3 charvarchar比较

  • 如果数据确定长度都 一样 ,就使用 定长
  • 如果数据长度 有变化 , 就使用 变长(varchar) ,

 5.4 日期和时间类型

常用的日期有如下三个:
  • date : 日期 'yyyy - mm - dd' 占用三字节
  • datetime  :时间日期格式 'yyyy - mm - dd HH:ii:ss' 表示范围从 1000 9999 ,占用八字节
  • timestamp :时间戳,从 1970 年开始的 yyyy - mm - dd HH:ii:ss 格式和 datetime 完全一致,占用四字节

理解mysql数据库_第36张图片

  • 添加数据时,时间戳自动补齐
  • 更新数据,时间戳会更新

5.5 string类型

 5.5.1 enumset  类型

enum :枚举, 单选 类型;
enum(' 选项 1',' 选项 2',' 选项 3',...);

理解mysql数据库_第37张图片

理解mysql数据库_第38张图片

  • 该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值;
  • 而且出于效率考虑实际存储的是数字,因为这些选项的每个选项值依次对应如下数字:1,2,3,....最多65535(位图结构)

5.5.1 集合查询使用find_ in_ set函数 

find_in_set(sub,str_list)
如果 sub str_list 中,则返回下标;如果不在,返回 0 ; str_list 用逗号分隔的字符串。

理解mysql数据库_第39张图片

6.  表的约束 

6.1 空属性

null(默认的)和not null(不为空)

理解mysql数据库_第40张图片

  • 在设计myclass表的时候,就约束了插入的数据->班级名和教室,不能为空 

6.2 默认值  

理解mysql数据库_第41张图片

理解mysql数据库_第42张图片

  • 这里的default默认值就像是c++的缺省值一样

6.3 列描述 

理解mysql数据库_第43张图片

  •  这里的commet就像是c++中的注释,虽然不影响数据,但这是一种规范

6.4 zerofill

理解mysql数据库_第44张图片理解mysql数据库_第45张图片

  •  int(11): 整数后面的数字代表的不是字节,而是宽度
  • 而这个数字只有在设置zerofill之后才会生效,而zerofill最大的作用就是格式化输出 

 6.5 主键

primary key 用来唯一的约束该字段里面的数据, 不能重复 不能为空 ,一张表中 最多只能有一个主键 ;主键所在的列通常是整数类型

6.5.1 创建主键 && 主键约束 

理解mysql数据库_第46张图片

  • 一般给业务无关的字段设置成主键 

6.5.2 删除主键 && 追加主键

理解mysql数据库_第47张图片

  •  alter table 表名 add primary key(字段列表/名称) // 在没有主键的情况下,追加主键 
  • alter table 表名 drop primary key // 在有主键的情况下, 删除主键

6.5.3 复合主键 

理解mysql数据库_第48张图片

 理解mysql数据库_第49张图片

  • 一般在表创建时就应该设置主键,
  • 如果有多个字段作为主键,可以使用 复合主键

6.6 自增长 

auto_increment :当对应的字段,不给值,会 自动的被系统触发 ,系统会从当前字段中已经有的 最大值 +1 操作,得到一个新的不同的值。通常和主键搭配使用,作为逻辑主键。

理解mysql数据库_第50张图片

理解mysql数据库_第51张图片

  • 这里的auto_increment和c++中的enum枚举很像,
  • auot_incremment在需要查找索引值的时候有用

6.7 唯一键

一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键:唯一键就可以解决表中有多个字段需要唯一性约束的问题

主键更多的是标识唯一性的。而唯一键更多的是保证在业务上不要和别的信息出现重复 

理解mysql数据库_第52张图片

  • 唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较。 

6.8 外键 

外键约束主要 定义在从表 上,主表则必须是有主键约束或 unique约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null

foreign key (字段名) references 主表() 

理解mysql数据库_第53张图片

  •  那么当用户插入不符合业务逻辑的数据的时候mysql不允许你插入

7. 表的增删改查

7.1 creat->增加

 7.1.1 单行数据 + 全列插入

理解mysql数据库_第54张图片

 7.1.2 多行数据 + 指定列插入

理解mysql数据库_第55张图片

 7.1.3 插入否则更新

 insert...on duplicate key update  column = value...

理解mysql数据库_第56张图片

理解mysql数据库_第57张图片

  •  select row_count();// 可以查看最近一次语句的影响行数
  • 0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等
  • 1 row affected: 表中没有冲突数据,数据被插入
  • 2 row affected: 表中有冲突数据,并且数据已经被更新

7.1.4 替换 

 理解mysql数据库_第58张图片

  • 1 row affected: 表中没有冲突数据,数据被插入
  • 2 row affected: 表中有冲突数据,删除后重新插入

7.2 Retrieve->查找 

理解mysql数据库_第59张图片

7.2.1 全列查询

理解mysql数据库_第60张图片

  • select * from 表名

7.2.2 指定列查询 

理解mysql数据库_第61张图片

  •  select 字段名 from 表名

7.2.3 查询字段为表达式

理解mysql数据库_第62张图片

  •  select 表达式 from 表名

7.2.4 为查询结果指定别名 

理解mysql数据库_第63张图片

  •   select 表达式 as 别名 from 表名

7.2.5 结果去重

理解mysql数据库_第64张图片

  •  select distinct 字段 from 表名

7.2.6 比较运算符 && 逻辑运算符

 比较运算符:

运算符 说明
>,>=,<,<= 大于,大于等于,小于,小于等于
= 等于,null 不安全,例如 null = null 的结果是null
<=> 等于,null安全,例如 null <=> null的结果是true(1)
!=,<> 不等于
between a and b 范围匹配,[a,b],如果 a <= value <= b,返回true(1)
in(option)
如果是 option 中的任意一个,返回 TRUE(1)
is null 
是null
is not null 不是null
like 模糊匹配,%表示任意多个(包括0个) 任意字符;_表示任意一个字符
逻辑运算符:
运算符 说明
and 多个条件必须都为true(1),结果才是true(1)
or 任意一个条件为true(1),结果为true(1)
not 条件为true(1),结果为false(0)

理解mysql数据库_第65张图片

理解mysql数据库_第66张图片理解mysql数据库_第67张图片


 理解mysql数据库_第68张图片

  •  模糊匹配的%_一般配合like使用

理解mysql数据库_第69张图片

  •  where 条件中使用表达式,别名不能用在where条件中,

理解mysql数据库_第70张图片

 理解mysql数据库_第71张图片

  •  null 与 null的比较建议使用<=>(是否相等),<>(是否不相等)

7.2.7 结果排序

 理解mysql数据库_第72张图片

理解mysql数据库_第73张图片

  •  asc 升序(从小到大),desc 降序(从大到小),默认为 ASC
  • 且如果有字段为null,则null在排序中是最小的

7.2.8 筛选分页结果

理解mysql数据库_第74张图片

  •  select ... from 表名 [where ...] [order by ...] limit n;
  • select ... from 表名 [where ...] [order by ...] limit s,n;
  • select ... from 表名 [where ...] [order by ...] limit n offset s;

 7.3 Updat->改

理解mysql数据库_第75张图片

  • update table_name set column = expr [,column = expr ...]
    [where ...][order by ...][limit ...]

 7.4 Delete->删 

7.4.1 删除表中数据 

理解mysql数据库_第76张图片

  •  delete from 表名 [where ...] [order by ...] [limit ...]

 7.4.2 截断表  

truncate [table] table_name

理解mysql数据库_第77张图片

理解mysql数据库_第78张图片

  • 只能对整表操作,不能像 delete 一样针对部分数据操作;
  • 实际上 MySQL 不对数据操作,所以比 delete更快,但是truncate在删除数据的时候,并不经过真正的事物,所以无法回滚
  • 重置 auto_increment

7.4.3 插入查询结果  

insert into 表名 [(column) [,colum ...])] select ...

案例:  删除表中的重复记录,重复的数据只能有一份

 理解mysql数据库_第79张图片

理解mysql数据库_第80张图片

  •  创建一张空表 no_duplicate_table结构和 duplicate_table 一样
  • duplicate_table 去重数据插入 no_duplicate_table
  • 通过重命名表,实现原子的去重操作

7.5 聚合函数

聚合统计一定是直接或者间接统计列方向的某些数据

函数
说明
count ([distinct] expr)
返回查询到的数据的 数量
sum ([distinct] expr)
返回查询到的数据的 总和,不是数字没有意义
avg ([distinct] expr)
返回查询到的数据的 平均值,不是数字没有意义
max ([distinct] expr)
返回查询到的数据的 最大值,不是数字没有意义
min ([distinct] expr)
返回查询到的数据的 最小值,不是数字没有意义

理解mysql数据库_第81张图片

7.5.1  count 统计数据数量

理解mysql数据库_第82张图片

 理解mysql数据库_第83张图片

 7.5.2  sum 统计数据总和

理解mysql数据库_第84张图片

  7.5.3  avg 统计数据平均总分

理解mysql数据库_第85张图片

 7.5.4  max 求数据的最大值

理解mysql数据库_第86张图片

  7.5.5  min求数据的最小值

 理解mysql数据库_第87张图片

  7.6 group by子句的使用

mysql可以支持按照指定的列进行对数据做分组,我们可以让特定的sql在特定的组内进行某种操作

理解mysql数据库_第88张图片

理解mysql数据库_第89张图片

 7.6.1  测试一

理解mysql数据库_第90张图片

  7.6.2  测试二

  •  在emp表中: 显示薪水大于 1000 的部门,并从中筛选出平均工资小于 2000的 ( 部门, 平均工资)
  • having经常和group by搭配使用,它是对聚合统计之后的结果进行筛选,作用有点像些where 

注意: having 在查询语句中必须依赖于group by 

7.6.3 小结 

  1. group by是通过分组这样的手段,为未来进行聚合统计提供基本的功能支持(group by一定是配合聚合统计使用的)
  2. group by后面跟的都是分组的字段依据,只有在group by后面出现的字段,未来在聚合统计的时候,在select 中才能出现
  3. where vs having 这两个不是冲突的,是相互补充的,但是二者的先后顺序是不一样的
    having通常: 是在完成整个分组聚合统计之后,才进行筛选的
    where通常: 是在表中数据初步被筛选的时候,才起效果的

 7.7 sql查询中各个关键字的执行先后顺序

  • from > on > join > where > group by > with > having > select > distinct > order by > limit

8. 函数

8.1 日期函数

函数名称 描述
current_date() 当前日期
current_time()

当前时间

current_timestamp() 当前时间戳
date(datetime) 返回datetime参数的日期部分
date_add(date,interval d_value_type) 在date中添加日期或时间
interval后的数据单位可以是: year minute second day
date_sub(date,interval d_value_type) 在date中减去日期或时间
interval后的数据单位可以是: year minute second day
datediff(date1,date2) 两个日期的差,单位是天
now() 当前日期时间

理解mysql数据库_第91张图片

8.1.1 留言表

理解mysql数据库_第92张图片

  •  select * from msg where date_add(sendtime, interval 2 minute) > now();

8.2 字符串函数

函数名称 描述
charset(str) 返回字符串字符集
concat(string2 [,...]) 连接字符串
instr(string,substring) 返回substring在string中出现的位置,没有返回0
ucase(string2) 转换成大写
lcase(string2) 转换成小写
left(string2,length) 从string2中的左边起取length个字符
length(string) string的长度
replace(str,search_str,replace_str) 在str中用replace_str替换search_str
strcmp(string1,string2) 逐字符比较两个字符串的大小
substring(str,position,[,lenth]) 从str的postion开始,取length个字符
ltrim(string) rtrim(string) trim(string) 去除前空格或后空格

理解mysql数据库_第93张图片

8.2.1charset 获取字符集

理解mysql数据库_第94张图片

  •  select charset(ename) from emp;

8.2.2concat 连接字符串

理解mysql数据库_第95张图片

  • select concat(name,'的语文是',Chinese,'分,数学是',math,'分')as '分数' from student;

8.2.3length 显示字符串长度(以字节为单位)

理解mysql数据库_第96张图片

  • select length(name),name from student; 
  • length函数返回字符串长度,以字节为单位。如果是多字节字符则计算多个字节数; 如果是单字节字符则算作一个字节。
  • 字母,数字算作一个字节,中文表示多个字节数 (与字符集编码有关)

8.2.4 replace 字符串替换 

理解mysql数据库_第97张图片

  • select replace(ename,'S','上海') , ename from emp;
  • emp表中所有名字中有S替换'上海'

8.2.5 substring字符串提取

理解mysql数据库_第98张图片

  • select substring(ename,2,2) ,ename from emp;
  • 截取 emp 表中 ename 字段的第二个到第三个字符

8.2.6 lcase 字符串转换(小写)

理解mysql数据库_第99张图片

  • select concat(lcase(substring(ename,1,1)),substring(ename,2)) from emp;

8.3 数学函数 

函数名称 描述
abs(number) 绝对值函数
bin(decimal_number)

十进制转换二进制

hex(decimal_number) 转换成十六进制
conv(number,from_base,to_base) 进制转换
ceiling(number) 向上取整
floor(number) 向下取整
format(number,deinmal_places) 格式化,保留小数位数
hex(decimalNumber) 转换成十六进制
rand() 返回随机浮点数,范围[0.0,1.0)
mod(number,denominator) 取模,求余数

理解mysql数据库_第100张图片

8.4 其他函数 

 8.4.1 user() 查询当前用户

理解mysql数据库_第101张图片

 8.4.2 md5加密

理解mysql数据库_第102张图片

8.4.3 database()显示当前正在使用的数据库

理解mysql数据库_第103张图片

 8.4.4 对用户加密

  • select password('root');

8.4.5ifnull 函数

理解mysql数据库_第104张图片

9. 复合查询(重点)

9.1 解决多表查询的思路:

  1. 先读题,确定都和那些表有关
  2. ''无脑''组合形成一张表 -- 多张表转成一张表
  3. 将多表查询,看做成为一张表的查询

理解mysql数据库_第105张图片

理解mysql数据库_第106张图片

 理解mysql数据库_第107张图片

 9.2 多表查询

显示部门号为 10 的部门名,员工名和工资

理解mysql数据库_第108张图片

  •  select ename,sal,dname from emp,dept where emp.depton = dept.deptno 
    and dept.deptno = 10;

9.3 自连接

自连接是指在同一张表连接查询

显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号--empno

9.3.1 使用的子查询

理解mysql数据库_第109张图片

 9.3.2 使用多表查询(自查询)

理解mysql数据库_第110张图片

  •  from emp leader, emp worker给自己的表起别名
    因为要先做笛卡尔积,所以这里的
    别名会先识别

9.4 子查询

9.4.1 单行子查询

显示SMITH同一部门的员工

理解mysql数据库_第111张图片

9.4.2 多行子查询

in关键字的使用

查询和 10 号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含 10
己的
理解mysql数据库_第112张图片

all关键字的使用

显示工资比部门 30 的所有员工的工资高的员工的姓名、工资和部门号
理解mysql数据库_第113张图片

理解mysql数据库_第114张图片


any关键字的使用

显示工资比部门 30 的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门
的员工)

理解mysql数据库_第115张图片

9.4.3  多列子查询

查询和 SMITH 的部门和岗位完全相同的所有雇员,不含 SMITH 本人
理解mysql数据库_第116张图片
  • 这里加上(),where就能多列匹配了

 9.4.4 终极解决方案 - > from子句中使用子查询

select查询到的结果也是一张表,自然也可以跟其他表连接

显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资 

理解mysql数据库_第117张图片

  •  获取各个部门的平均工资,将其看作临时表,
  • 注意: 这里的新表需要加别名,像自连接一样,以示区分

8.4.5 合并查询

 union && union all 关键字的使用

将工资大于 2500 或职位是 MANAGER 的人找出来
理解mysql数据库_第118张图片

理解mysql数据库_第119张图片

  •  union会取得两个结果集的并集,并自动去掉结果集中的重复
  • 如何使用的是union all的话,则不会去掉重复行

10 .表的内连和外连 

10.1 内连接

显示 SMITH 的名字和部门名称

10.1.1 简略写法

  • select ename, dname from EMP, DEPT where EMP .deptno =DEPT .deptno and
    ename= 'SMITH' ;

10.1.2 标准写法

  • select ename, dname from EMP inner join DEPT on EMP.deptno=DEPT.deptno and ename='SMITH';

 10.2 外连接

理解mysql数据库_第120张图片

 10.2 .1 左外连接

查询所有学生的成绩,如果这个学生没有成绩,也要将学生的个人信息显示出来

理解mysql数据库_第121张图片

  •  以左为主,没有为空补充

 10 .2.1 右外连接

stu 表和 exam 表联合查询,把所有的成绩都显示出来,即使这个成绩没有学生与它对应,也要
显示出来
理解mysql数据库_第122张图片
  • 以右为主,没有为空补充 

11.索引

11.0  创建海量数据

drop database if exists `bit_index`;
create database if not exists `bit_index` default character set utf8;
use `bit_index`;

-- 构建一个8000000条记录的数据
-- 构建的海量表数据需要有差异性,所以使用存储过程来创建, 拷贝下面代码就可以了,暂时不用理解

-- 产生随机字符串
delimiter $$
create function rand_string(n INT)
returns varchar(255)
begin
declare chars_str varchar(100) default
'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
declare return_str varchar(255) default '';
declare i int default 0;
while i < n do
set return_str =concat(return_str,substring(chars_str,floor(1+rand()*52),1));
set i = i + 1;
end while;
return return_str;
end $$
delimiter ;


-- 产生随机数字
delimiter $$
create function rand_num( )
returns int(5)
begin
declare i int default 0;
set i = floor(10+rand()*500);
return i;
end $$
delimiter ;

-- 创建存储过程,向雇员表添加海量数据
delimiter $$
create procedure insert_emp(in start int(10),in max_num int(10))
begin
declare i int default 0;
set autocommit = 0;
repeat
set i = i + 1;
insert into EMP values ((start+i)
,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand_num());
until i = max_num
end repeat;
commit;
end $$
delimiter ;

-- 雇员表
CREATE TABLE `EMP` (
  `empno` int(6) unsigned zerofill NOT NULL COMMENT '雇员编号',
  `ename` varchar(10) DEFAULT NULL COMMENT '雇员姓名',
  `job` varchar(9) DEFAULT NULL COMMENT '雇员职位',
  `mgr` int(4) unsigned zerofill DEFAULT NULL COMMENT '雇员领导编号',
  `hiredate` datetime DEFAULT NULL COMMENT '雇佣时间',
  `sal` decimal(7,2) DEFAULT NULL COMMENT '工资月薪',
  `comm` decimal(7,2) DEFAULT NULL COMMENT '奖金',
  `deptno` int(2) unsigned zerofill DEFAULT NULL COMMENT '部门编号'
);


-- 执行存储过程,添加8000000条记录
call insert_emp(100001, 8000000);

理解mysql数据库_第123张图片

11. 1 常见索引

  • 主键索引(primary key)
  • 唯一索引(unique)
  • 普通索引(index)
  • 全文索引(fulltext)--解决中子文索引问题。

11.2 索引的重要性

理解mysql数据库_第124张图片

  •  在对数据进行增删查改的时候,本质是在内存中进行的
  • 索引的本质就是协助查找

11.3 MySQL 与磁盘交互基本单位 

理解mysql数据库_第125张图片

  • MySQL 作为一款 应用软件 ,可以想象成一种 特殊的文件系统 。它有着更高的 IO 场景,
  • 所以,为了提高基本的IO 效率, MySQL 进行 IO 的基本单位是 16KB ( 后面统一使用 InnoDB 存储引擎讲解 )

11.4 索引的理解

11.4.1 mysql的所有操作都是在内存中的 

理解mysql数据库_第126张图片

  •  mysql本质就是一个进程,一定是在OS之上运行的
  • 对mysql内部的数据等做操作(CURD)的时候,本质其实就是操作文件内容
  • 文件必须先被打开,对文件内容做任何操作,都不是直接在磁盘设备上做操作的
  • 任何磁盘数据,在进程中要进行操作,本质都必须在内存中进行
    msql内部一定要有自己的内存管理,且它启动时会预先申请一批内存空间

11.4.2 理解单个Page 

理解mysql数据库_第127张图片

  •  MySQL 中要管理很多数据表文件,而要管理好这些文件,就需要 先描述,在组织 ,
  • 我们目前可以简单理解一个个独立文件是由一个或者多个Page构成的

11.5 页目录 && 索引所使用的数据结构

页目录 

  •  虽然插入的时候是乱序的,但查的时候却是有序的,或者说page内部的数据是有序
  • 且又因为page内部的数据是有序的,则就引入页内目录

单页情况 

理解mysql数据库_第128张图片

 多页情况

理解mysql数据库_第129张图片

目录页 

理解mysql数据库_第130张图片

  •  不同的page,在mysql中,都是16kb,使用prevnext构成双向链表
  • 所有的数据,全部都在叶子节点
  • 表中的所有带有主键的数据,都是以B+的形式呈现的,
    其中,B+数和数据是耦合在一起的,聚簇索引->InnoDB

小结: 

  • Page分为目录页数据页。目录页只放各个下级Page的最小键值。
  • 查找的时候,自顶向下找,只需要加载部分目录页到内存,即可完成算法的整个查找过程,大大减少了IO次数

主键索引:

  1.  具有主键的表,一表一个B+树
  2. 如果没有主键,mysql 会自动形成隐藏主键
  3. B+中所有的叶子节点,路上节点,都是按需加载到mysql page中的

InnoDB 在建立索引结构来管理数据的时候,其他数据结构为何不行?

  •  链表,线性遍历不行
  • 二叉搜索树,可能退化成为线性结构
  • AVL && 红黑树,深度太深
  • Hash, 范围查找不行

 11.6 聚簇索引 VS 非聚簇索引

理解mysql数据库_第131张图片

  •  myisam存储引擎,数据和主键索引分开的
  • innodb存储引擎,数据和主键索引放在一起的

11.7 索引操作

11.7.1 创建主键索引

  • 方式一:  在创建表的时候,直接在字段名后指定 primary key
    create table user1(id int primary key, name varchar ( 30 ));
  • 方式二:  在创建表的最后,指定某列或某几列为主键索引
    create table user2(id int , name varchar ( 30 ), primary key(id));
  • 方式三: 创建表以后再添加主键
    alter table user3 add primary key(id);

11.7.2 唯一索引的创建

  • 方式一: 在表定义时,在某列后直接指定unique唯一属性。
    create table user4(id int primary key, name varchar(30) unique);
  • 方式二: 创建表时,在表的后面指定某列或某几列为unique
    create table user5(id int primary key, name varchar ( 30 ), unique(name));
  • 方式三: 创建表以后再添加唯一键
    alter table user6 add unique(name);

11.7.3 普通索引的创建

  • 第一种方式-> 在表的定义最后,指定某列为索引
create table user8(id int primary key,
        name varchar ( 20 ),
        email varchar ( 30 ),
        index(name)
);
  •  第二种方式->创建完表以后指定某列为普通索引
    alter table user9 add index(name); 

  • 第三种方式->创建一个索引名为 idx_name 的索引
    create index idx_name on user10(name);

  • 注意: 第三种方法可以给索引起一个新名字

普通索引的特点:

  1. 一个表中可以有 多个普通索引 ,普通索引在实际开发中用的比较多
  2. 如果某列需要创建索引,但是该列有 重复的值 ,那么我们就应该使用 普通索引

11.7.4 全文索引的创建  

当对文章字段或有大量文字的字段进行检索时,会使用到全文索引。 MySQL 提供全文索引机制,但是有要求,要求表的存储引擎必须是MyISAM ,而且默认的全文索引支持英文, 不支持中文 。如果对中文进行全文检索,可以使用sphinx 的中文版 (coreseek);

理解mysql数据库_第132张图片

 直接查询

理解mysql数据库_第133张图片

 理解mysql数据库_第134张图片

  •  可以用explain工具看一下,是否使用到索引

全文索引查询 

理解mysql数据库_第135张图片

 理解mysql数据库_第136张图片

11.7.5 查询索引

  • show keys from 表名
  • show index from 表名;
  • desc 表名;

11.7.6 删除索引  

  • alter table 表名 drop primary key ;
  • alter table 表名 drop index 索引名;
  • drop index 索引名 on 表名

12. 事务管理

一个或多个sql语句的集合,就是事务,事务 = 数据结构 + 算法

12.1 例子

业务需求 : 张三给李四转50

理解mysql数据库_第137张图片

  •  需要保证张三账号少了50,李四账号多了50,
  • 一件或多件事,必须做完(绝对成功,绝对失败),不要出现中间操作这样的概念 --  原子

小结

  1.  上层看来比较简单的需求,可能对应的后端要做很多的工作,
    组合起来才是一个完整的需求解决的方案

  2. 事务本身不是数据库类软件天然有的,
    事务本质工作其实是为了简化程序员的工作模型

12.2  事务的特性

  • 原子性:
    一个事务( transaction )中的所有操作,要么全部完成,要么全部不完成,不会结束在中 间某个环节。
    事务在执行过程中发生
    错误 ,会被 回滚 (Rollback )到事务开始前的状态,就像这个 事务从来没有执行过一样。
  • 一致性:
    事务开始之前 事务结束 以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,
    这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • 隔离性:
    数据库允许
    多个并发事务 同时对其数据进行 读写 修改 的能力,隔离性可以防止多个事务
    并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括
    读未提交
    Read uncommitted)、读提交( read committed)
    可重复读(
    repeatable read)  串行化(Serializable)
  • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失 
  • 这四个属性,可以简称为 ACID (单词的首字母)

 12.3 事务的版本支持

理解mysql数据库_第138张图片

  •  MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务MyISAM 不支持

12.4 事务提交方式  

默认的提交方式是自动提交 

理解mysql数据库_第139张图片

  •  自动提交: set autocommit = 1;
  • 手动提交: set autocommit = 0;

12.5 事务常见操作方式 

理解mysql数据库_第140张图片

 12.5.1 证明事务的开始与回滚

理解mysql数据库_第141张图片

理解mysql数据库_第142张图片

 理解mysql数据库_第143张图片

  •  begin : 开始一个事务
  • savepoint: 创建一个保存点
  • rollback : 回滚到保存点(默认回滚到最开始)

 12.5.2 commit对mysql数据的影响 

  • 终端Acommit,客户端崩溃,MySQL自动会回滚(隔离级别设置为读未提交)
  • 终端A commit了,客户端崩溃,MySQL数据不会在受影响,已经持久化

 12.5.3 begin操作会自动更改提交方式,不会受MySQL是否自动提交影响

理解mysql数据库_第144张图片

 理解mysql数据库_第145张图片

 小结-> 证明原子性 , 一致性

  • 只要输入begin或者start transaction,事务便必须要通过commit提交,才会持久化,与是
    否设置set autocommit 无关
  • 事务可以手动回滚,同时,当操作异常,MySQL会自动回滚
  • 对于 InnoDB 每一条 SQL 语言都默认封装成事务,自动提交。(select有特殊情况,因为
    MySQL 有 MVCC)

 事务操作注意事项

  • 如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback(前提是事务
    还没有提交)
  • 如果一个事务被提交了(commit),则 不可以回退 (rollback)
  • 可以选择回退到哪个保存点
  •  InnoDB 支持事务MyISAM 不支持事务
  • 开始事务可以使 start transaction 或者 begin

12. 6事务隔离级别 

  • 读未提交【 Read Uncommitted
  • 读提交【 Read Committed
  • 可重复读【 Repeatable Read
  • 串行化【 Serializable

12.6.1 查看与设置隔离性 

理解mysql数据库_第146张图片

  • select @@global.tx_isolation;// 查看全局隔离性
  • select   @@session .tx_isolation ;// 查看会话隔离性, 
  • select  @@tx_isolation;// 查看当前隔离性
  • 注意: 会话隔离性只在当前终端有效

​​​​​​​12.6.2 读未提交【Read Uncommitted 

set global transaction isolation level read uncommitted ;
  • 终端A事务在没有commit的时候,终端B也会拿到终端A事务的数据(脏读)

12.6.3 读提交【Read Committed

set global transaction isolation level read committed;
  •  终端A事务在没有commit的时候,终端B得不到终端A事务的数据
  • 注意: 这可能引起在两个终端两个事务中,数据重复的现象(幻读)-> 不可重复读

12.6.4 可重复读【Repeatable Read 

set global transaction isolation level repeatable read ;
  •  可重复度本质其实就是在一个事务内部,不受任何事务操作的影响,每次查到的数据都是一致性

12.6.5 串行化【serializable 

set global transaction isolation level serializable;

  •  对所有操作全部加锁,进行串行化,不会有问题
  • 它在每个读的数据行上面加上共享锁,。但是可能会导致超时和锁竞争效率很低,几乎完全不会被采用

12.6.6 小结 

理解mysql数据库_第147张图片

13. 视图

13.1 基本操作

理解mysql数据库_第148张图片

  • 创建视图create view 视图名 as select语句;
  • 修改了视图,对基表数据有影响
  • 修改了基表,对视图有影响
  • 删除视图: drop view 视图名 

 13.2 视图规则和限制​​​​​​​

  • 与表一样,必须唯一命名(不能出现同名视图或表名)
  • 创建视图数目无限制,但要考虑复杂查询创建为视图之后的性能影响
  • 视图不能添加索引,也不能有关联的触发器或者默认值
  • 视图可以提高安全性,必须具有足够的访问权限
  • order by 可以用在视图中,但是如果从该视图检索数据 select 也含有 order by ,那么该视图 中的 order by 将被覆盖
  • 视图可以和表一起使用

14. 用户管理 

  •  用户管理: 是普通用户只能管理某一个数据库,这样就增强了安全性

14.1 用户 

14.1.1 用户信息

理解mysql数据库_第149张图片

  •  MySQL中的用户,都存储在系统数据库mysqluser表
  • authentication_string :是密码通过md5加密之后形成的

 14.1.2 创建用户

create user '用户名'@'登陆主机/ip' identified by '密码'; 

理解mysql数据库_第150张图片

  • 刷新权限:  flush privileges;

14.1.3 删除用户 

drop user ' 用户名 ' @ ' 主机名 '

 14.1.4 用户登录

mysql -u用户 -h'登录方式' -p 

理解mysql数据库_第151张图片

13.1.5 修改用户密码 

  • 自己改自己密码 set password=password( ' 新的密码 ' );
  • root用户修改指定用户的密码
    set password for ' 用户名 ' @ ' 主机名 ' =password( ' 新的密码 ' );

13.2 数据库的权限

13.2.1 给用户授权

​​​​​​​grant 权限列表 on .对象名 to '用户名'@'登陆位置' [identified by '密码']​​​​​​​

理解mysql数据库_第152张图片

理解mysql数据库_第153张图片 

  • grant select on ...
    grant select , delete , create on ....
    grant all [privileges] on ... -- 表示赋予该用户在该对象上的所有权限
  • *.* : 代表本系统中的所有数据库的所有对象(表,视图,存储过程等)
  • 库.* : 表示某个数据库中的所有数据对象 ( 表,视图,存储过程等 )
  • identified by可选 。 如果用户存在,赋予权限的同时修改密码 , 如果该用户不存在,就是创建用户

注意:如果发现赋权限后,没有生效,执行如下指令: 

  • flush privileges;

14.2.2 回收权限 

revoke 权限列表 on . 对象名 from ' 用户名 ' @ ' 登陆位置 '

15. mysql connect理解mysql数据库_第154张图片

  •  保证mysql服务有效
  • 在官网上下载合适自己平台的mysql connect库,以备后用

mysqlClient.cc

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

string host = "127.0.0.1"; //'localhost'
string user = "whb";
string passwd = "123456";
string db = "104_105_db";
unsigned int port = 8080;

int main()
{
    // cout << "mysql client version: " << mysql_get_client_info() << endl;
    // 0. 初始化mysql对象
    MYSQL *msql = mysql_init(nullptr);
    if (msql == nullptr)
    {
        cerr << "mysql_init error" << endl;
        exit(1);
    }
    // 1. 登陆认证
    if (mysql_real_connect(msql, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        cerr << "mysql_real_connect error" << endl;
        exit(2);
    }
    mysql_set_character_set(msql, "utf8");
    cout << "mysql_real_connect success" << endl;

    // string sql = "insert into emp values (666, '张飞', 789.987)";
    // string delSql = "delete from emp where id=666";
    // string updateSql = "update emp set name='赵云' where id=666";
    // string selectSql = "select * from emp";
    char sql[1024];
    while (true)
    {
        printf("mysql> ");
        fgets(sql, sizeof sql, stdin); //'    select  * from user   ' 

        // 调用成功的时候,返回值是0, 否则就是1
        int n = mysql_query(msql, sql);
        if (strcasestr(sql, "select") && n == 0)
        {
            cout << "result: " << n << endl;
            // 对结果进行解析
            MYSQL_RES *res = mysql_store_result(msql);
            if (res == nullptr)
                exit(0);
            int rows = mysql_num_rows(res);
            int fields = mysql_num_fields(res);

            MYSQL_FIELD *fname = mysql_fetch_fields(res);

            for (int j = 0; j < fields; j++)
                cout << fname[j].name << "\t|\t";
            cout << endl;

            MYSQL_ROW line;
            for (int i = 0; i < rows; i++)
            {
                line = mysql_fetch_row(res); // 按行获取文件的内容,自动会更新行数
                for (int j = 0; j < fields; j++)
                    cout << line[j] << "\t|\t";
                cout << endl;
            }

            printf("%d rows in set\n", rows);
        }
        else
        {
            cout << "execl sql : " << sql << " done" << endl;
        }
    }
    // 关闭mysql对象
    mysql_close(msql);
    return 0;
}

 makefile

mysqlClient:mysqlClient.cc
	g++ -o $@ $^ -std=c++11 -L/lib64/mysql -lmysqlclient
.PHONY:clean
clean:
	rm -rf mysqlClient
  • 初始化接口: MYSQL *mysql_init(MYSQL *mysql) ;
  • 链接数据库接口: MYSQL *mysql_real_connect(MYSQL *mysql, const char *host,​​​​​​​
    const char * user , const char * passwd , const char * db , unsigned int port , const char *unix_socket , unsigned long clientflag )
  • 发送mysql请求: int mysql_query ( MYSQL * mysql , const char * q );  
sql 执行完以后,如果是 查询语句 ,我们当然还要读取数据,如果是 update insert 等语句,那么就看下操 作成功与否即可。我们来看看如何获取查询结果: 如果mysql_query 返回成功,那么我们就通过 mysql_store_result这个函数来读取结果。原型如下:
  • 读取mysql结果: MYSQL_RES * mysql_store_result ( MYSQL * mysql );
  • 结果行数:   my_ulonglong mysql_num_rows ( MYSQL_RES * res );
  • 获取结果列数unsigned int mysql_num_fields(MYSQL_RES *res);
  • 获取列名MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);  
  • 获取结果内容:  MYSQL_ROW mysql_fetch_row ( MYSQL_RES * result );
    它会返回一个
    MYSQL_ROW 变量, MYSQL_ROW 其实就是 char **. 就当成一个二维数组来用吧。

 另外,mysql C api还支持事务等常用操作

  • my_boolSTDCALLmysql_autocommit(MYSQL*mysql,my_boolauto_mode);
  • my_boolSTDCALLmysql_commit(MYSQL*mysql);
  • my_boolSTDCALLmysql_rollback(MYSQL*mysql);

你可能感兴趣的:(linux,centos,运维)