MySQL表的约束


真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。比如有一个字段是email,要求是唯一的。

表的约束很多,这里主要介绍如下几个: null/not null,default, comment, zerofill,primary key,auto_increment,unique key 。

一、 空属性

  • 两个值:null(默认的)和not null(不为空)
  • 数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。可以看到任何数据与null运算结果还是null,所以要尽可能保证字段不为空。

如下图:使用select语句可以查询null,同时null不参与运算
在这里插入图片描述

案例:
创建一个班级表,包含班级名和班级所在的教室。
站在正常的业务逻辑中:

  • 如果班级没有名字,你不知道你在哪个班级
  • 如果教室名字可以为空,就不知道在哪上课

此处我们创建一个class表,里面有两列内容一个是班级名字class_name一个是教室名字class_room,在擦汗如的时候这俩列都不能为空,所以我们可以设置not null属性
在这里插入图片描述
利用desc查询可以看到NULL这一列显示class_name和class_room显示NO
在这里插入图片描述
在进行插入的时候设置为not null的一列必须有值,除非有默认值,否则就会报错,比如这里只插入class_name或者只插入class_room,都会报错。
在这里插入图片描述
只有同时插入class_name和class_room才能插入成功。
在这里插入图片描述

所以我们在设计数据库表的时候,一定要在表中进行限制,满足上面条件的数据就不能插入到表中。这就是“约束”。

二、 默认值

默认值:某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候,用户可以选择性的使用默认值。
默认值的生效:数据在插入的时候不给该字段赋值,就使用默认值

例如这里创建一个user表,将age默认值设置为0,sex默认设置成’男’。
在这里插入图片描述

利用desc进行显示会发现Default一列就会显示设置的默认值。
在这里插入图片描述
–注意:只有设置了default的列,才可以在插入值的时候,对列进行省略

这里只插入名字name不插入age和sex,就会插入默认值,所以利用select查出来的age就是0,sex就是男。
在这里插入图片描述

当然虽然有默认值,我们也可以选择不用,而是自己插入值,这个时候插入的就是自己设置的值,比如这里显示的就是20和女而不是0和男。
在这里插入图片描述

三、列描述

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

其实列描述类似于程序语言中的注释,帮助理解,但不起其他作用
比如这里建立一个users表,将每一列都进行列描述
在这里插入图片描述

通过desc查看不到注释信息:
在这里插入图片描述

通过show可以看到:使用show create table 表名\G即可查看在这里插入图片描述

四、 zerofill

刚开始学习数据库时,很多人对数字类型后面的长度很迷茫。通过show看看tt3表的建表语句:

在这里插入图片描述
可以看到int(10),这个代表什么意思呢?整型不是4字节码?这个10又代表什么呢?其实没有zerofill这个属性,括号内的数字是毫无意义的。a和b列就是前面插入的数据,如下:
在这里插入图片描述

但是对列添加了zerofill属性后,显示的结果就有所不同了。修改tt3表的属性:
在这里插入图片描述

对a列添加了zerofill属性,再进行查找,返回如下结果:
在这里插入图片描述

这次可以看到a的值由原来的1变成00000 00001,这就是zerofill属性的作用,如果宽度小于设定的宽度(这里设置的是10,默认就是10),自动填充0。
我们可以手动在将它设置成5,看看效果。
在这里插入图片描述
可以看到由00000 00001变成了00001

要注意的是,这只是最后显示的结果,在MySQL中实际存储的还是1。为什么是这样呢?我们可以用hex函数来证明。
在这里插入图片描述
可以看出数据库内部存储的还是1,00001只是设置了zerofill属性后的一种格式化输出而已。

五、 主键

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

  • 创建表的时候直接在字段上指定主键

这里建立一个student表,显而易见每个学生的学号肯定是不能一样的,我们可以通过学号来唯一标识一个学生,所以在这里我们将id设置为主键,即primary key
在这里插入图片描述

  • 主键约束:主键对应的字段中不能重复,一旦重复,操作失败。

