Mysql基础部分

1. 数据库基本介绍

1.1 数据库基本知识

概念

数据库:database(DB),是一种存储数据的仓库

  • 数据库是根据数据结构组织、存储和管理数据
  • 数据库能够长期、高效的管理和存储数据
  • 数据库的目的就是能够存储(写)和提供(读)数据

1.2 数据库分类

概念

数据库分类:根据数据库的架构和数据组织原理进行分类

1、早期根据数据库的组织数据的存储模型分类

  • 层次数据库:基于层次的数据结构(数据分层)
  • 网状数据库:基于网状的数据结构(数据网络)
  • 关系数据库:基于关系模型的数据结构(二维表)

2、现在较多根据实际数据管理模型分类(存储介质)

  • 关系型数据库:基于关系模型的数据结构(二维表)通常存储在磁盘
  • 非关系型数据库:没有具体模型的数据结构(键值对)通常存储在内存

1.3 关系型数据库

概念

关系型数据库:是一种建立在关系模型上的数据库

  • 关系模型
    • 关系数据结构(存储)
    • 关系操作集合(操作)
    • 关系完整性约束(约束)
  • 关系型数据库存储在磁盘中(永久性存储)
  • 关系型数据库系统(DBS)模型有四层结构
    • 数据库管理系统(DBMS):管理系统运行(DataBase Management System)
    • 数据库(DB):数据存储的管理者(小管理,受DBMS管理)
    • 数据表(Table):数据关系管理者
    • 数据字段(Field):依赖于数据表,实际数据存储者
  • 关系型数据库产品
    • 大型:Oracle、DB2
    • 中型:MySQL、SqlServer
    • 小型:Sybase、Access

1.4 非关系型数据库

概念

非关系型数据库:NoSQL(Not only SQL),不仅仅是关系型数据库

  • 所有不是关系型数据库的统称
  • 数据存储模型不是二维表,而是键值对(key->value)
  • 存储的位置通常是内存(效率高)
  • 不能永久性存储(需要定时存到关系型数据库中)
  • 常见的非关系型数据库产品
    • MongoDB
    • Redis
    • Memcached

对比

NoSQL通常是与关系型数据库配合使用的,他们彼此是一种互补关系

  • NoSQL运行在内存,解决效率问题
    • I/O问题
    • 效率问题
  • MySQL运行在磁盘,解决稳定问题
    • 安全问题(永久存储)
    • 稳定

小结

1、NoSQL是对非关系型数据库的一类统称

  • NoSQL是不仅仅只是关系型数据库的意思

2、NoSQL通常运行在内存

  • 读取效率高
  • 并发访问高
  • 稳定性不高(断电即丢失)

3、NoSQL通常是键值对存储数据,访问也比较简单

1.5 SQL基本介绍

概念

SQL:Structured Query Language,结构化查询语言,是一种针对关系型数据库特殊标准化的编程语言

  • SQL是一种编程语言

  • 能够实现用户数据库查询和程序设计

  • SQL根据操作不同,分为几类

    • DQL:Data Query Language,数据查询语言,用于查询和检索数据
    • DML:Data Manipulation Language,数据操作语言,用于数据的写操作(增删改)
    • DDL:Data Definition Language,数据定义语言,用于创建数据结构
    • DCL:Data Control Language,数据控制语言,用于用户权限管理
    • TPL:Transaction Process Language,事务处理语言,辅助DML进行事务操作(因此也归属于DML)

小结

1、SQL虽然是编程语言,但是目前数据库通常只用来进行数据管理(逻辑部分给其他编程语言)

2、SQL虽然是针对关系型数据库的通用语言,但是不同的产品操作指令不完全通用

1.6 MySQL基本介绍

概念

MySQL:是瑞典AB公司下的一款关系型数据库

  • MySQL当前属于甲骨文公司(AB->Sun->Oracle)
  • MySQL开源免费(部分存储引擎)
  • MySQL是一种C/S结构软件,因此需要MySQL的客户端来访问服务端(数据管理)
    • mysqld.exe:服务端
    • mysql.exe:客户端
  • MySQL使用SQL指令对数据库进行操作

访问原理

MySQL客户端
寻找服务端
host寻找
寻找服务端
Port寻找
验证身份
username判定
password判定
服务端

小结

1、MySQL是一款流行的关系型数据库

2、MySQL是一款C/S结构的软件,需要客户端访问服务端

3、MySQL是基于SQL指令进行管理操作

1.7 MySQL访问

概念

MySQL访问:就是客户端连接上服务端,然后实现数据操作的过程

  • 客户端访问服务端

    • 利用Windows控制台访问(MySQL客户端)
    • 利用数据库管理工具(Navicat,idea,sqlyog)
  • 客户端需要连接认证

    • -h:主机地址(本机localhost可以省略)
    • -P:端口号(默认3306可以省略)
    • -u:用户名
    • -p:用户密码
  • 客户端连接上服务端就表示占用了一个资源,可以进行对应权限的操作

    • MySQL数据库连接资源有限:单个服务器最多16384个
    • 连接资源不够了其他访问就需要排队等待
    • 用完尽可能释放资源
  • 客户端退出服务端(命令窗口输入指令)

    • \q
    • quit
    • exit
    • Ctrl + c

注意 ,要配置环境变量

步骤

1、打开客户端(CMD控制台):mysql.exe

2、输入服务器信息(连接)和用户信息(验证)

3、执行SQL操作

4、断开连接

示例

mysql -hlocalhost -P3306 -uroot -proot

Mysql基础部分_第1张图片

我们也可以使用简化版本的访问(省略 -h 和 -P,因为在本机)

mysql -uroot -proot

Mysql基础部分_第2张图片

我们推荐使用控制台密文密码连接认证(安全)

mysql -uroot -p
root

Mysql基础部分_第3张图片

小结

1、MySQL需要通过客户端来进行服务端访问

  • 自带客户端mysql.exe:Windows下借助CMD
  • 数据库管理工具:Navicat,图形化管理
  • 支持MySQL扩展的编程语言:PHP、Java等

2、数据库操作需要进行连接认证

  • 主机地址:-h,默认localhost可省略
  • 端口:-P(大写字母),默认3306可省略
  • 用户名:-u
  • 密码:-p(小写字母)

3、数据库连接资源有限,用完即关闭

1.8 总结

1、数据库的作用要清楚:高效的存储和管理数据,为编程语言提供数据支撑

2、当前市面上数据库的分类主要为两类

  • 关系型数据库:注重结构和数据存储的持久性
  • 非关系型数据库:注重数据读取的效率

3、关系型数据库是几乎所有网站都会使用到的,必须掌握其概念

4、所有关系型数据库都是基于SQL进行数据的操作,MySQL数据库也是(不同的数据库产品对应的SQL指令可能有细微差别)

5、MySQL是一种C/S结构的软件,所以访问者必须通过客户端进行访问

  • 客户端与服务端通常不会在一台电脑上
  • 客户端访问服务端需要寻址、授权(-h -P -u -p)
  • MySQL服务端的连接数是有限的,时刻注意用完就销毁(减少资源无效占用)

2. Mysql基本操作

2.1 sql语法规则

概念

SQL语法规则:SQL是一种结构化编程语言

  • 基础SQL指令通常是以行为单位
  • SQL指令需要语句结束符,默认是英文分号:;、\g、\G
    • \G:主要用于查询数据,立体展示结果
  • SQL指令类似自然语言
  • 编写的SQL中如果用到了关键字或者保留字,需要使用反引号``来包裹,让系统忽略

例如

select * from user;

2.2 SQL库操作

目标:掌握数据库相关SQL指令

  • 创建数据库
  • 显示数据库
  • 使用数据库
  • 修改数据库
  • 删除数据库

2.2.1 创建数据库

概念

创建数据库:根据项目需求创建一个存储数据的仓库

  • 使用create database 数据库名字创建
    • 数据库层面可以指定字符集:charset / character set
    • 数据库层面可以指定校对集:collate
  • 创建数据库会在磁盘指定存放处产生一个文件夹
  • 创建语法
create database 数据库名字 [数据库选项];

示例

1、创建一个指定名字的数据库

create database db_1;

2、创建一个指定字符集的数据库

create database db_2 charset utf8MB4;

3、创建一个指定校对集的数据库(必须和字符集一起指定)

create database db_3 charset utf8MB4 collate utf8mb4_general_ci;

小结

1、数据库的创建是存储数据的基础,数据库的创建通常是一次性的

2、创建数据库的语法包含几个部分

  • 关键字: create database
  • 数据库名字: 自定义名字
    • 数字、字母和下划线组成
    • 不区分大小写
    • 数字不能开头
    • 使用下划线法创建复杂数据库名字
  • 数据库选项:非必须的规定
    • 字符集:charset /character set 字符集。非必须,默认继承DBMS(也就是安装的时候指定的编码)
    • 校对集:collate 校对集。非必须,依赖字符集

