MySQL数据库入门到进阶!(3)——MySQL数据类型和MySQL表的约束

前言

**欢迎观看MySQL系列文章!!**第3篇主要讲述了++MySQL数据类型++ 和++MySQL表的约束++ ,表的约束包含了++空值++ 、++默认值++ 、++列描述++ 、++zerofill++ 、++主键++ 、++自增长++ 、++唯一键和外键++。

目录

前言

数据类型

数值类型

字符串(文本/二进制)类型

日期与时间类型

枚举和集合类型

表的约束

空值约束

默认值约束

列描述(注释)

zerofill

主键

删除主键

添加主键(建表后)

添加主键(建表时)

复合主键

自增长auto_increment

查看auto_increment

修改auto_increment:

唯一键

创建表时添加unique

创建表后添加unique

删除unique

外键

作用

1️⃣便于管理

2️⃣在业务上有多表之间的联动的删除/更新

创建表后添加外键

创建表时添加外键

查看外键

删除外键


数据类型

数值类型中

M:数据存储总长度;

D:数据标度/精度(存储到小数点后的位数)

分类 数据类型 说明
数值类型 BIT(M) 位类型。M指定位数,默认值1,范围1-64
TINYINT[UNSIGNED] 带符号的范围-128~127,无符号范围0~255。默认有符号
BOOL 使用0和1表示真和假
SMALLINT[UNSIGNED] 带符号是-2^15到2^15-1,无符号是2^16-1
INT[UNSIGNED] 带符号是-2^31到2^31-1,无符号是2^32-1
BIGINT[UNSIGNED] 带符号是-2^63到2^63-1,无符号是2^64-1
FLOAT[(M,D)][UNSIGNED] M指定显示长度,D指定小数位数,占用4字节
DOUBLE[(M,D)][UNSIGNED] 表示比float精度更大的小数,占用空间8字节
DECIMAL(M,D)[UNSIGNED] 定点数,M指定长度,D表示小数点的位数
文本、二进制类型 CHAR(size) 固定长度字符串,最大255
VARCHAR(size) 可变长度字符串,最大长度65535
BLOB 二进制数据
TEXT 大文本,不支持全文索引,不支持默认值
时间日期 DATE / DATETIME / TIMESTAMP 日期类型(yyyy-mm-dd)、(yyyy-mm-dd hh:mm:ss);timestamp时间戳
String类型 ENUM 枚举的一列值,字符串对象,值来自创建时规定的允许值
SET 字符串对象,可以有零或多个值,值来自创建时规定的允许值,多个成员之间用逗号间隔,成员值本身不能包含逗号

数值类型

数据类型本身是一种约束(之后会细讲)。

· 正负符号 :数值类型除了bool和bit类型,都是可有符号也可以无符号,默认有符号。

· 不同于其他数值类型,浮点数的无符号相比于有符号,取值范围是直接除去负数部分的范围,最大精度和最大长度是不变的。

· 插入拦截 :有或无符号的数值范围是不一样的(同C语言),如果插入的数据超过了范围,MySQL会拦截你的操作,不准插入。

· MySQL不会像C语言一样,会把进行数据截断,因为截断后的数据是没有完整性的,这会导致表中的数据变得不可信。

· 数据截断:修改字段时可以修改数值类型的M和D,如果把M或D变小,可能会发生数据截断,这种行为MySQL是不会拦截的,一定要小心。

· 默认设置:M,D和unsigned都是可选项,如果指明,就默认设置为最大长度、最高精度和有符号。但是版本不同,对这个默认值的设置是不一样的。

· 四舍五入:如果输入的数据精度 > 字段设置精度,会进行四舍五入,四舍五入的结果不会超过数据范围。

· 精度差异:decimal > double > float(默认情况下)。

字符串(文本/二进制)类型

· 存储大小单位:字符串类型的存储大小单位是字符数,不是字节数。如存一个"李"字和一个"L"存放的大小是一样的。

·char与varchar的区别 :varchar必须指定长度,没有默认值。

·在指定存储大小范围内,char不管输入的数据有多大,存储大小都是设置的大小;varchar存储大小 = 输入的数据大小 + 额外1~3个字节。

·varchar需要额外的1~3个字节记录实际存储长度,这几个字节不含在设置的存储大小单位里。

· 读取时,char不保留尾部空格,varchar保留尾部空格。

日期与时间类型

·占用字节:date固定3字节,"yyyy-mm-dd";datetime固定8字节,"yyyy-mm-dd hh-mm-ss";timestamp 时间戳固定4字节。

· 自动更新:在插入和更新数据时,timestamp类型的数据会自动更新为现在的时间戳。

枚举和集合类型