此处第一次插入1 bob的时候插入成功了,第二次再次插入1 bob的时候报错说1重复了,1的列是主键,因此插入失败了。但是name bob却没有报错,那是因为name是允许重复的,我们这里没有给它设置主键
在这里插入图片描述

  • 当表创建好以后但是没有主键的时候,可以再次追加主键
alter table 表名 add primary key(字段列表)
  • 删除主键
alter table 表名 drop primary key;

这里将student表中id的主键去掉
在这里插入图片描述

  • 复合主键
    在创建表的时候,在所有字段之后,使用primary key(主键字段列表)来创建主键,如果有多个字段作为主键,可以使用复合主键。

这里我们将id和course都设置成主键,利用desc进行查看的时候就会发现Key一列,id和course都有PRI。

在这里插入图片描述

再插入是复合主键不能全部相同,否则的话就会报错。在这个例子中就是id和course在插入时不能和表中已有的一行中的id和course都相同
在这里插入图片描述
想要插入成功的话只需要保证id和course其中至少有一个和表中的不同就可以插入。
在这里插入图片描述
使用alter table 表名 drop primary keySQL可以删除指定表的复合主键,比如这里删除进程表的复合主键后再查看表结构,可以看到ip和port对应的Key列的PRI都没有了。如下:

在这里插入图片描述
对于已经创建好了的表,也可以使用alter table 表名 add primary key(多个列名)SQL用多个列形成复合主键,但是需要注意的是,被选取的多个列当中的值不能为空并且不能同时出现重复。比如这里重新将ip和port设置成进程表的复合主键后再查看表结构,可以看到ip和port对应的Key列的PRI又回来了。如下:
在这里插入图片描述

六、 自增长

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

  • 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
  • 自增长字段必须是整数
  • 一张表最多只能有一个自增长

案例:
此处我们创建了一个autoincrement表,将id设置成了主键并且设置成了自增长
在这里插入图片描述
之后我们在插入的时候可以不用插入id,它会自动找出表中id最大的值num,并在下次插入的时候将id设置为num+1如果一开始表中没有数据那插入的第一条数据中id就是1.然后多插入几条,都不指定id是多少,id就会一直自动增长。
在这里插入图片描述

插入记录的时候也可以指明自增长字段的值,此时将会使用该值进行插入,但注意指明的值不能和表中已有的id值重复。此后向表中插入记录时如果又不指明自增长字段的值,那么自增长字段的值将会从id列中找出最大值,将最大值加一后得到的值作为自增长字段的值进行插入。
此处我们插入10和张飞,后面继续不指定id进行插入,可以看到id自动设置成了11、12.
在这里插入图片描述

在插入后获取上次插入的 AUTO_INCREMENT 的值(批量插入获取的是第一个值)
在这里插入图片描述

索引:
在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。

索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。数据库使用索引以找到特定值,然后顺指针找到包含该值的行。这样可以使对应于表的SQL语句执行得更快,可快速访问数据库表中的特定信息。

七、 唯一键

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

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

关于唯一键和主键的区别:
我们可以简单理解成,主键更多的是标识唯一性的。而唯一键更多的是保证在业务上,不要和别的信息出现重复。乍一听好像没啥区别,我们举一个例子

假设一个场景(当然,具体可能并不是这样,仅仅为了帮助大家理解)
比如在公司,我们需要一个员工管理系统,系统中有一个员工表,员工表中有两列信息,一个身份证号码,一个是员工工号,我们可以选择身份号码作为主键。
而我们设计员工工号的时候,需要一种约束:而所有的员工工号都不能重复。
具体指的是在公司的业务上不能重复,我们设计表的时候,需要这个约束,那么就可以将员工工号设计成为唯 一键。
一般而言,我们建议将主键设计成为和当前业务无关的字段,这样,当业务调整的时候,我们可以尽量不会对 主键做过大的调整。