3、创建好的数据库可以在数据存储指定地点(安装时指定)看到

  • 一个数据库对应一个文件夹
  • 每个数据库下有个对应的文件,里面有字符集和校对集信息(Mysql7以前

4 . 我们一般就使用默认的数据库创建语句 create database db_1;

2.2.2 显示数据库

概念

显示数据库:通过客户端指令来查看已有数据库

  • 数据库的查看是根据用户权限限定的
  • 数据库的查看分为两种查看方式:
    • 查看全部数据库
    • 查看数据库创建指令

示例

1、显示所有数据库

show databases;

2、显示数据库创建指令

show create database db_1;

小结

1、查看数据库分为两种方式

  • 查看全部:show databases;
  • 查看具体创建指令:show create database 数据库名字;

2、查看数据库的目的和应用

  • 开发人员确认数据库是否存在
  • 数据库管理员维护

2.2.3 使用数据库

概念

使用数据库:指在进行具体SQL指令之前,让系统知道操作针对的是哪个数据库

  • 数据库的操作通常是针对数据表或者数据
  • 通过使用数据库可以让后续指令默认针对具体数据库环境
  • 使用数据库语法:use 数据库名字;

示例

use db_1;

小结

1、使用数据库的指令是:use 数据库名字;

2、使用数据库的目标

  • 让系统知道后续SQL指令都是针对当前选择的数据库
  • 简化后续SQL指令的复杂度(如果不指定数据库,那么所有的SQL操作都必须强制指定数据库名字)

2.2.4 修改数据库

概念

修改数据库:修改数据库的相关库选项

  • 数据库名字不可修改(老版本可以)
  • 修改数据库名的顺序
    • 先新增一个数据库
    • 把老数据库的数据通过一个sql文件导出
    • 新数据库执行导出的sql文件
    • 删除老数据库
  • 数据库修改分为两个部分(库选项)
    • 字符集
    • 校对集
  • 数据库修改指令(与创建指令差不多)
alter database 数据库名字 库选项 # 库选项可接多个 ,用空格隔开

示例

1、修改数据库字符集

alter database db_2 charset gbk;

2、修改数据库校对集(如果校对集修改必须同时改变字符集)

alter database db_3 charset gbk collate gbk_chinese_ci;

小结

1、数据库的修改只能修改库选项,不能修改名字

2、字符集的修改指令使用alter,其他跟创建指令一致

3、数据库修改通常有两部分

  • 字符集修改
  • 校对集修改(校对集必须对应字符集)

4、一般我们都不会使用数据库修改(一般要改也是删除后新增)

2.2.5 删除数据库

概念

删除数据库:将当前已有数据库删除

  • 删除数据库会删除数据库内所有的表和数据
  • 删除数据库操作要慎重(删前备份)
  • 删除数据库后,对应的存储文件夹就会消失
  • 删除语法
drop database 数据库名字;

示例

drop database db_1;

小结

1、删除数据库使用指令:drop database 数据库名字

2、数据库的删除不可逆

  • 删除会清空当前数据库内的所有数据表(表里数据一并删除)
  • 删除数据库会将对应的文件夹从磁盘抹掉
  • 数据库删除要谨慎(一般不建议删除)

2.3 SQL表(字段)操作

2.3.1 创建数据表

概念

创建数据表:根据业务需求,确定数据表的字段信息,然后创建表结构

  • 表与字段不分家,相辅相成

  • 表的创建需要指定存储的数据库

    • 明确指定数据库:
    create table db_1.t_1(
    	name VARCHAR(32)
    )charset=utf8; # db_1 是数据库名 ,t_1 是表名
    
    • 先使用数据库:use 数据库名字
    use db_1;
    create table t_1(
    	name VARCHAR(32)
    )charset=utf8; # db_1 是数据库名 ,t_1 是表名
    
  • 字段至少需要指定名字、类型

  • 数据库表不限定字段数量

    • 每个字段间使用逗号,分隔
    • 最后一个字段不需要逗号
  • 表可以指定表选项(都有默认值)

    • 存储引擎:engine [=] 具体存储引擎
    • 字符集:[default] charset 具体字符集(继承数据库)
      • 我当前默认是gbk ,所有加上比较好
    • 校对集:collate(继承数据库)
  • 表创建语法

create table [数据库名.]表名(
	字段名 字段类型,
	...
    字段名 字段类型
)表选项1 表选项2;

注意点 : mysql 中使用UTF-8 字符集只能写成 utf8 ,其他的写法都会报错

示例

1、创建简单数据表(指定数据库创建数据表)

create table db_2.t_1(
	name varchar(50)
);

2、创建数据表——多字段

# 使用数据库(进入数据库环境)
use db_2;
create table t_2(
    name varchar(50),
    age int,
    gender varchar(10)
);

3、创建数据表——表选项

create table t_3(
	name varchar(50)
)engine Innodb charset utf8;

也可以

CREATE TABLE t_3(
	NAME VARCHAR(50)
)ENGINE=INNODB CHARSET=utf8; # default 选择性加在 charset 前面

4, 赋值表

语法

create table 被复制表名 like [数据库名字.]复制表名 # 同一个数据库下就不用加数据库名字

示例 :

CREATE TABLE tt_1 LIKE t_1;

小结

1、创建数据库表是为了存储具体数据

2、数据表的创建与字段是同时存在的

3、数据表的创建需要指定数据库

  • 在表名字前指定数据库:数据库名.表名
  • 进入数据库环境(常用)

4、一张数据表用来存一组相关数据

5、扩展:存储引擎是指数据存储和管理的方式,MySQL中提供了多种存储引擎,一般使用默认存储引擎

  • InnoDB
    • 默认存储引擎
    • 支持事务处理和外键
    • 数据统一管理
  • MyIsam
    • 不支持事务和外键
    • 数据、表结构、索引独立管理
    • MySQL5.6以后不再维护

6、扩展:如果想创建一个与已有表一样的数据表,MySQL提供了一种便捷的复制模式

  • create table 表名 like 数据库名字.表名

2.3.2 显示数据表

目的:了解如何查看数据表结构

概念

显示数据表:客户端通过指令显示已有的数据表

  • 数据表的显示跟用户权限有关
  • 显示数据表有两种方式
    • 显示所有数据表
    • 显示具体数据表的创建指令

示例

1、显示所有数据表——当前数据库下

show tables;

2、显示所有数据表——指定数据库

SHOW TABLES FROM db_2;

3、显示部分关联数据表——匹配

# 搜索当前数据库中是否有 名字 可以匹配 %like 的表
show tables like '%like';	# _表示匹配一个字符(固定位置),%表示匹配N个字符

4、显示数据表的创建指令

show create table t_1; # 看到的结果未必一定是真实创建的指令(系统会加工)

小结

1、显示数据表有两种形式

  • 显示所有数据表:show tables [from 指定数据库];
    • 显示部分:show tables like ‘pattern’; 匹配模式:_匹配单个字符,%匹配不限量字符
  • 显示数据表创建指令:show create table 表名;

2、显示数据表通常是为了验证数据表是否存在或者验证数据表的创建指令是否正确

3、在显示数据的时候可以使用不同的语句结束符**(只在命令行中有效)**

  • \g:与普通分号无区别
  • \G:纵向显示列数据

2.3.3 查看数据表

目标:了解查看数据表的概念和掌握数据表查看的语法

概念

查看数据表:指查看数据表中的具体结构

  • 通常是查看字段信息
  • 详细的显示字段的各项信息
  • 查看语法有三种(效果一样)
desc 表名;
describe 表名;
show columns from 表名;

示例

desc t_1;

小结

1、数据表的查看是为了查看表中具体字段的信息

2、查看数据表的指令有多个,效果都一样

  • desc 表名;(常用)
  • describe 表名;
  • show columns from 表名;

3、查看表结构的原因通常是在开发过程中为了更清晰的了解数据的存储形式和要求

2.3.4 更改数据表

概念

更改数据表:修改表名字和表选项

  • 修改表名
rename table 表名 to 新表名
  • 修改表选项
alter table 表名 表选项1 表选项2 ;

示例

1、修改表名

rename table t_1 to t1;

注意:如果有时候想要跨库修改的话,需要使用数据库名.表名

RENAME TABLE db_1.t_1 TO t1;

2、修改表选项

alter table t1 charset utf8;

小结

1、更改数据表分为两个部分

  • 更改表名:rename table 原表名 to 新表名;
  • 更改表选项:alter table 表名 表选项

2、通常我们较少使用更改数据表,数据表应该在创建时就定义好

2.3.5 删除数据表

删除数据表 : 删除该表

语法 :

drop table 数据表;

示例

1, 删除一个数据表

drop table t_1;

2.3.6 更改字段

目标:了解字段更改的类型和基本语法的使用

概念

更改字段:指针对表创建好后,里面字段的增删改

  • 字段操作包含字段名字、类型和属性的操作
  • 字段操作分为四类
    • 新增字段:add [column]
    • 更改字段名:change
    • 修改类型:modify
    • 删除字段:drop
  • 字段操作还有位置处理
  • 字段操作通常是在表已经存在数据后进行

新增字段

概念

新增字段:在表创建好后往里面增加其他字段

  • 字段的新增必须同时存在字段类型

  • 新增语法

# column 可写可不写
alter table 表名 add [column] 字段名 字段类型 [字段属性] [字段位置]

示例

1、给已经存在的t_3表增加一个字段age

alter table t_3 add age int;

2、给已经存在的t_3表增加一个字段nickname

alter table t_3 add column nickname varchar(10);

3, 给已经存在的t_3表增加一个字段id ,放在name后面(字段位置在后面有讲)

ALTER TABLE t_3 ADD id INT AFTER name

小结

1、新增字段就是给已有表追加一个字段(较少)

2、字段新增必须指定字段类型

3、字段新增语法为:alter table 表名 add [column] 字段名 字段类型;

4、字段的追加默认是在所有字段之后

字段位置

目标:了解字段位置的概念,掌握字段位置的使用

概念

字段位置:指字段放到某个指定字段之后

  • 字段位置分为两种
    • 第一个字段:first
    • 某个字段后:after 已经存在字段名
  • 字段位置适用于追加字段、修改字段、更改字段名
  • 字段位置语法(放在更改字段操作的后面 ,是一个可选操作)
# 字段操作 如 add change modify drop 等等
alter table 表名 字段操作 字段位置;

示例

1、为t_3表增加一个id字段,放到最前面

alter table t_3 add id int first;

2、在t_3表name字段后增加一个身份证字段card

alter table t_3 add card varchar(18) after name;

小结

1、字段位置是配合字段操作的(新增、修改)

2、字段位置分两种

  • 最前面(第一个字段):first
  • 字段后面:after 已存在字段名

更改字段名

目标:了解更改字段名的基本语法

概念

更改字段名:指对已经存在的字段名进行修改

  • 字段名的修改也必须跟上字段类型
  • 字段名修改语法
alter table 表名 change 原字段名 新字段名 字段类型 [字段属性] [字段位置]

示例

1, 修改字段名card为sfz

ALTER TABLE t_3 CHANGE id sfz VARCHAR(18);

2, 把sfz字段提到第一个(一般不使用这个关键字进行字段名位置修改)

ALTER TABLE t_3 CHANGE sfz sfz VARCHAR(18) FIRST;

小结

1、字段名更改通常只是修改字段名字,但是也必须跟随类型

2、字段名修改语法:alter table 表名 change 原字段名 新字段名 字段类型

3、字段名修改change其实也可以修改字段类型、属性和位置,但是通常不使用,一般使用 modify 操作

修改字段

目标:了解字段修改的概念和基本语法,掌握字段修改的实现

概念

修改字段:指修改字段的相关信息

  • 修改 字段类型, 字段属性字段位置
  • 修改字段语法
alter table 表名 modify 字段名 字段类型 [字段属性] [位置];

示例

1, 修改身份证的类型为char(18)并且位置放到id后面

alter table t_3 modify sfz char(18) after id;

2, 修改身份证的类型为varchar(30)

ALTER TABLE t_3 MODIFY sfz VARCHAR(30);

小结

1、修改字段包含多个操作

  • 字段类型修改
  • 字段属性修改
  • 字段位置修改

2、修改字段语法:alter table 表名 modify 字段名 字段类型 [字段属性] [位置];

删除字段

目标:了解字段删除语法

概念

删除字段:即将某个不要的字段从表中剔除

  • 删除字段会将数据也删除(不可逆)
  • 删除字段语法
alter table 表名 drop 字段名;

示例

1, 删除年龄字段

alter table t_3 drop age;

小结

1、字段删除在删除字段名的同时会删除字段对应的数据,而且不可逆

2、字段删除语法:alter table 表名 drop 字段名

2.4 SQL数据操作

目标:掌握mysql中数据的增删改查的基本操作

  • 新增数据
  • 查看数据
  • 更新数据
  • 删除数据

2.4.1 新增数据

目标:了解数据的新增指令和逻辑,实现数据的入库操作

概念

新增数据:将数据插入到数据表永久存储

  • 新增数据是根据表的字段顺序和数据类型要求将数据存放到数据表中

  • 数据表中的数据以行(row)为存储单位,实际存储属于字段(field)存储数据

  • 我们尽量使用单引号来表示填入字段的字符串

  • 数据插入分两种方式

    • 全字段插入:
    insert into 表名 values(字段列表顺序对应的所有值);
    
    • 部分字段插入
    insert into 表名 (字段列表) values(字段列表对应的值顺序列表);
    

示例

已知 表t_3 的结构如下

Mysql基础部分_第4张图片

1、给t_3表插入一条完整数据

# 填写字段值的时候,我们尽量使用单引号表示字符串 ,因为在别的数据库里面使用双引号非法(双引号用作圈数据库名,数据表名)
INSERT INTO t_3 VALUES('440111200011111101','Jim',18,'Green');

2、根据字段插入数据

insert into t_3(age,sfz,name) values(18,'441000200011111211','Tom');

小结

1、数据插入是利用insert指令将数据永久存储到数据表中

2、数据存储以行为单位,字段为最小实际存储单位

3、数据插入分为两种方式插入数据

  • 全字段插入
    • insert into 表名 values(值列表)
    • 值列表必须与字段列表顺序一致
    • 值列表的每个数据类型必须与字段类型一致
  • 部分字段插入
    • insert into 表名 (字段列表) values(值列表)
    • 字段列表可以顺序随意
    • 值列表必须与指定的字段列表顺序一致
    • 值列表元素的类型必须与字段列表的类型一致

2.4.2 查看数据

概念

查看数据:将表中已经存在的数据按照指定的要求显示出来

  • 查到的数据显示出来是一张二维表
  • 数据显示包含字段名和数据本身
  • 数据查看分两种方式
    • 查看全部字段:使用*代替所有字段
    • 查看部分字段:明确字段名,使用逗号分隔
  • 查看数据很多时候也是根据条件查询部分数据
  • 查看语法
select *|字段列表 from 表名;

示例

1、查看t_3表中所有数据

select * from t_3;

2、查看t_3表中的name和身份证信息

select name,sfz from t_3;

3、查看t_3表中年龄值为18的信息

select * from t_3 where age = 18;

小结

1、数据查看是数据库中最常用的操作(99%)

2、数据查看分两种情况

  • 查看全部:select * (*叫做通配符)
  • 查看部分:select 字段列表(建议,这样可以减少数据库的压力)

3、实际使用时通常会带where条件进行数据筛选

2.4.3 更新数据

目标:了解更新数据的语法,掌握数据更新操作

概念

更新数据:即更新某个已有字段的值

  • 更新数据通常是根据条件更新某些数据,而不是全部记录都更新
  • 更新数据语法
update 表名 set 字段 = 新值[,字段 = 新值] [where条件筛选];

示例

1、更新所有记录的身份证信息

update t_3 set sfz = '440100200010100001';

2、更新某个记录的多个字段数据

update t_3 set name = 'Lily',sfz = '440100200010100002' where age = 18;

小结

1、更新数据的针对记录的字段数据进行更新

2、更新通常是限定条件更新(一般不会更新全部)

2.4.4 删除数据

目标:了解删除语法,掌握删除操作实现

概念

删除数据:将数据从已有数据表中清除(针对的是记录record)

  • 删除数据是一种不可逆操作
  • 数据删除通常都是有条件删除
  • 数据删除语法
delete from 表名 [where条件];

示例

删除t_3表中age为18的数据

delete from t_3 where age = 18;

小结

1、数据删除是不可逆的操作

2、数据删除通常都匹配条件部分删除

3. 字符集和校对集

3.1 字符集概念

目标:了解字符集概念,掌握字符集存储和读取的实现原理

概念

字符集:charset或者character set,是各种文字和符号在计算机中的总称

  • 字符集根据不同国家的符号不同,有不同的字符集
  • 不同的字符集占用的存储空间不一样,存储的底层也不一样
  • 不同字符集之间可以进行转换
  • 常见字符集
    • ASCII:美国信息交换标准码,一般英文符号,一个字节存储
    • latin1:拉丁文字符集,一个字节存储,ISO-8859-1的别名 ,能够向下兼容ASCII
    • GB2312:信息交换用汉字编码字符集 ,是中国1981年的一套国标规范,2个字节存储
    • GBK:汉字内码扩展规范(1995年),两个字节表示表示(汉字很多超过5000个)
    • Unicode:万国码(统一码),使用统一的编码方式来解决传统的局限,1994年出现
    • UTF-8:8-bit Unicode Transformation Format(万国码) ,针对Unicode的可变长度字符编码,采用1-6个字节编码Unicode字符(目前通用编码规则)。建议使用UTF-8字符集进行数据存储(MySQL8中建议使用utf8mb4)

原理流程图

1、数据存储

ASCII
GBK
ASCII 存储中文
输入符号
A
计算机存储
字符集选择
转码
01000001
转码
0000000001000001
转码
乱码
存储

2、数据读取

ASCII
GBK
UTF-8
数据读取
字符集选择
读1个字节
01000001
读2个字节
0000000001000001
读3个字节
错误读取
解析
乱码
解析
A
输出

小结

1、字符集是一套符号的总称

2、不同国家地区的符号有区别,所以有自己的字符集

3、常见的字符集目前是三个

  • ASCII:美国信息交换标准码
  • GBK:汉字内码扩展规范(国标),兼容ASCII
  • UTF-8:8字节万国码,兼容GBK和ASCII

4、目前基本都统一使用UTF-8开发和数据存储

5、字符集是指定字符的存储和读取的规范

  • 指定的字符集存储需要使用对应的字符集读取
  • 错误的字符集存储或者读取都会产生乱码

3.2 MySQL字符集

概念

MySQL字符集:MySQL内部对于数据实际存储的字符集(服务器端)

  • MySQL内部对象可以在各个层级设置字符集
  • MySQL内部对象存在字符集继承:字段 继承继承数据库 继承 DBMS
  • MySQL内部内嵌支持几乎所有主流字符集
  • 数据存储的最终字符集由字段控制
  • 客户端与服务器进行交互时,需要明确告知服务器客户端自己的字符集(数据格式)

示例

查看MySQL支持的所有字符集

show charset;

原理图

1、数据库内部对象字符集原理

继承DBMS字符集
继承数据库字符集
继承数据表字符集
服务器数据管理
DBMS系统
安装配置字符集
数据库
设定字符集
数据表
设定字符集
数据字段
设定字符集

1.1、服务端存储的数据最终字符集由字段确定

1.2、字段通常不会设置字符集,继承表的字符集(统一性,真正一般都与数据库一致)

1.3、数据存储的字符集与客户端的字符集没有直接关系,是由表(字段)决定

2、客户端存储数据原理

提前告知服务端客户端数据字符集
如不告知-服务器使用默认设置
客户端录入数据
数据自带字符集
发送服务端
服务端接收数据
执行存储操作
转码为目标字符集
存储

3、客户端读取数据原理

提前告知服务端客户端数据字符集
如不告知-服务器使用默认设置
客户端录入获取指令
发送服务端
服务器接收请求
执行获取指令
按照数据存储本身字符集获取
转成客户端字符集数据
返回客户端
客户端解析
只能按照自己的字符集解析

小结

1、MySQL服务端数据存储的字符集依赖各个对象设置

  • DBMS:设置最广,一旦设置所有对象都可以依赖,但是优先级最低
  • DB:针对数据库内的所有表,优先级高于DBMS,可以继承DBMS(现在一般在数据库层设置)
  • Table:针对当前表的设置,优先级高于DB,可以继承DB
  • Field:针对当前字段设置,优先级高于Table,可以继承Table,优先级最高

2、通常字符集的设置都是围绕数据表(现在都在数据库层),不会到具体字段

3、建议使用UTF8字符集存储数据(MySQL8以后建议使用UTF8MB4)

4、MySQL服务端支持各种字符集,并且能够进行各种字符集转换

5、客户端存储数据到服务端原理

  1. 客户端告知服务端客户端的字符集

  2. 服务端按照客户端指定的字符集接收数据(如果没有指定,使用默认,可能出现乱码)

  3. 服务端按照实际存储表对应的字符集进行转换

  4. 服务端存储数据

6、客户端读取服务端数据原理

  1. 客户端告知服务端客户端的字符集

  2. 服务端按照客户指定的指令从数据库读取原始字符集数据

  3. 服务端按照客户端的需求将数据进行字符转换

  4. 服务端发送目标数据给客户端

  5. 客户端按照自己的字符集进行解析

3.3 乱码问题解决

目标:了解乱码发生的原因,实现乱码问题的解决方案

概念

乱码:指数据不能按照正确的字符集进行存储或者解析

  • 乱码原因1:数据在存储的时候已经变成乱码
    • 客户端字符集与服务端解析字符集不一致
    • 读取时想转成其他字符集均会错误
  • 乱码原因2:数据存储时正确,但是读取时解析成错误字符集
    • 客户端能解析的字符集与服务器提供的字符集不一致
  • 乱码解决方案:不论存储还是读取,都提前告知服务器当前客户端的字符集
set names 客户端字符集;

示例

1、MySQL客户端(CMD打开),命令行客户端字符集是固定的GBK,客户端是什么编码就设置什么编码

set names gbk;

流程图

客户端连接认证服务端
设定字符集
告知服务端当前客户端的字符集
其他操作
内部字符集转换不用管
结束

小结

1、乱码的本质原因就是客户端与服务端的字符集不一致导致

  • 客户端存储数据的时候服务端没有正确理解(服务端按照默认的存储,存储的就是乱码)
  • 客户端读取的时候没有正确告知服务端(服务端按照默认的提供)

2、解决乱码问题的方案:保证服务端正确理解客户端的字符集

  • set names 客户端字符集
  • 在任何数据操作之前(尤其是写数据,包括结构)

3.4 字符集设置原理

目标:了解set names 字符集的本质原理

概念

字符集设置原理:服务器端正确保障对客户端的数据识别

  • MySQL服务端提供了变量来记录客户端的字符集
  • MySQL对应的存储字符集的变量可以修改
  • set names 字符集就是对变量的修改,总共有三个
    • character_set_client:客户端告诉服务器传入的数据以什么编码解析
    • character_set_results:服务器对客户端需要的数据以什么编码解析给客户端
    • character_set_connection:连接使用的字符集,内部数据操作(可以不用管)

示例

1、查看系统内部存储这些记录字符集的信息

show variables like 'character_set%';	#%表示通配符,匹配后续所有不确定的数据

Mysql基础部分_第5张图片

1)character_set_server:mysql server默认字符集。