· 枚举类型: 即enum,在插入和修改时只能多选一。

如 gender enum('男', '女')。

· 数据输入格式:插入和修改时可以写设置的常量('男','女'),下标从1开始(这里'男'为1,'女'为2)。

· 集合类型: 即set,在插入和修改时可以多选。

如 set hobby('运动','听歌', '游戏')。

**· 数据输入格式:**插入和修改时可以写设置的常量,也可以写对应的下标。有多个选项时,插入和更新的数据选项放在一起,逗号分割(用常量就不用逗号和引号了):

sql 复制代码
insert into table_name values('name', 23, '运动,听歌');
insert into table_name values('name', 23, 6);

这里用到了位图的思想,6的二进制是110。从高到低,第1、2位为1,第3位为0,所以这里选择了前两个选项(运动、听歌)。

**· 插入拦截:**同数值类型,如果输入的数据不在范围内,也会被MySQL拦截。

表的约束

表通过各种约束,让我们插入数据库表中的数据是符合预期的。避免因为程序员的疏忽和失误导致插入错误的数据。数据库是后端数据的最后一道防线。

不满足约束的插入和修改会被拦截。

最终目标:保证数据的完整性和可预知性。

空值约束

两个数值:null 和 not null。

null:允许为空;not null:不允许为空

大多数字段的属性默认都是允许为空null,不允许为空的字段,必须输入数据,否则会被拦截。

这里class_id不允许为空,但是插入数据时没有给class_id输入数据,所以被报错拦截。

默认值约束

一开始就指定好默认值,当某字段的数值没有输入时,就使用默认值填充。

虽然class_id不允许为空,而且也没有给class_id输入数据,但是并没有报错,是因为在没有输入时,class_id使用了default默认数值。

一般,not null 和 default(非空)不需要同时出现。

default值我们自己不设置,MySQL也会自己设置默认值,一般默认值都是null 。

列描述(注释)

comment,没有实际意义,只有注释作用。

这个信息是给维护人员看的,MySQL不会对这个约束作任何反应,算是一种软约束。

zerofill

一种格式化输出的设置,与实际存储的数据没关系。

作用:位数未满zerofill设置位数的数据,在左边补够0之后再输出;位数超过zerofill设置位数的数据,显示原数据即可。

该约束除了影响输出格式,还会将数值类型变为无符号。如上,class_id被改为了unsigned。

zerofill只能给整数类型使用。整数旁的括号只有带了zerofill的时候才有意义。它的意思不是存储大小限制,而是控制格式化输出的字符宽度。

主键

用来让指定字段具有唯一性,每张表最多只能有一个主键。

比如:class表中有更多行数据,每行数据中班号是可以唯一标识该行数据的,即每个班的班号都是唯一的,不一样的。那么就把class_id就应是主键。还有工号、身份证等,都能作为主键。

不止插入是这样,修改数据同理。

此处报错"定义了多个主键"。

删除主键

使用alter ··· drop。

此时表中就没有主键了,class_id就可以存在重复的数据。

添加主键(建表后)

使用alter ··· add。

添加前要保证这个字段没有重复数据,否则是无法添加的。

添加主键最好建表的时候就添加,不然得删除和修改数据,不仅麻烦,还影响数据完整性。

添加主键(建表时)

复合主键

虽然表中只能有一个主键,但是主键可以有多个字段组成,这叫做复合主键。

此处有了有了一个复合主键,作用同普通主键,设为主键字段的数据要具有唯一性。

添加主键方式是一样的。

注意⚠️:如果表中已经有了一个普通主键,想把它变成复合主键,就要把原本的主键删了再添加。

自增长auto_increment

通常与主键搭配使用,能自动生成唯一且递增的数字的属性。

示例:

sql 复制代码
create table student(
    stu_id int auto_increment,
    stu_name char(10) not null,
    age int,
    gender enum('male','female'),
    primary key(stu_id)
)auto_increment=1;

上面的代码给主键stu_id设置了自增长。

最后的auto_increment设置了下一次写入的数字,每建一行,他会自动+1.

可见stu_id完成了自增长。

auto_increment也从1变为了4,所以下一次插入数据,如果你不手动修改,stu_id就是4了。

查看auto_increment

通过last_insert_id(),获得上次auto_increment插入的数值。

sql 复制代码
select last_insert_id();

修改auto_increment:

sql 复制代码
ALTER TABLE class AUTO_INCREMENT = 100;

注意⚠️:

· auto_increment只能给索引(主键、唯一键,该概念之后会说)使用。

· auto_increment只能给整数类型使用。

· 一张表只能用一次。