案例:
创建一个student表,将id设置为主键和自增长,因为学号是不能重复的,但是电话号码tel也是不能重复的,但是主键一般只设置一个,我们要保证这里电话在表中的唯一性就可以将tel设置为unique
在这里插入图片描述
当插入的电话号相同的时候就会报错
在这里插入图片描述
此外,向表中插入的记录可以不指明唯一键字段的值,此时该字段默认为空,不做唯一性比较。如下:
在这里插入图片描述

八、 外键

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

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

案例:
在这里插入图片描述
对上面的示意图进行设计:

  • 先创建主键表

先创建一个班级表,将id设置成主键
在这里插入图片描述

  • 再创建从表

然后建立一个stu表,将id设置成主键
表当中包含学生的id、姓名以及学生所在班级对应的id,并将学生表中的班级id列设置成外键,关联到班级表中的班级id列。如下:
在这里插入图片描述

  • 正常插入数据

在这里插入图片描述

  • 插入一个班级号为30的学生,因为没有这个班级,所以插入不成功

在这里插入图片描述

  • 插入班级id为null,比如来了一个学生,目前还没有分配班级

在这里插入图片描述

如何理解外键约束

  • 理论上来说,我们创建班级表和学生表后就算不设置外键,在语义上其实也已经有了外键,但这样我们没办法保证后续插入学生表的记录中的班级id的正确性。
  • 而我们给学生表中的班级id设置成外键后,外键约束就能保证只有班级id在班级表中存在的记录才能插入学生表,否则就会插入失败。
  • 实际建立外键的本质就是把相关性交给MySQL去审核了,提前告诉MySQL表之间的约束关系,当用户插入不符合业务逻辑的数据时,MySQL就不允许你进行插入。

首先我们承认,这个世界是数据很多都是相关性的。 理论上,上面的例子,我们不创建外键约束,就正常建立学生表,以及班级表,该有的字段我们都有。
此时,在实际使用的时候,可能会出现什么问题? 有没有可能插入的学生信息中有具体的班级,但是该班级却没有在班级表中?
因为此时两张表在业务上是有相关性的,但是在业务上没有建立约束关系,那么就可能出现问题。
解决方案就是通过外键完成的。建立外键的本质其实就是把相关性交给mysql去审核了,提前告诉mysql表之间的约束关系,那么当用户插入不符合业务逻辑的数据的时候,mysql不允许你插入。

九、 综合案例

有一个商店的数据,记录客户及购物情况,有以下三个表组成:

  • 商品goods(商品编号goods_id,商品名goods_name, 单价unitprice, 商品类别category, 供应商provider)
  • 客户customer(客户号customer_id,姓名name,住址address,邮箱email,性别sex,身份证card_id)
  • 购买purchase(购买订单号order_id,客户号customer_id,商品号goods_id,购买数量nums)

要求:

  • 每个表的主外键
  • 客户的姓名不能为空值
  • 邮箱不能重复
  • 客户的性别(男,女)
-- 创建数据库
create database if not exists bit32mall
default character set utf8 ;
-- 选择数据库
use bit32mall;
-- 创建数据库表
-- 商品
create table if not exists goods
(
   goods_id  int primary key auto_increment comment '商品编号',
   goods_name varchar(32) not null comment '商品名称',
   unitprice  int  not null default 0 comment '单价,单位分',
   category  varchar(12) comment '商品分类',
   provider  varchar(64) not null comment '供应商名称'
);
-- 客户
create table if not exists customer
(
   customer_id  int primary key auto_increment comment '客户编号',
   name varchar(32) not null comment '客户姓名',
   address  varchar(256) comment '客户地址',
   email  varchar(64) unique key comment '电子邮箱',
   sex  enum('男','女') not null comment '性别',
   card_id char(18) unique key comment '身份证'
);
-- 购买
create table if not exists purchase
(
   order_id  int primary key auto_increment comment '订单号',
   customer_id int comment '客户编号',
   goods_id  int comment '商品编号', 
   nums  int default 0 comment '购买数量',
   foreign key (customer_id) references customer(customer_id),
   foreign key (goods_id) references goods(goods_id)
);
  • 34
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

争不过朝夕,又念着往昔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值