2)character_set_database:数据库默认字符集。

3)character_set_client:MySQL server假定客户端发送的查询使用的字符集。

4)character_set_connection:MySQL Server接收客户端发布的查询等请求后,将其转换为character_set_connection变量指定的字符集(也就是客户端的编码)。

5)character_set_results:mysql server把结果集和错误信息转换为character_set_results指定的字符集,并发送给客户端。

6)character_set_system:系统元数据(字段名等)字符集

我们可以设置mysql 服务器的默认字符集编码 ,找到mysql安装文件下的 my.ini或my-default.ini文件,打开 ,设置

default-character-set=utf8

character-set-server=utf8

Mysql基础部分_第6张图片

2、修改客户端字符集变量,保证数据正常存进服务端 (客户端是什么编码 ,就设置什么编码)

set character_set_client = uft8;

3、修改客户端解析字符集变量,保证数据正常被客户端查看

set character_set_results = uft8;

4、使用set names 字符集批量修改,保证客户端被服务端正确理解,同时客户端也能正确解析

set names uft8;

注意 : 如果是命令行操作 ,其客户端默认编码为 gbk ,那我们需要默认设置 set names gbk;

小结

1、MySQL字符集控制是在服务端内部通过变量连接(针对每个独立的客户端)

2、set names字符集是一种快捷方式,本质有三个变量被修改

  • character_set_client:服务端接收客户端数据
  • character_set_connection:服务端内部连接使用
  • character_set_results:服务端提供数据给客户端

3、通常我们都是使用set names字符集来进行统一设置,而且是在建立连接之后操作数据之前就设置

3.5 字符集总结(重要 ***)

1、字符集是所有编程语言里都必须面对的首要问题,必须在一开始就选择好字符集(去到企业后先问清楚)

  • 业务针对的符号
  • 业务针对的范围

2、乱码是编程中最基础要解决的问题,一旦数据产生了乱码,通常是不可逆操作

3、解决乱码问题其实本质就是统一字符集问题

  • 客户端字符集:character_set_client
  • 连接层字符集:character_set_connection
  • 结果集字符集:character_set_results
  • 简单统一方式:set names 客户端字符集
  • 存储字符集:不用考虑,因为数据库有强大的字符集转换能力,只要在开始设置好,保证后续数据不会超出字符集即可

流程总结 :

  1. mysql 分为客户端和服务器端, 两边分别有不同的编码
  2. 客户端在向服务器端发送请求的时候, 数据将以客户端的编码解码为二进制数据 ,然后发送给服务器端
  3. 服务器端接收到数据后 ,首先看一下 character_set_client,以该变量指定的编码格式把客户端传入的二进制数据转码服务器端默认的编码格式,如果用户没有设置就用character_set_client的默认值编码(我的是utf8)
  4. 如果用户的请求是存储数据 ,那么服务器端将把传入的数据再转码成 其数据库表的编码存储
  5. 若用户请求数据 ,首先服务器把数据从表中取出 ,将其数据转换成服务器默认编码 ,再把数据 以character_set_results的编码格式解码成二进制数据,传输给客户端
  6. 客户端把服务器端传回来的数据以自身默认编码 编码二进制数据,再把可视化的数据显示,至此结束

3.6 校对集概念

概念

校对集:collate/collation,即数据比较时对应的规则

  • 校对集依赖字符集
  • 校对集的校对方式分为三种
    • 大小写不敏感:_ci,case insensitive(不区分大小写)
    • 大小写敏感:_cs,case sensitive(区分大小写)
    • 二进制比较:_bin,binary(区分大小写)
  • 校对集是在进行数据比较的时候触发

示例

1、_ci,大小写不敏感

A 与 a 是相同的,不存在谁大谁小(系统会转换成一种)

2、_cs,大小写敏感

A 与 a 有大小关系,所以不同(存储数值)

3、_bin,二进制比较

A的二进制是01000001
a的二进制是01100001
二进制按位比较,所以不同

小结

1、校对集是数据比较的规则

  • 校对集依赖字符集存在

  • 每个字符集有多种校对规则

2、校对规则一共有三种

  • _ci:大小写不敏感,不区分大小写
  • _cs:大小写敏感,区分大小写
  • _bin:二进制比较(区分大小写)

3.7 校对集设置

目标:了解MySQL中校对集的设计方式以及规则查看

概念

校对集设置:在创建数据表的时候创建校对规则

  • 校对规则可以在MySQL四层对象设计
    • DBMS:系统配置
    • DB:数据库指定(库选项)
    • Table:表指定(表选项)
    • Field:字段指定(字段选项,一般不用)
  • 校对集从Field到DBMS继承;优先级Field最高
  • 每个校对集都有字符集对应的默认规则
  • 校对集设置语法
