MySQL之表的约束

目录

一、表的约束

二、空属性

三、默认值

四、列描述

五、zerofill

六、主键

七、自增长

八、唯一键

九、外键


一、表的约束

前面我们所讲到的数据类型就是一种表的约束。为什么这么说呢?因为数据类型有自己的大小,也就是我们插入的数据是有范围的,不能够随意插入,这就对程序员的插入操作作了规范和约束,保证了插入的数据的合法性和完整性以及可预期性。

但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。比如:身高不能为负数,每个人的电话号码都是唯一的等。

约束本质:通过技术手段,倒逼程序员,插入正确的数据。

二、空属性

cpp 复制代码
null(默认的)和 not null(不为空)

数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。并且有的数据是不能为空的。

比如,在学校中,一个学生一定有其所在的班级,且不能为空,因为某个学生一定是属于一个确定的班级的,并且这个班级所在的教室也是确定的且不能为空,不然学生就不知道在哪里上课了。所以如果我们要创建一个学生的信息表的话,这两个字段不能够为空。

我们先创建一个学生信息表:

cpp 复制代码
mysql> create table stu(
    -> name varchar(20),
    -> class_name varchar(20) not null,
    -> class_room varchar(20) not null
    -> );

如下图的表结构:null一栏,yes表示可以为空,no表示不能为空。

然后我们向其中插入一些数据:

而如果我们插入null数据的话,就会出错:

而允许为空的列,它的默认值是null。所以如果插入null,则是合法的:

三、默认值

默认值(default):某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候,用户可以选择性的使用默认值。

下面我们在学生信息表中插入一列年龄信息,并设置其默认值是18。

下面我们进行包含age数据的插入,和不包含age数据的插入:

我们发现,如果用户指明了年龄,就使用用户指定的年龄,如果用户没有指明年龄,就使用我们设置的默认值。默认值的生效:数据在插入的时候不给该字段赋值,就使用默认值。

如果没有明确指定一列要插入,用的是default值,而如果没有设置default值,就会出错:比如下面,name就没有设置default值。

注:只有设置了default的列,才可以在插入值的时候,对列进行省略。

四、列描述

列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或DBA来进行了解列字段的含义。

具体使用方式如下:

cpp 复制代码
mysql> create table users(
    -> name varchar(20) comment '用户名字',
    -> address varchar(32) comment '用户地址',
    -> telephone int comment '用户电话'
    -> );

五、zerofill

引列:对于下表。

cpp 复制代码
mysql> create table t12(
    -> id int
    -> );

我们查看一下它的属性:

我们发现,int类型后面还跟了一个数字10。它肯定不是表示int类型的大小,因为int类型的大小是4字节,那么这个10代表什么意思呢?

其实没有zerofill这个约束的话,括号内的数字是毫无意义的。所以我们需要将他们结合起来理解。

比如,对于下表:

cpp 复制代码
mysql> create table t12(
    -> a int(5),
    -> b int(5)
    -> );

一般情况下,我们向表中插入数据没有什么特别的地方:

但是对列添加了zerofill约束后,显示的结果就有所不同了。修改t12表中,b的约束条件:

cpp 复制代码
alter table t12 change b b int(5) zerofill;

然后,我们再查看t12表中的数据:

其实,int身后括号里面的数字就表示数值显示的宽度。这里面显示的宽度是5。加了zerofill约束后,这次可以看到b的值由原来的2变成00002,这就是zerofill约束的作用,如果宽度小于设定的宽度(这里设置的是5),自动填充0。

根据上面的结果,要注意的是,这只是最后显示的结果,在MySQL中实际存储的还是1。可以看出数据库内部存储的还是1,00001只是设置了zerofill属性后的一种格式化输出而已。

六、主键

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

创建表的时候直接在字段上指定主键约束(primary key)。我们先创建一个包含主键约束的学生信息表:

cpp 复制代码
mysql> create table stu(
    -> id int primary key,
    -> name varchar(20),
    -> password int
    -> );

然后查看其列属性:列属性中key一列中pri表示该字段是主键。

先插入两条数据:

如果我们再插入一条id为2的记录,就会报错:

报错的提示信息就是id为2的主键冲突了。即主键对应的字段中不能重复,一旦重复,插入操作就会失败。

当表创建好以后,但是没有在创建时就指定主键的时候,可以再次追加主键。

cpp 复制代码
alter table 表名 add primary key(字段列表);

当你不再需要主键的时候, 可以删除主键:

cpp 复制代码
alter table 表名 drop primary key;

复合主键:在创建表的时候,在所有字段之后,使用primary key来创建主键,如果设置多个字段作为主键,这就是复合主键。

我们先创建一个包含复合主键约束的学生信息表:id表示学生编号,crouse_id表示课程编号,score表示该学生该课程的分数。

cpp 复制代码
mysql> create table stu(
    -> id int,
    -> crouse_id int,
    -> score int,
    -> primary key(id,crouse_id)
    -> );

然后我们向其中插入一些数据:

我们发现,对于复合主键,这里是(id,crouse_id),只要两个中有一个和表中数据不一样,就可以插入成功。如果两个中同时和表中的数据冲突了,那么插入失败。也就是说,(id,crouse_id)同时构成了主键。用上面的例子解释的话,就是一个同学可以选多个课程,多个同学选同一个课程,但是同一个同学不能多次选择同一个课程。

七、自增长

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

自增长的特点:

~ 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)。

~ 自增长字段必须是整数。

~ 一张表最多只能有一个自增长。

我们先创建一个包含自增长约束的信息表:

cpp 复制代码
mysql> create table stu(
    -> id int primary key auto_increment,
    -> name varchar(20)
    -> );

然后我们插入一些数据,并进行查询:

我们发现,有了自增长约束,我们不需要手动插入id数据,并且每次插入它还会自加1。这样还保证了主键不会冲突。

如果我手动插入id,会是怎么样呢?

从上面的结果可以看出,如果我们手动插入, 就会是我们用户自己指定的数据进行插入。而下一次插入时,也不指定id的话,id就会从13开始自增。

当然,我们也可以在创建表的时候就指定自增长值:

cpp 复制代码
mysql> create table stu1(
    -> id int primary key auto_increment,
    -> name varchar(20)
    -> )auto_increment=10;

插入数据:

八、唯一键

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

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

我们创建如下的学生信息表:

cpp 复制代码
mysql> create table stu(
    -> id int primary key auto_increment,
    -> telphone int unique key
    -> );

如下,key一列中的UNI就表示该字段是唯一键:

然后我们向表中插入一些数据:

我们发现,如果telphone插入相同的值就会报错,报错就是唯一键发生了冲突。

唯一键是可以为空的:

唯一键 VS 主键

主键:主要是用来标识表中一条数据的唯一性。

唯一键:主要是用来标识某一列的字段的数据不能出现重复。

九、外键

外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表则必须是有主键约束或unique约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null。

语法:

cpp 复制代码
foreign key (字段名) references 主表(列)

下面创建一张班级信息表(主表):

cpp 复制代码
mysql> create table class(
    -> id int primary key,
    -> name varchar(20) not null
    -> );

插入一些数据:

再创建一张学生表(从表):

cpp 复制代码
create table stu( 
id int primary key, 
name varchar(20) not null, 
class_id int, 
foreign key (class_id) references class(id)
);

下图,key列 MUL 就表示该字段是外键。

插入数据:

如果我们在stu表中插入class表中不存在的班级会发生什么呢?插入一个班级号为3的学生,因为class表中没有这个班级,所以插入失败了。

我们发现,报错提示会告诉我们不存在3号外键。

如下图,如果我们想要删除班级号为1的班级信息,就会报错,因为班级号为1的班级里还有学生。

相关推荐
高兴就好(石2 小时前
DB-GPT部署和试用
数据库·gpt
这孩子叫逆3 小时前
6. 什么是MySQL的事务?如何在Java中使用Connection接口管理事务?
数据库·mysql
Karoku0663 小时前
【网站架构部署与优化】web服务与http协议
linux·运维·服务器·数据库·http·架构
码农郁郁久居人下3 小时前
Redis的配置与优化
数据库·redis·缓存
MuseLss4 小时前
Mycat搭建分库分表
数据库·mycat
Hsu_kk5 小时前
Redis 主从复制配置教程
数据库·redis·缓存
DieSnowK5 小时前
[Redis][环境配置]详细讲解
数据库·redis·分布式·缓存·环境配置·新手向·详细讲解
程序猿小D5 小时前
第二百三十五节 JPA教程 - JPA Lob列示例
java·数据库·windows·oracle·jdk·jpa
Flerken1015 小时前
数据库语言、SQL语言、数据库系统提供的两种语言
数据库·sql·oracle
掘根5 小时前
【网络】高级IO——poll版本TCP服务器
网络·数据库·sql·网络协议·tcp/ip·mysql·网络安全