· 如果我们手动插入了非自增长预期的值,auto_increment会自行修改为手动插入值+1(如手动插入的数据是10,auto_increment就从4变为11)。

· 如果删除了之前的某行数据,auto_increment不会改变。

唯一键

和主键差不多,区别是唯一键允许为空,而且可以多个为空,空字段不会去做唯一性比较。

在使用上:主键用来标识身份唯一(学号、工号、身份证号等),唯一键用来标识业务唯一(电话、游戏等)。

创建表时添加unique

sql 复制代码
--直接添加unique约束
CREATE TABLE users (
    id INT PRIMARY KEY,
    username VARCHAR(50) UNIQUE,   
    email VARCHAR(100) UNIQUE
);

创建表后添加unique

sql 复制代码
alter table users add constraint uk_name unique (username);

alter table users add unique index uk_email (email);   

这里的uk_name是给唯一键显式指定名称,因为可能存在多个唯一键,所以要命名方便管理。不指定的话,一般默认会设置为字段名。

删除unique

sql 复制代码
alter table users drop index uk_username;

外键

作用

1️⃣便于管理

用于定义父表和子表之间的关系,外键约束主要定义在子表上。

这里的student和class表之间同样有class_id字段,通过这个字段,使得两个表存在了从属关系。结合实际,明显是student属于class的。这时就需要外键建立起这种关系。

我们也可以把两个表合在一起,就不需要外键了。但是这样存储数据,会多存很多重复数据,浪费资源,而且不易管理。案例如下:

订单ID 用户ID 用户姓名 用户电话 商品 金额
1 101 张三 138xxx 手机 5000
2 101 张三 138xxx 电脑 8000

在这里用户ID、用户姓名和用户电话重复存储了。若将用户ID作为外键,用户ID、用户姓名和用户电话另建一个表,就可以靠外键的联系减少重复存储了。

而且后续的查询,修改,删除操作使用的SQL语句也不会冗杂。

2️⃣在业务上有多表之间的联动的删除/更新

当一个用户注销(删除)之后,是不允许删除后的用户还拥有订单、评论和收藏等,就要把对应的订单信息也删除。

创建表后添加外键

sql 复制代码
ALTER TABLE 子表名
ADD CONSTRAINT 外键名
FOREIGN KEY (子表外键列) REFERENCES 父表名(父表主键列)
[ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
[ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}];

可选项:

on delete:父表外键列删除时

on update:父表外键列更新时

cascade :父表外键列删除/更新,子表外键列随之删除/更新

set null:父表删除/更新时,将子表中的外键列设为null

no action:如果父表删除/更新时,子表外键列有匹配的字段,不允许执行

restrict:同no action,这个选项是为了兼容标准SQL存在的。

创建表时添加外键

sql 复制代码
CREATE TABLE 子表 (
    ...,
    FOREIGN KEY (子表外键列) REFERENCES 父表(父表主键列)
) ENGINE=InnoDB;

**注意⚠️:
1️⃣外键要起作用,必须使用InnoDB存储引擎。**在大多数版本(最新版MySQL可能不需要)只有它有这个能力处理外键。其他引擎会忽略外键。
2️⃣外键必须联系上的是父表的主键列或者unique列

3️⃣添加时,子表外键列不可以存在父表主键列没有的数据,即"孤儿数据"。

4️⃣不要循环引用,父子关系只能是单向的。

5️⃣注意多层级联的cascade(A->B->C),一连串的删除更新可能会导致数据出错,要注意评估。

查看外键

sql 复制代码
show create table_name \G
-- or
show create table_name;

外键放置在子表中,父表中是看不到的。

删除外键

sql 复制代码
alter table table_name drop foreign_key_name

❤~~本文完结!!感谢观看!!接下来更精彩!!欢迎来我博客做客~~❤

相关推荐
青柠代码录4 小时前
【Redis】数据类型:String
数据库·redis·缓存
TDengine (老段)5 小时前
TDengine 超级表/子表/普通表 — 设计理念与内部表示
android·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
老纪5 小时前
c++怎么利用std--variant处理多种二进制子协议包的自动分支解析【进阶】
jvm·数据库·python
pigs20185 小时前
Docker容器中Kingbase数据库授权到期更换解决方案
数据库·docker·容器
guygg886 小时前
C# 监听数据库数据变化(SqlDependency 实现)
数据库·oracle·c#
隐退山林6 小时前
JavaEE进阶:MyBatis 操作数据库(入门)
数据库·java-ee·mybatis
晴天¥6 小时前
达梦数据库的内存结构
服务器·数据库·达梦数据库
倔强的石头_6 小时前
生产环境排坑实录:SQL 标量子查询的“静默杀手”与优化器的智能推演
数据库