collate 校对集规则;

注意 : 校对集依赖于字符集 ,字符集决定校对集 ,两者必须是一个系列才可以 ,决不能说字符集是gbk ,校对集是utf8_bin

示例

1、查看MySQL支持的所有校对集

show collation;

2、在数据库层设计校对集(常见)

create database db_4 charset utf8mb4 collate utf8mb4_bin;
# 或者
create database db_4 charset utf8 collate utf8_bin;

3、在数据表层设计校对集

create table t_4(
	id int,
    name varchar(10)
)charset utf8mb4 collate utf8mb4_bin;

4、在字段层设计校对集(一般不常用)

create table t_5(
	id int,
    name varchar(10) collate utf8mb4_bin
)charset utf8mb4;

小结

1、MySQL中四层对象都可以设置校对集

  • DBMS:配置文件 (可以在mysql配置文件中设置)
  • DB:创建数据库时限定(一般在创建数据库的时候就设置)
  • Table:创建表示限定
  • Field:创建字段时限定

2、校对集从Field到DBMS实现继承

3、校对集依赖字符集,且每个字符集都有默认的校对集(一般情况不需要设置)

3.8 校对集应用

目标:了解不同校对集的实际校对原理,掌握校对规则的应用场景

概念

校对集应用:触发校对规则的使用

  • 校对集的应用通常是通过数据比较触发:order by 字段
  • 数据表中数据一旦产生,校对集的修改就无效

示例

1、创建校对规则数据表并插入数据

# 创建默认校对规则表(不区分大小写)
create table t_4(
	name varchar(1)
)charset utf8mb4;
insert into t_4 values('B');
insert into t_4 values('A');
insert into t_4 values('b');
insert into t_4 values('a');

# 创建二进制校对规则(区分大小写)
create table t_5(
	name varchar(1)
)charset utf8mb4 collate utf8mb4_bin;
insert into t_5 values('B');
insert into t_5 values('A');
insert into t_5 values('b');
insert into t_5 values('a');

2、触发校对:排序 order by

select * from t_4 order by name; # 升序
select * from t_5 order by name;

3、数据已经存在的表重新修改校对规则无效

alter table t_5 collate utf8mb4_general_ci; # 无效操作 ,无法修改

小结

1、校对集的应用不是主动触发,而是通过数据比较自动触发

2、校对集对应的数据一旦产生,那么就不可以修改数据表的校对规则

3、校对集通常使用字符集默认校对集,如果需要进行额外的比较应用(通常是区分大小写),那么需要在建表的时候设定好目标校对规则

3.9 校对集总结

1、校对集是数据比较的标准

2、校对集的校对规则都是依赖字符集存在的,不外乎三种规则

  • _ci:不区分大小写
  • _cs:区分大小写
  • _bin:二进制比较(区分大小写,且比 cs敏感)

3、校对集的触发是自动的,只要数据在进行比较的时候就会自动触发设定的校对规则

  • 校对集的维护要在数据产生之前
  • 数据产生之后校对集的修改将无效

4、在进行数据表设计之前,要提前了解数据后续可能产生的比较形态,选择好合适的校对规则(一般都默认不区分大小写)

4. 字段类型

4.1 字段类型作用

概念

字段类型:MySQL中用来规定实际存储的数据格式

  • 字段类型在定义表结构时设定
  • 设定好字段类型后,插入数据时必须与字段类型对应,否则数据错误
  • MySQL有四大数据类型
    • 整数类型
    • 小数类型
    • 字符串类型
    • 时间日期类型

示例

规定类型的字段只能插入相应的数据格式

Mysql基础部分_第7张图片

# 正确数据类型插入
insert into t_6 values(3,'444111222211110101','Lily','Lee');

# 错误数据类型插入
insert into t_6 values('hello','444444222211110102','Lucy','Lu');

小结

1、字段类型的作用就是强制规范录入的数据格式

  • 规范数据的格式
  • 保证数据的有效性

2、MySQL中有四种数据类型规范

  • 整数类型:只能存储整数
  • 小数类型:可以存储有效数值
  • 字符串类型:存储字符串数据
  • 时间日类类型:存储时间日期格式数据

4.2 整数类型

目标:了解MySQL中的整数机制,掌握常用的整数类型解决整数存储问题

概念

整数类型:有效的整数数据

  • MySQL中为了数据空间的有效使用,设定了五种整数类型
    • 迷你整型:tinyint,使用1个字节存储整数,最多存储256个整数(-128~127)
    • 短整型:smallint,使用2个字节存储整数
    • 中整型:mediumint,使用3个字节存储整数
    • 标准整型:int,使用4个字节存储整数
    • 大整型:bigint,使用8个字节存储
  • 数值型存储在MySQL中分为有符号(有负数)和无符号(纯正数
  • 可以用在创建表的时候用 unsigned 来修饰整数类型 ,这样只会表示正数 ,且可表示的值也会翻倍

步骤

1、确定数据的格式是存储整数

2、预估整数的范围,选择合适的整数类型

3、确定整数是否需要符号(负数区间)

示例

1、设计一个表记录个人信息:年龄、头发数量

# 年龄:没有负数,正常年龄也不超过200岁,迷你整型无符号即可
# 头发数量:没有负数,大概在几百万根,所以标准整型无符号即可
create table t_7(
	age tinyint unsigned, # unsigned修饰整数,表示无符号(从0开始)
    haircount int unsigned
)charset utf8 COLLATE utf8_bin;

2、设计一个表记录4S店的汽车销量信息:库存数量、销量、采购量

# 4S店经常是先卖后进货,所以库存可能为负数,一个店铺的库存数通常不会太多,那么小整型即可
# 销量通常全国一个月也就几万台,所以基本上小整型就够了,但是为了保证后续可能存在的爆发,那么中整型也是绝对够了的,而且不会是负数
# 采购通常是正向采购,所以不会出现负数,而采购数量与销量持平就好

create table t_8(
    stock smallint,
    sales mediumint unsigned,
    purchase mediumint unsigned
)charset=utf8 COLLATE=utf8_bin;

小结

1、整型是用来存储整数数据的

2、整数数据也需要根据业务大小来选择合适的存储方式

  • 迷你整型:存储数量不超过1个字节表示范围
  • 小整型:存储数量不超过2个字节表示范围
  • 中整型:存储数量不超过3个字节表示范围
  • 整型:存储数量不超过4个字节表示范围
  • 大整型:存储数量不超过8个字节表示范围

3、数值型类型在MySQL中默认是有符号的,即有正负

  • 无符号需要使用unsigned修饰整型,即纯正数

4、一般开发中不会太计较一个或者两个字节(不愿意算),所以tinyint和int居多,其他较少

4.3 显示宽度

目标:了解显示宽度的实现,掌握在具体需求下使用显示宽度

概念

显示宽度:int(L),整数在数据库中显示的符号(数字+符号)个数

  • 显示宽度一般是类型能表示的最大值对应的数字个数(通过desc查看表字段显示)
  • 显示宽度包含符号(如果允许为负数,-负号会增加一个宽度)
  • 显示宽度可以主动控制:创建字段时加括号确定
  • 显示宽度不会影响类型能表示的最大数值
  • 可以通过zerofill让不够宽度的数值补充到对应宽度:在字段类型后使用zerofill
id         int(11)      YES             (NULL) 

这里的 id 的宽度就是 11位, 即查询出来显示11 位

示例

1、有符号和无符号对应的宽度不一样

create table t_9(
	a tinyint, # tinyint(4)
    b tinyint unsigned #  tinyint(3) unsigned
)charset utf8;

2、可以主动控制显示宽度

增加一个字符设置其显示宽度

alter table t_9 add c tinyint(2) unsigned;

修改一个字符设置其显示宽度

alter table t_9 modify a tinyint(2) unsigned;

3、显示宽度不影响数据的大小

insert into t_9 values(1,1,1); #小于显示宽度
insert into t_9 values(100,100,100); #大于显示宽度

4、可以通过zerofill让小于显示宽度的数值前置补充0到显示宽度

alter table t_9 add d tinyint(2) zerofill; # 0填充只能针对正数
insert into t_9 values(1,1,1,1);

或者

ALTER TABLE t_9 MODIFY a TINYINT(3) UNSIGNED ZEROFILL;  # 0填充只能针对正数
INSERT INTO t_9 VALUES(1,2,1,1);
SELECT * FROM t_9;

小结

1、显示宽度是显示整型能表示的最多符号数量

2、显示宽度能主动设置,但是绝对不会改变类型本身能表示的数据大小

3、可以通过zerofill来强制让不够宽度的数据补充前置0来达到显示宽度

  • zerofill默认要求整型为无符号
  • zerofill通常用来制作一些规范宽度的数据

4.4 小数类型(浮点型)

概念

浮点数:float/double,存储不是特别精确的数值数据

  • 浮点数又称之为精度数据,分为两种(精度是整数部分位数加小数部分位数)
    • 单精度:float,使用4个字节存储,精度范围为6-7位有效数字 (一共九位 ,看整数部分和小数部分怎么分配)
    • 双精度:double,使用8个字节存储,精度范围为14-15位有效数字
  • 浮点数超过精度范围会自动进行四舍五入
  • 精度可以指定整数和小数部分
    • 默认不指定,整数部分不超过最大值,小数部分保留2位
    • 可以指定:float/double(总长度,小数部分长度)
  • 可以使用科学计数法插入数据:AEB,A * 10 ^ B

步骤

1、确定当前设计的字段的数据为不精确型数据(或者小数)

2、确定数据的大小或者精度的要求范围(精度是整数部分位数加小数部分位数)

  • 6-7位有效数字使用float
  • 14-15位有效数字使用double

3、确定精度的分布:整数部分和小数部分

示例

1、记录宇宙中恒星、行星的数量

# 数量属于不确定量级,所以精确的数据是无意义的,只能是个大概(绝大部分时候float就可以)
create table t_10(
	h_star float unsigned,
    x_star float(20,0) unsigned
)charset utf8;

insert into t_10 values(1234567890,1.2E10);

select * from t_10; # 1234570000 12000000000
# 说明默认的float精度只有 6位 ,超过6位直接四舍五入

2、记录商品的价格

# 商品名字字符串
# 商品价格一般都允许带小数
create table t_11(
	goods_name varchar(20),
    goods_price float
)charset utf8;
insert into t_11 values('Nokia3310',199.999); # 成功 ,且没有发生四舍五入
insert into t_11 values('Nokia6100',1999.9999); # 失败 ,四舍五入成2000

小结

1、浮点数是用来记录一些不需要特别精确的数值或者小数数值的

  • float:单精度,6-7位有效数字
  • double:双精度,14-15位有效数字

2、浮点数能够表示很大的数值

3、浮点数可以指定整数部分和小数部分的有效数值区间

  • float/double
    • 默认是整数不超过最大范围即可
    • 小数部分保留2位有效数字
  • float/double(有效数位,小数部分有效位)
    • 整数部分为有效数位 - 小数部分
    • 数值如果超过整数部分就不让插入

4、因为浮点数会自动四舍五入,所以不要使用浮点数来存储对精度要求较高的数值

4.5 小数类型(定点型)

概念

定点型:decimal,能够保证精度的小数

  • 不固定存储空间存储
  • 每9个数字使用4个字节存储
  • 定点型可以指定整数部分长度和小数部分长度
    • 默认不指定,10位有效整数,0位小数
    • 可以指定:decimal(有效数位,小数部分数位)
    • 有效数位不超过65个
  • 数据规范
    • 整数部分超出报错
    • 小数部分超出四舍五入

步骤

1、确定小数是否需要保证精度

2、确定有效数位长度

示例

记录个人资产情况:资产和负债

# 资产和负债应该都是精确的,小数部分可以到分
CREATE TABLE t_12(
	money DECIMAL(10,2),
	beg DECIMAL(10,2) # 八位整数 ,两位小数
)CHARSET=utf8 COLLATE=utf8_bin;

insert into t_12 values(1111111111.12,1111111.99);
insert into t_12 values(1111111111.12,99999999.999); # 错误:进位导致正数部分超过指定范围

小结

1、定点数是用来存储精确的小数的

2、定点数可以指定长度

  • decimal:默认
    • 整数部分为10位
    • 小数部分为0
  • decimal(有效位数,小数位数)
    • 整数部分为:有效位数 - 小数位数
    • 有效数位不超过65个

3、定点数的存储模式不是固定长度,所以数据越大占用的存储空间越长

4.6 字符串类型(定长型)

概念

定长型:char(长度),指定固定长度的存储空间存储字符串

  • 定长是指定存储长度
  • 定长的长度是字符而不是字节
    • 长度的最大值是255
    • 实际存储空间:长度字符数 * 字符集对应字节数
  • 定长里存储的数据不能超过指定长度,但是可以小于指定长度
  • 字符串数据使用单引号或者双引号包裹

步骤

1、确定数据类型为字符串(或不能用整数存储的超长数字符号)

2、确定数据长度基本一致(定长占用固定空间)

3、确定具体长度

示例

记录个人信息:身份证信息和手机号码

# 身份证为固定长度18位(数字)
# 手机号码是11位固定长度(数字)
create table t_13(
	id_number char(18),
    phone_number char(11)
)charset utf8;
insert into t_13 values('440111999912120304','13512345678');

小结

1、定长是固定存储空间

  • 实际存储空间:L字符 * 字符集对应字节数

2、定长对应的是字符长度,而不是字节长度

3、字符串数据需要使用引号包裹具体数据(推荐使用单引号)

4、定长的访问效率较高,但是空间利用率不高

  • 固定长度的数据使用定长

  • 定长最大数据长度指定不超过255字符

4.7 字符串类型(变长型)

概念

变长型:varchar(最大长度),根据实际存储的数据变化存储空间

  • 变长型的存储空间是由实际存储数据决定的
  • 变长型的L也是指字符而不是字节
    • L指定的是最大存储的数据长度
    • L最大值理论是65535
    • 变长需要额外产生1-2个字节,用来记录实际数据的长度
      • 数据长度小于256个,多1个字节
      • 数据长度大于256个,多2个字节
    • 实际存储空间:实际字符数 * 字符集对应字节数 + 记录长度
  • 变长数据不能超过定义的最大长度

步骤

1、确定数据类型为字符串

2、确定数据是不规则的数据

3、确定最大长度

示例

记录个人信息:用户名、密码、姓名、身份证

# 用户名不确定长度,最长不超过50个字符
# 密码不确定长度,最潮超过15个字符
# 姓名不确定长度,最长不超过10个字符
# 身份证固定长度,18个字符
create table t_14(
	`username` varchar(50),
    `password` varchar(15),
    `name` varchar(10),
    `id_number` char(18)
)charset utf8;

insert into t_14 values('username','password','name','444111999912121111');

小结

1、变长varchar是根据数据的长度实际计算存储空间

2、变长需要规定数据的最大长度,理论长度为65535个字符

3、变长字符串能够更好的利用存储空间

4、变长字符串需要有额外1-2个字节存储数据长度

  • 不超过256个字符:1个字节
  • 超过256个字符:2个字节

5、变长字符串在读取时需要进行长度计算,所以效率没有定长字符串高

4.8 字符串类型(文本字符串)

目标:了解文本字符串的作用,掌握文本字符串的使用规则

概念

文本字符串:text/blob,专门用来存储较长的文本

  • 文本字符串通常在超过255个字符时使用
  • 文本字符串包含两大类
    • text:普通字符
      • tinytext:迷你文本,不超过2 ^ 8 -1个字符
      • text:普通文本,不超过 2 ^ 16 - 1个字符
      • mediumtext:中型文本,不超过 2 ^ 24 - 1 个字符
      • longtext:长文本,不超过 2 ^ 32 - 1 个字符(4G)
    • blob:二进制字符 (可以用来储存文件 ,图片 等等)
      • tinyblob
      • blob
      • mediumblob
      • longblob
  • 文本字符串会自动根据文本长度选择适合的具体类型
  • 一般在文本超过255个字符时,都会使用text(blob现在极少使用)
  • 读取效率 : char > varchar > text

步骤

1、确定类型为文本类型

2、确定数据长度可能超过255个字符

3、使用text

示例

记录新闻信息:标题、作者和内容

# 标题一般不会超过50个字符,varchar
# 作者一般不会超过10个字符:varchar
# 内容通常都很长,使用text
CREATE TABLE t_15(
	author VARCHAR(32),
	title VARCHAR(50),
	content TEXT
)CHARSET utf8;

insert into t_15 values('佚名','给联合国的一封信','给联合国的一封信...');

小结

1、文本类型是专门用来存储长文本的

  • text:普通文本字符
  • blob:二进制文本字符

2、一般文本长度超过255的(较长)都使用text

3、text/blob根据数据存储长度有很多种,但是一般使用text/blob,因为文本会根据数据长度自适应选择

4.9 字符串类型(枚举)

概念

枚举:一种映射存储方式,以较小的空间存储较多的数据

  • 枚举是在定义时确定可能出现的可能
  • 枚举在定义后数据只能出现定义时其中的一种
  • 枚举类似一种单选框
  • 枚举使用1-2个字节存储,最多可以设计65535个选项 (2^16)
  • 枚举实际存储是使用数值,映射对应的元素数据,从1开始
  • 枚举语法:enum(元素1,元素2,…元素N)

步骤

1、确定数据是固定的几种数据之一

2、使用枚举穷举相应的元素

3、数据存储只能选择穷举中的元素之一

示例

1、记录人群类型:小朋友、少年、青年、中年、老年,每个人实际只属于一种类别

# 要保证未来数据只能出现在某种可能中,所以要先列出来,可以使用enum
    create table t_16(
        type enum('小朋友','少年','青年','中年','老年')
    )charset utf8;

insert into t_16 values('少年');
# 等价于
insert into t_16 values(2);

# 错误实例
insert into t_16 values('仙人');	# 不存在的数据不能插入

2、enum是建立映射关系,然后实际存储是数字,数值是按照元素顺序从1开始

# 可以使用字段 + 0来判定数据具体的效果(字符串转数值为0)
select type,type + 0 from t_16;
insert into t_16 values(5); # 等价于 insert into t_16 values('老年');

流程原理

1、枚举定义原理

枚举数据 映射值
数据1 1
数据2 2
数据N N(小于65535)

2、数据存储(读取反过来)

指令开始
插入数据
读取映射关系
元素==数值
数值==数值
数值存储到字段
结束

小结

1、枚举是在定义时确定可能出现的元素,而后数据只能出现规定的元素之一的数据类型

2、枚举的存储是一种映射关系,对元素进行顺序编号,实际存储的是编号

3、使用枚举的作用

  • 规范数据模型
  • 优化存储空间

4.10 字符串类型(集合)

目标:了解集合概念和存储原理,掌握集合的应用

概念

集合:set,一种映射存储方式,以较小的空间存储较多的数据

  • 集合是在定义时确定可能出现的元素进行穷举
  • 集合在定义后数据只能出现定义时其中的元素(可以是多个)
  • 集合类似一种多选框
  • 集合使用1-8个字节存储数据,最多可以设计64个元素
  • 集合实际存储是使用数值(二进制位),映射对应的元素数据,每个元素对应一个比特位
  • 集合语法:set(元素1,元素2,…元素N)

步骤

1、确定数据是固定的几种数据组合

2、使用集合穷举相应的元素

3、数据存储只能选择穷举中的元素组合(多个使用逗号分隔)

示例

1、记录个人的球类爱好,有篮球、足球、羽毛球、网球、乒乓球、排球、台球、冰球

# 爱好可以是多种,并非固定的,但是只能从规定的类型中选择
create table t_17(
	hobby set('足球','篮球','羽毛球','网球','乒乓球','排球','台球','冰球')
)charset utf8;

insert into t_17 values('足球');
insert into t_17 values('冰球,台球,篮球');

2、集合建立的也是映射关系,映射方式是每个元素对应一个字节的比特位,从左边开始第一个对应字节从右边开始的第一位

# 可以通过字段 + 0的方式查看存储的具体数值
select hobby,hobby + 0 from t_17;

# 可以通过插入数值来组合元素,但是需要确定对应的十进制转换成二进制有对应的元素对应
insert into t_17 values(8); # 二进制表示 00001000 第四位为 1 ,所有是网球 

/*
 8:00001000
 
 1:00000001
 
 冰球、台球、篮球
 11000010 => 1 + 2 ^ 1 + 1 * 2 ^ 6 + 1 * 2 ^ 7 = 2 + 64 + 128 = 194
*/

image-20211024174253059

流程原理

1、集合定义原理

把数据转换为二进制 , 哪一位为 1 则说明集合中有这一位对应的元素

集合数据 映射位
数据1 00000001
数据2 00000010
数据8 10000000

2、数据存储(读取反过来)

指令开始
插入数据
读取映射关系
元素选中==位值为1
元素未选中==位值为0
转化成十进制存储
结束

小结

1、集合是在定义时确定可能出现的元素,而后数据只能出现规定的元素数据类型

2、集合的存储是一种映射关系,每个元素对应字节中的一个位,实际存储的是编号

  • 数据存在:对应位为1
  • 数据不存在:对应位为0

3、使用集合的作用

  • 规范数据模型
  • 优化存储空间

4.11 时间日期类型 (年)

概念

:year,MySQL中用来存储年份的类型

  • MySQL中使用1个字节存储年份
  • year能够表示的范围是1901-2155年(256年)
    • year的特殊值是:0000
  • year允许用户使用两种方式设计(效果一样)
    • year
    • year(4)
  • 一般不使用

步骤

1、确定存储的数据是年份

2、确定年份的区间在1901-2155之间

3、使用year类型

示例

1、记录个人的出生年份

create table t_18(
	y1 year,
    y2 year(4)
)charset utf8;
insert into t_18 values(1901,2155);

2、Year类型允许使用2位数来插入,系统会自动匹配对应的年份

  • 69以前:系统加上2000
  • 69以后:系统加上1900
insert into t_18 values(69,70); # 查询出来的值 : 2069 1970 

3、Year类型的特殊值是0000,可以使用00或者0000插入

insert into t_18 values(00,0000);

小结

1、year类型是MySQL用来存储年份信息的

2、year使用1个字节,所以只能表示256个年号,表示区间为1901-2155年

3、year数据可以用两种方式插入

  • 直接插入4位年,1901-2155之间都可以
  • 插入2位年,0-99之间,系统会自动以69和70为界限

4、因为year字段表示的范围有限,所以通常会使用字符串来存储(牺牲空间换安全)

4.12 时间日期类型(时间戳)

概念

时间戳:timestamp,基于格林威治时间的时间记录

  • MySQL中时间戳表现形式不是秒数,而是年月日时分秒格式
    • YYYY-MM-DD HH:II::SS
    • YYYYMMDDHHIISS
  • timestamp使用4个字节存储
  • timestamp的特点是所对应的记录不论哪个字段被更新,该字段都会更新到当前时间

步骤

1、确定类型需要使用年月日时分秒格式

2、确定当前字段需要记录数据的最近更新时间

3、使用timestamp时间戳

示例

1、记录商品库存的最后更新时间

create table t_19(
	goods_name varchar(10),
    goods_inventory int unsigned,
    change_time timestamp
)charset utf8;

insert into t_19 values('Nokia3110',100,'1971-01-01 00:00:00');
insert into t_19 values('Nokia7100',100,'19710101000000');

2、timestamp会在自己所在的记录任何位置被修改时自动更新时间

update t_19 set goods_inventory = 90;

更新成功

image-20211024174559834

注意:在MySQL8以后,取消了timestamp的默认自动更新,如果需要使用,需要额外使用属性: on update current_timestamp

alter table t_19 add c_time timestamp on update current_timestamp;

update t_19 set goods_inventory = 80;

小结

1、timestamp是用以时间戳的形式来保存时间的

  • 时间戳算法是从格林威治时间开始
  • MySQL中存储的是年月日时分秒格式

2、timestamp使用4个字节存储数据

  • 表示范围是1971年1月1日0时0分0秒-2155年12月31日23是59分59秒
  • timestamp可以使用0000-00-00 00:00:00

3、timestamp一般用来记录数据变化的,其他时候通常用整型保存真正的时间戳

  • timestamp在MySQL8中需要主动使用on update current_timestamp才会自动更新

4.13 时间日期类型 (日期)

概念

日期:date,用来记录年月日信息

  • 使用3个字节存储数据
  • 存储日期的格式为:YYYY-MM-DD
  • 存储的范围是:1001-01-01~9999-12-31

步骤

1、确定存储的数据格式为日期类格式

2、确定数据格式为YYYY-MM-DD

3、使用date类型

示例

记录个人生日

create table t_20(
	name varchar(10),
    birth date
)charset utf8;

insert into t_20 values('Jim','2000-12-12');
insert into t_20 values('Tom','10011212');

小结

1、日期date是用来存储YYYY-MM-DD格式的日期的

2、date用3个字节存储,存储区间是1000 - 9999年,跨度很大

3、date可以在需要存储日期的地方放心使用

4.14 时间日期类型(日期时间)

概念

日期时间:datetime,用来综合存储日期和时间

  • 使用8个字节存储数据
  • 存储格式为:YYYY-MM-DD HH:II:SS
  • 存储区间为:1000-01-01 00:00:00 到9999-12-31 23:59:59

步骤

1、确定要存储的时间格式包含日期

2、确定存储格式为:YYYY-MM-DD HH:II:SS

3、使用datetime

示例

记录个人具体的出生时间

create table t_21(
	name varchar(10),
    birth datetime
)charset utf8;

insert into t_21 values('Jim','2000-12-12 12:12:12');
insert into t_21 values('Tom','10011212182323');

小结

1、日期时间是综合存储日期和时间两部分的

2、日期时间datetime使用8个字节存储

3、datetime的存储区间为:1000-01-01 00:00:00 到 9999-12-12 23:59:59

4、实际开发中因为编程语言(PHP)的强大,实际存储的时候通常不会使用这种类型

  • 占用较大存储空间
  • 处理不够灵活(固定格式)
  • 使用int unsigned存储时间戳然后利用PHPdate进行格式处理

4.15 时间日期类型(时间)

目标:了解时间的存储格式和实际效果

概念

时间:time,用来记录时间或者时间段

  • 使用3个字节存储数据
  • 数据范围是 -838:59:59 - 838:59:59
  • 数据插入的格式分为两种
    • 时间格式:[H]HH:II:SS([]表示可以没有)
    • 时间段格式:D HH:II:SS(D表示天)

步骤

1、确定要存储的类型是时间格式

2、确定格式类型为time能表示的格式

3、使用time存储

示例

记录用户登录的具体时间

# 具体登录时间可以使用时间戳(包含年月日时分秒信息)
# 也可以时间datetime格式,或者date+time双字段格式(具体后面学习范式时会知道该怎么用)
create table t_22(
	login_time1 int unsigned,
    login_time2 datetime,
    login_date date,
    login_time3 time
)charset utf8;

insert into t_22 values(12345678,'2000-12-12 12:12:12','2000-12-12','12:12:12');
insert into t_22 values(1234567,'2000-12-12 12:12:12','2000-12-12','3 12:12:12');

小结

1、时间格式time主要用来记录时间点或者时间段

2、time类型通常被用来做时间段计算:如多少天后的什么时间点(可以理解为过期检查)

4.16 总结

1、字段类型是用来规范数据的格式的

2、MySQL中有很多类型用来规范数据格式

  • 整数类型(常用)
    • 常用类型:tinyint、int
  • 小数类型(常用)
    • 常用类型:decimal、float
  • 字符串类型(常用)
    • 常用类型:char、varchar、text
  • 时间日期类型(不常用:通常使用真正时间戳存储数据,然后PHP进行灵活解读)

3、实际开发的时候,一定要仔细了解需求,根据需求判定好具体选用那种数据类型

  • 最原始的维护能够具有最大的通用性(选中类型)
  • 最小的消耗能够解决全部的问题(巧妙利用存储空间)

4, 开发的时候一般使用整形来代表事件(事件戳)

4.17 java和mysql数据类型对应

类型名称 显示长度 数据库类型 JAVA类型 JDBC类型索引(int)
varchar L+N VARCHAR java.lang.String 12
char N CHAR java.lang.String 1
blob L+N BLOB java.lang.byte[] -4
text 65535 VARCHAR java.lang.String -1
interger 4 INTEGER UNSIGNED java.lang.Long 4
tinyint 3 TINYINT UNSIGNED java.lang.Integer -6
smallint 5 SMALLINT UNSIGNED java.lang.Integer 5
mediumint 8 MEDIUMINT UNSIGNED java.lang.Integer 4
big 1 BIT java.lang.Boolean -7
bigint 20 BIGINT UNSIGNED java.math.BigInteger -5
float 4+8 FLOAT java.lang.Float 7
double 22 DOUBLE java.lang.Double 8
decimal 11 DECIMAL java.math.BigDecimal 3
boolean 1 同TINYINT
id 11 PK (INTEGER UNSIGNED) java.lang.Long 4
date 10 DATE java.sql.Date 91
time 8 TIME java.sql.Time 92
datetime 19 DATETIME java.sql.Timestamp 93
timestrap 19 TIMESTAMP java.sql.Timestamp 93
year 4 YEAR

5. 字段属性

5.1 属性作用

概念

属性:建立在字段类型之后,对字段除类型之外的其他约束

  • 属性是在定义表字段的时候针对每个字段进行属性设定
  • 设定好的属性可以通过查看表字段desc进行查看
  • 数据在进行增删改(写)操作时需要在满足字段的要求同时还要满足属性的要求

示例

查看表属性:desc 表名

desc t_11;

# Field:字段名字
# Type:数据类型
# Null:是否允许为空(属性)
# Key:索引类型(属性)
# Default:默认值(属性)
# Extra:额外属性

image-20211024204710078

小结

1、属性是用来MySQL用来增加字段规范和约束的

2、数据的写操作必须严格满足字段类型和属性要求

3、用好属性能够提升数据的有效性,方便未来进行数据操作和数据分析(数据真实性和有效性)

5.2 NULL属性

概念

NULL:数据是否允许为空

  • 默认情况下数据是允许为空的
  • 不为空设计:Not Null
  • 数据为空一般不具备运算和分析价值,所以通常数据都需要设定为Not Null(不区分大小写)

步骤

1、数据类型确定

2、数据是否为空确定

  • 允许为空:不用考虑Null属性(默认为Null)
  • 不允许为空:Not Null

示例

1、用户信息表:用户名、密码、姓名、年龄、注册时间

create table t_23(
	username varchar(50) not null,
    password char(32) not null,
    name varchar(20),
    age tinyint unsigned,
    reg_time int unsigned not null
)charset utf8;

2、如果字段不能为空(Not Null),那么数据就必须满足条件:插入时不能为空的字段就需要主动提供值

insert into t_23 values('username','password','Jim',20,123456789);

# 错误操作:reg_time不能为空,而默认为空,所以系统报错
insert into t_23 (username,password) values('username','password');

小结

1、Null/Not Null属性是用来限定数据是否为Null值的

  • 默认是允许为Null值
  • 不允许为空:Not Null

2、一般有效的数据都必须设定为Not Null来保证数据的有效性

5.3 Default属性

概念

默认值:default,在设计表字段的时候给定默认数据,在后续字段操作(数据新增)的时候系统没有检测到字段有数据的时候自动使用的值

  • 默认值在字段设计的时候使用(默认值需要满足数据类型规范)
  • 默认值通常设计的是字段容易出现的数据
    • 一般字段的默认值默认是Null
  • 默认值触发
    • 在系统进行数据插入时自动检测触发
    • 主动使用default关键字触发默认值

步骤

1、确定字段的数据类型

2、确定字段可能出现的数据会是某个经常出现的值

3、设定默认值

4、触发默认值

  • 自动触发:数据插入时不给字段赋值
  • 手动触发:数据插入时主动使用default关键字

示例

1、用户开户:银行卡账号、身份证号码、姓名、账户余额

create table t_24(
	account varchar(19) not null,
    id_card char(18) not null,
    name varchar(20) not null,
    money decimal(16,2) default 0.00 not null
)charset utf8;

2、默认值触发

# 默认触发
insert into t_24 (account,id_card,name) values('6226000000000001','44011120001212000x','Lily');

# 主动触发
insert into t_24 values('6226000000000002','440111200012120011','Tom',default);

3, 修改字段的默认值

alter table t_24 modify money decimal(16,2) default 10.0 first;

小结

1、每个字段都有默认值

  • 默认情况下基本为Null
  • 主动设置后,默认值改变

2、默认值是在设置表字段的时候添加 ,也可以 修改字段的时候添加

3、默认值触发

  • 自动触发
  • 关键字手动触发

4、默认值通常用于一些不重要的字段,但是会出现常用值(或者初始值一样)

5.4 主键

概念

主键:primary key,用来保证整张表中对应的字段永远不会出现重复数据

  • 主键在一张表中只能有一个
  • 主键的另外一个特性是能够提升主键字段作为查询条件的效率(索引)
  • 主键不能为空:Not Null(默认)
  • 逻辑主键:数据没有具体业务意义,纯粹是一种数值数据
    • 逻辑主键通常是整数:int
    • 逻辑主键目的是方便检索和数据安全(不暴露数据真实信息)
  • 复合主键:多个字段共同组成不能重复的数据
    • primary key(字段1,字段2,…字段N)
    • 联合主键使用不多,一般也不会超过2个字段

步骤

1、确定字段数据具有唯一性 (unique)

2、确定数据不允许为空 (not null)

3、确定数据会经常用于数据检索(条件查询)

4、使用主键primary key

5、一般每张表都会使用一个逻辑主键(id)

示例

1、银行账户信息:账户、姓名、余额

# 银行账户具有唯一性,不能重复,也不允许为空
create table t_25(
    account varchar(17) primary key,
    name varchar(20) not null,
    money decimal(16,2) not null default 0.00
)charset utf8;

# 复合主键
create table t_26(
	account varchar(17),
    name varchar(20),
    money decimal(16,2) not null default 0.00,
    primary key(account,name)
)charset utf8;

# 一般使用逻辑主键
create table t_27(
	id int unsigned primary key,
    account varchar(17) not null,
    name varchar(20) not null,
    money decimal(16,2) not null default 0.00
)charset utf8;

2、主键数据不允许重复

insert into t_27 values(1,'6226000000000001','Lily',default);

# 错误:主键1已经存在
insert into t_27 values(1,'6226000000000002','Tom',default);

# 联合主键就是联合字段加起来不重复即可
insert into t_26 values('6226000000000001','Tom',default);
insert into t_26 values('6226000000000002','Tom',default);

3, 删除主键

alter table t_25 drop primary key;

4, 重新设置主键 (只能设置一个字段的主键)

alter table t_25 modify accout varchar(32) primary key;

小结

1、主键的作用就是控制对应字段的数据具有唯一性(不能重复)

2、一张表只能有一个主键

3、虽然主键可以用来保证数据的唯一性,但是一般都是使用逻辑主键作为主键字段(保证唯一性还有其他方式,如唯一键)

4、通常也不怎么使用复合主键

5.5 主键管理

概念

主键管理:在创建表并且已经有数据后的维护

  • 删除主键
  • 追加主键
  • 修改主键(先删除后新增)

示例

1、删除主键:主键只有一个,所以删除语法也比较特殊

alter table t_26 drop primary key;

2、后期新增主键:如果是针对业务主键需要保证字段数据没有Null数据且没有数据重复(一般主键都会在表创建时维护好)

# 新增的主键有多个字段
alter table t_26 add primary key(account,name);

#新增的主键只有一个字段
alter table t_26 add primary key(id);

小结

1、主键的使用通常是在创建表的时候就会指定好

2、主键的维护实际使用较少,主要涉及的操作是删除和新增

5.6 自增长属性

概念

自增长:auto_increment,被修饰的字段在新增时,自动增长数据

  • 自增长只能是整数类型,而且对应的字段必须是一个索引(通常逻辑主键)
  • 一张表只能有一个自动增长 ,该属性是表属性
  • 自增长数据可以理解为一种默认值,如果主动给值,那么自动增长不会触发
  • 自增长由两个变量控制
    • 初始值:auto_increment_offset,默认是1
    • 步长:auto_increment_increment,默认值也是1
    • 查看自增长控制:show variables like 'auto_increment%';

步骤

1、确定数据类型为整型

2、确定数据需要有规则的变化

  • 从1开始
  • 每次增长1
  • 可以调整,但是通常有固定规则(一般不调整)

3、必须是一个索引字段(逻辑主键)

4、使用auto_increment

示例

1、记录学生信息:学号和姓名

# 学生信息:学号自动增长
create table t_28(
    id int primary key auto_increment,
	stu_no int(8) zerofill not null,
    stu_name varchar(20) not null
)charset utf8;

Mysql基础部分_第8张图片

2、触发自增长

# 使用自增长(可以使用NULL或者default来触发)
insert into t_28 values(null,1,'Jim');
insert into t_28 values(default,2,'Tom');

# 主动控制:自增长的值会从当前最大的值开始自动增长
insert into t_28 values(10,3,'Lily');
insert into t_28 values(null,4,'Lucy');

Mysql基础部分_第9张图片

小结

1、自增长auto_increment一般是配合逻辑主键实现自动增长

  • 整型字段
  • 存在索引(主键)

2、自增长的触发是通过不给值(默认值)实现自动计算

3、自增长是根据当前表中自增长列最大值运算

4、一张表中只能有一个自增长

5.7 自增长管理

概念

自增长管理:在某些特殊使用下,需要自增长按照需求实现

  • 修改表中自增长的值:让下次自增长按照指定值开始

  • 修改自增长控制:调整自增长的变化

示例

1、修改表中自增长的值,跳过一些值,直接从下次开始按照新的目标值出现

alter table t_28 auto_increment = 50;

注意:奇数会保留原值,偶数会自动加1(可能出现的情况)

2、修改自增长控制:步长和起始值(修改针对的是整个数据库,而非单张表)

set auto_increment_increment = 2;	# 当前用户当前连接有效(局部)
set @@auto_increment_increment = 2;	# 所有用户一直有效(全局)

小结

1、自增长通常不会修改,如果有规则要求必须修改,通常也会在数据库运行前修改好

2、如果碰到要修改操作的,通常会选择全局修改而不是局部修改

5.8 唯一键

概念

唯一键:unique key,用来维护数据的唯一性

  • 一个表中可以有多个唯一键
  • 唯一键与主键的区别在于唯一键允许数据为Null(而且Null的数量不限)
  • 唯一键与主键一样,可以提升字段数据当做条件查询的效率(索引)
  • 复合唯一键:多个字段共同组成
    • unique key(字段1,字段2,…字段N)
    • 一般不会出现,最多2个字段组成
  • 唯一键最好要取一个名字,方便今后修改
  • 如果设置唯一键的时候不取名 ,默认为字段名称 (一个唯一键有多个字符的话默认为第一个字符的名称)

步骤

1、确定数据列具有唯一特性

2、确定数据列不用作为主键

3、确定数据会经常用于检索条件

4、唯一键字段是否允许数据为空

  • 为空:普通唯一键
  • 不为空:not null(唯一键与主键效果一样)

5、使用唯一键

示例

1、用户表:用户名唯一,而且经常作为查询条件

create table t_29(
	id int primary key auto_increment,
    username varchar(50) unique comment '唯一键,可以直接在字段之后增加,使用unique关键字',
    password char(32) not null
)charset utf8;

insert into t_29 values(null,'username','password');
insert into t_29 values(null,Null,'password');
insert into t_29 values(null,Null,'password');

# 错误
insert into t_29 values(null,'username','password1');

2、学生成绩表:一个学生只能有一个学科成绩,但是可以有多个学科

# 学号和学科编号共同组成唯一
create table t_30(
	id int primary key auto_increment,
    stu_name varchar(20) not null,
    course varchar(20) not null,
    score decimal(5,2),
    unique key(stu_name,course)
)charset utf8;

insert into t_30 values(null,'Jim','Math',50);
insert into t_30 values(null,'Jim','English',80);

3, 查看唯一键的名字

show create table t_30;

Mysql基础部分_第10张图片

4, 创建唯一键时指定其名称

# 指定唯一键名称为 hello
create table t_31(
	id int primary key auto_increment,
    stu_name varchar(20) not null,
    course varchar(20) not null,
    score decimal(5,2),
    unique key hello(stu_name,course)
)charset utf8;

小结

1、唯一键的目标是保证对应字段数据的唯一性

  • 唯一键不限定数据是否为Null(Null不参与唯一判定)
  • 复合唯一键:允许多个字段共同组成唯一性

2、唯一键能够弥补主键只有一个的特性(不限定数据量)

3、唯一键使用的位置应该要确保该字段数据会用作数据检索条件

5.9 唯一键管理

概念

唯一键管理:在表创建后对唯一键的管理

  • 删除唯一键:一张表中不止一个唯一键,所以删除方式是相对麻烦:alter table 表名 drop index 唯一键名字;
  • 新增唯一键:alter table 表名 add unique key [唯一键名称](字段列表);

示例

1、删除表中已有的唯一键

# stu_name 是 唯一键的名称 (默认为字段名)
alter table t_30 drop index `stu_name`;

2、追加唯一键

# stu_course 是唯一键名称
alter table t_30 add unique key `stu_course` (stu_name,course);
# 也可以
alter table t_30 add unique key(stu_name,course);
  • 追加唯一键要保证字段里的数据具有唯一性

也可以

alter table t_30 modify stu_name varchar(20) not null unique;

小结

1、唯一键一般也会在前期架构(创建表)时就会设置好

2、如果在后期数据庞大后进行数据库优化,可能会涉及到后期维护唯一键

3、唯一键的删除不能像主键那样删除,原因就是唯一键在表中不是唯一存在的,必须指定唯一键名字

5.10 comment属性

概念

描述:comment,是用文字描述字段的作用的

  • comment代表的内容是对字段的描述
    • 方便以后自己了解字段的作用
    • 方便团队了解字段的作用
  • 描述如果涉及到字符集(中文)一定要在创建表之前设置好客户端字符集(否则会出现描述乱码)

步骤

1、字段命名不是特别简单(见名知意)

2、使用comment增加简易描述

示例

1, 创建学生成绩表

# 学生成绩表中通常是存储学生学号
# 学科通常也是学科代码
create table t_32(
	id int primary key auto_increment,
    stu_no varchar(10) not null comment '学号',
    course_no varchar(10) not null comment '课程号',
    score decimal(5,2) comment '考试成绩',
    unique key `stu_course` (stu_no,course_no) comment '学号和课程号组成唯一键'
)charset utf8;

2, 查看注释信息

show create table t_32;

Mysql基础部分_第11张图片

小结

1、养成描述的良好习惯,为自己也为其他同事提供方便

2、并非所有字段都需要描述,但是对于自定义名字或者关联关系,都应该使用描述说清楚

5.11 总结

1、字段属性是基于字段类型对数据控制后,再进行其他控制(辅助加强字段类型对数据的控制)

2、巧妙的利用好字段属性,能够帮助我们更好的保证数据的有效性、安全性

3、字段属性与字段类型通常是搭配使用,常见的属性有

  • 主键(逻辑)+自增长
  • 唯一键+Not Null(Null数据不参与运算,没有价值)
  • 默认值以及default关键字的使用

6. 数据库记录长度

概念

数据库记录长度:MySQL中规定一条记录所占用的存储长度最长不超过65535个字节

  • 记录长度为表中所有字段预计占用的长度之和
  • 所有字段只有允许Null存在,系统就会预留一个字节存储Null(多个Null也只要一个就好)
  • 因为MySQL记录长度的存在,varchar永远达不到理论长度
    • GBK存储:65535(字符) * 2 + 2 = 131072(字节)
    • UTF8存储:65535(字符) * 3 + 2 = 196607(字节)
  • 一般数据长度超过255个字符都会使用text/blob进行存储(数据存储不占用记录长度

步骤

1、字符串字段如果超过长度255字符,使用text/blob替代

2、所有字段是否有允许为Null的,如果有要占用1个字节

3、计算字段所占用的预计总长度不要超过65535个字节

示例

1、GBK表能存储的最大varchar字符串长度

create table t_32(
	content varchar(65535)
)charset gbk;	# 错误

create table t_32(
	content varchar(32767)
)charset gbk;	# 错误

create table t_32(
	content varchar(32766)
)charset gbk;	

2、UTF8表能存储的最大varchar字符串长度

create table t_33(
	content varchar(65535)
)charset utf8;	# 错误

create table t_33(
	content varchar(21844)
)charset utf8;

3、Null也要占用一个字节

create table t_34(
    id tinyint,
	content varchar(21844)
)charset utf8;	# 错误

create table t_34(
    id tinyint not null,
	content varchar(21844) not null
)charset utf8;

小结

1、MySQL的记录长度是从设定表的时候就会检查所有字段加起来的预占用长度是否超过65535个字节

  • 超过:创建失败
  • 不超过:创建成功

2、创建表字段的时候要使用text/blob来避免长字符串出现,超过MySQL记录长度

3、Null是个细节,一条记录只要允许出现Null就会占用记录长度里的一个字节

7. 关系型数据库设计范式

学习目标:了解数据库设计的基础规范,掌握范式在数据库设计上的指导意义,运用范式科学设计好的数据库

概念

范式:Normal Format,符合某一种级别的关系模式的集合,表示一个关系内部各属性之间的联系的合理化程度

  • 范式是离散数学里的概念

  • 范式目标是在满足组织和存储的前提下使数据结构冗余最小化

  • 范式级别越高,表的级别就越标准

  • 目前数据库应用到的范式有以下几层

    • 第一范式:1NF
    • 第二范式:2NF
    • 第三范式:3NF
    • 逆规范化

示例

1、一张员工表

工号 姓名 部门 入职时间
0001 杨戬 武装部 0001-01-01
0002 李白 书院部 1500-12-12

2、每个员工都是与部门挂钩的,但是部门不可能很多,所以上述表中会有很多数据重复,此时应该将部门单独维护出来,减少数据冗余

部门编号 部门名称
1 武装部
2 书院部
工号 姓名 部门编号 入职时间
0001 杨戬 1 0001-01-01
0002 李白 2 1500-12-12

N个1和N个武装部占用的磁盘空间肯定是不一样的

小结

1、范式是一种数学理论,在关系型数据库上用来减少数据冗余

2、满足的范式越多,越符合高标准表设计

3、范式一共有6层,但是数据库的设计通常只要求满足3层即可

7.1 第一范式1NF

目标:了解第一范式的原理,掌握第一范式的实际应用

概念

第一范式:1NF,数据字段设计时必须满足原子性

  • 1NF要求字段数据是不需要拆分就可以直接应用
  • 如果数据使用的时候需要进行拆分那么就违背1NF

步骤

1、设计的字段是否在使用的时候还需要再拆分?

2、将数据拆分到最小单位(使用),然后设计成字段

3、满足1NF

示例

1、设计一张学生选修课成绩表

学生 性别 课程 教室 成绩 学习时间
张三 PHP 101 100 2月1日,2月28日
李四 Java 102 90 3月1日,3月31日
张三 Java 102 95 3月1日,3月31日

当前表的学习时间在使用的时候肯定是基于开始时间和结束时间的,而这种设计就会存在使用时的数据拆分,不满足原子性也就是1NF

2、满足1NF的设计:字段颗粒度应用层最小(不需要拆分)

学生 性别 课程 教室 成绩 开始时间 结束时间
张三 PHP 101 100 2月1日 2月28日
李四 Java 102 90 3月1日 3月31日
张三 Java 102 95 3月1日 3月31日

小结

1、1NF就是要字段数据颗粒度最小,保证数据取出来使用的时候不用再拆分

2、1NF是满足数据表设计的最基础规范

7.2 第二范式2NF

目标:了解第二范式的原理,掌握第二范式的实际应用

概念:

第二范式:2NF,字段设计不能存在部分依赖

  • 部分依赖:首先表存在复合主键,其次有的字段不是依赖整个主键,而只是依赖主键中的一部分
  • 部分依赖解决:让所有非主属性都依赖一个候选关键字
    • 最简单方式:取消复合主键(一般选用逻辑主键替代,但是本质依然是复合主键做主),所有非主属性都依赖主属性(逻辑主键)
    • 正确方式:将部分依赖关系独立成表

步骤

1、表中是否存在复合主键?

2、其他字段是否存在依赖主键中的一部分?

3、如果存在部分依赖,将部分依赖的关系独立拆分成表

4、满足2NF

示例

1、学生成绩表中学生和课程应该是决定性关系,因此属于主属性(主键)

学生(P) 性别 课程(P) 教室 成绩 开始时间 结束时间
张三 PHP 101 100 2月1日 2月28日
李四 Java 102 90 3月1日 3月31日
张三 Java 102 95 3月1日 3月31日
  • 成绩是由学生和课程决定的,是完全依赖主属性
  • 性别只依赖学生(部分依赖)
  • 教室、开始时间和结束时间依赖课程(部分依赖)

2、解决方案:将学生信息维护到一张表,课程信息维护到一张表,成绩表取两个表的主属性即可

学生表

Stu_id(P) 姓名 性别
1 张三
2 李四
  • Stu_id是姓名的代指属性(逻辑主键,本质主键是姓名)
  • 性别只依赖主属性

课程表

Class_id(P) 课程 教室 开始时间 结束时间
1 PHP 101 2月1日 2月28日
2 Java 102 3月1日 3月31日
  • Class_id是课程的代指属性(逻辑主键)
  • 教室、开始时间和结束时间都依赖课程(主属性)

成绩表

Stu_id(P) Class_id(P) 成绩
1 1 100
2 2 90
1 2 95
  • Stu_id和Class_id共同组成主属性(复合主键)
  • 成绩依赖Stu_id和Class_id本身,不存在部分依赖

小结

1、2NF是在满足1NF的前提之上的

2、2NF的目标是取消表中存在的部分依赖

  • 主属性(主键)为复合主键才有可能存在
  • 解决方案就是让部分依赖存在的关系独立成表(学生表和课程表),不存在部分依赖关系的独立成表(学生成绩表)

3、2NF可以实现很大程度的数据冗余减少

7.3 目标:了解第三范式的原理,掌握第三范式的实际应用

概念

第三范式:3NF,字段设计不能存在传递依赖

  • 传递依赖:字段某个非主属性不直接依赖主属性,而是通过依赖某个其他非主属性而传递到主属性之上
  • 传递依赖解决:让依赖非主属性的字段与依赖字段独立成表

步骤

1、确定表中的所有字段都是依赖主属性的

2、如果存在不直接依赖主属性,而是通过依赖其他属性产生依赖的,形成独立的表

3、满足3NF

示例

1、学生表:包括所在系信息

学号(P) 姓名 专业编号 专业名字
1 张三 0001001 软件工程
2 李四 0001002 土木工程
  • 姓名和专业编号都依赖于学号(为学号提供信息支持)
  • 专业名字依赖专业编号(为编号提供信息支持)
  • 专业名字间接依赖学号:传递依赖
  • 随着学生增加,专业名字会出现大量数据冗余

2、解决方案:将存储传递依赖部分的字段(非主属性)独立成表,然后在需要使用相关信息的时候,引入即可

专业表

专业编号(P) 专业名字
0001001 软件工程
0001002 土木工程
  • 即使有更多的信息为专业提供支持也不存在传递关系

学生表

学号(P) 姓名 专业编号
1 张三 0001001
2 李四 0001002
  • 姓名和专业编号都依赖学号(为学号提供信息支持)
  • 没有其他字段是通过非主属性(专业编号)来依赖主属性的:没有传递依赖
  • 学生再多,专业名字信息只需要维护一次,减少数据冗余

小结

1、3NF目的是为了解决非主属性对主属性的传递依赖

2、让有关联关系的表独立成表就可以消除传递依赖,满足3NF

7.4 逆规范化

目标:了解逆规范化的概念,掌握逆规范化的应用

概念

逆规范化:为了提升数据查询的效率刻意违背范式的规则

  • 逆规范化的目标是为了提升数据访问效率
  • 所谓逆规范化就是减少表之间的关联查询(效率降低),刻意增加数据冗余

步骤

1、表中部分数据来源于其他表(通常只需要其他表的某个简单数据)

2、当前表会被高频次查询

3、数据表数据量很大

4、考虑使用逆规范化

示例

1、学生成绩表需要经常查询,而且数据量很大,但是:

  • 成绩表中只有学号,显示的时候需要学生姓名(去学生表中连表查询)
  • 成表表中只有课程号,显示的时候需要显示课程名(去课程表中连表查询)
  • 逆规范化:将学生姓名和课程名在表中冗余维护(不满足2NF)
学号(P) 学生姓名 课程号(P) 课程名字 成绩
1 张三 1 PHP 100
1 张三 2 Java 90
  • 学生姓名部分依赖学号(主属性):不满足2NF
  • 学生姓名和课程名字会有大量数据冗余存在(不满足2NF导致)

小结

1、逆规范化只有在数据量大,查询效率低下的时候为了提升查询效率而牺牲磁盘空间的一种做法

2、逆规范化后数据表的设计必然是不完全符合范式要求的(2NF/3NF)

7.5 总结

1、范式是关系型数据库设计借鉴用来减少数据冗余

  • 1NF:数据字段的原子性,增强数据的可用性
  • 2NF:取消字段的部分依赖,建立数据的关联性,减少数据冗余
  • 3NF:取消字段的传递依赖,将相关实体独立划分,减少数据冗余
  • 逆规范化:为了提升数据访问效率,刻意增加数据冗余(磁盘空间利用率与访问效率的矛盾)

2、在进行数据表设计的时候,需要严格遵循范式规范

  • 基于规范设计数据表
  • 在设计表中深入认知范式规范
  • 熟练的基于业务设计数据表

8. 表关系

学习目标:了解MySQL中表设计关系,理解关系设计给数据库带来的方便,掌握表关系的应用实现复杂数据库设计

  • 一对一关系
  • 一对多关系(多对一)
  • 多对多关系

概念

表关系:一个表代表一个实体,实体之间都有关联关系的

  • 根据范式的要求来设计表关系,减少数据冗余
  • 根据实际需求来设计表关系,提升访问效率

示例

设计一个简单新闻管理系统的数据库

  • 新闻信息表:id、标题、内容、发布时间、作者id(作者表主属性)、分类id(分类表主属性)、阅读量、推荐数

  • 作者表:id、作者名字、作者来源id(来源表)

  • 来源表:id、来源名字、来源描述

  • 分类表:id、分类名字、分类级别(父分类id)

  • 评论表:id、评论人id(评论表)、评论时间、评论内容(不回复)

小结

1、表关系是体现数据实际联系的方式

2、表关系的设计好坏直接关联数据维护的准确性、有效性

3、良好的数据库设计有助于后期程序开发

8.1 一对一关系

目标:了解一对一关系的处理方式,掌握一对一关系的实体设计

概念

一对一关系:一张表中的一条记录与另外一张表中有且仅有一条记录有关系

  • 一对一关系通常是用来将一张原本就是一体的表拆分成两张表
    • 频繁使用部分:常用字段
    • 不常使用部分:生僻字段
    • 使用相同的主键对应
  • 一对一关系设计较多使用在优化方面

步骤

1、一张表的数据字段较多且数据量较大

2、表中有部分字段使用频次较高,而另一部分较少使用

3、将常用字段和不常用字段拆分成两张表,使用同样的主键对应

示例

1、学生信息表

学号(P) 姓名 性别 年龄 身高 体重 籍贯 政治面貌
1 张飞 20 178 160 农民
2 武则天 21 168 110 党员
  • 以上数据表信息字段较多
  • 姓名、性别、年龄属于常用字段,频繁查询

2、一对一关系设计

  • 将常用字段取出,与学号组合成一张常用表
  • 将不常用字段取出,与学号组合成一张不常用表
  • 表与表数据对应关系:基于学号(唯一)是一对一关系

常用表

学号(P) 姓名 性别 年龄
1 张飞 20
2 武则天 21

不常用表

学号(P) 身高 体重 籍贯 政治面貌
1 178 160 农民
2 168 110 党员

小结

1、一对一关系的核心是两张表中记录匹配有且仅有一条匹配

2、一对一关系常用来进行分表,实现优化操作

3、因为一对一关系表通常有相同信息作为匹配条件,所以查询方式也比较方便

  • 连表操作:利用共有信息进行匹配,一并查出一条完整信息
  • 多次查询:利用共有信息进行多表查询,利用程序组合成一条完整信息

8.2 一对多关系

目标:了解一对多关系的原理,掌握一对多关系的实体设计

概念

一对多关系:也叫多对一关系,一张表中的一条记录与另外一张表的多条记录对应,反过来另外一张表的多条记录只能对应当前表的一条记录

  • 一对多关系是实体中非常常见的一种关系,实体设计时也应用非常多
  • 一对多关系的核心解决方案是如何让记录能够正确匹配到另外表中的数据
    • 一表设计:一表记录在另外一张表中有多条记录,所以无法记录多个字段(违背1NF)
    • 多表设计:多表记录在另外一张表中只有一条记录,可以设置字段记录对应的主属性(通常主键)

步骤

1、确定实体间的关系为一对多(多对一)关系

2、在多表中增加一个字段记录一表中对应的主属性

示例

1、老师与学科间的关系:一个老师只能教一个学科,但是一个学科有多个老师教授,学科与老师形成的关系就是一对多(反过来老师与学科的关系就是多对一关系)

老师表(多表)

老师ID(P) 姓名 年龄 性别
1 张老师 35
2 李老师 34
3 王老师 30

学科表(一表)

学科ID(P) 名字 课时长度
1 PHP 600
2 Java 800
  • 以上两个实体没有体现彼此之间的关联关系
  • 实际上讲师与学科肯定是有关联的

2、在多表(讲师)中增加字段维护一表(学科)的关系型,形成多对一关系

老师ID(P) 姓名 年龄 性别 学科ID
1 张三 35 1
2 李四 34 1
3 王五 30 2
  • 基于新的讲师表与学科表产生了关联关系(多对一)
  • 基于讲师表可以知道讲师所属学科
  • 基于学科ID可以统计出不同学科的讲师数量

小结

1、一对多关系设计是将实体的关系在表结构层进行强制关联(没有关系程序层也可以控制,但是会非常麻烦)

  • 便于连表操作
  • 便于数据分析统计(数据库层)

2、一对多关系的核心在于分析出表与表之间的关系

8.3 多对多关系

目标:了解多对多关系的处理方式,掌握多对多关系的实体设计

概念

多对多关系:一张表中的一条记录对应另外一个表中多条记录,反过来一样

  • 多对多关系在实体中是最常见的关系
  • 多对多关系是无法在自身表中维护对应表关系的(违背1NF),需要通过第三方表来实现将多对多关系变成多个多对一关系
    • 设计一个中间表:记录两张表之间的对应关系(主属性)
    • 中间表与其他表都是多对一的关系

步骤

1、确定实体间的关系为多对多关系

2、设计中间表,记录两张表的对应关系

示例

1、老师与学生之间的关系:一个老师会教授多个学生,一个学生也会听多个老师的课,所以实体关系是多对多关系

老师表

老师ID(P) 姓名 年龄 性别
1 张老师 35
2 李老师 34
3 王老师 30

学生表

学生ID(P) 姓名 年龄 性别
1 小明 15
2 小红 14
3 小萌 14
  • 以上实体没有从结构上体现表之间的关系

2、设计一个中间表:老师与学生关系表,将老师与学生的对应关系对应上(多对一)

中间表

ID(P) 学生ID 老师ID
1 1 1
2 1 2
3 1 3
4 2 1
5 2 2
6 2 3
7 3 1
8 3 3
  • 中间表与老师表的对应关系是多对一:通过老师ID可以找到每一个上过课的老师
  • 中间表与学生表的对应关系是多对一:通过学生ID可以找到每一个听过课的学生
  • 老师找学生:老师表 ==> 中间表( 找出老师对应的学生ID) ==>学生表(找出学生ID对应的学生信息)
  • 学生找老师:学生表 ==> 中间表( 找出学生对应的老师ID) ==>老师表(找出老师ID对应的老师信息)

小结

1、多对多关系在表上不能直接维护(字段设计违背1NF)

2、多对多关系是将关系抽离形成中间关系表,形成多个多对一的关系

3、多对多关系是否建立主要看业务上是否存在数据要求,如果不存在数据需求,那么就没必要刻意设计

8.4 总结

1、表关系的设计是要遵循范式规范作为前提

2、表关系的设计是根据实体关系以及业务需求进行设计

  • 一对一关系:主要在于优化访问效率、传输效率
  • 一对多关系:在于如何让实体间的联系在结构中体现(后期可以使用外键进行相关约束保证数据的有效性)
  • 多对多关系:与一对多关系一样,清晰明了的体现实体间的结构联系

3、在设计数据库的时候,要严格使用表关系来进行实体关联设计

  • 基于表关系来实现实体间的关联控制
  • 在设计和应用表的时候提炼对表关系的认知
  • 能够熟练的基于业务控制数据库的关系

你可能感兴趣的