前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL表的约束

MySQL表的约束

作者头像
每天都要进步呀
发布2023-10-16 11:16:19
1840
发布2023-10-16 11:16:19
举报
文章被收录于专栏:C++/LinuxC++/Linux

一.表的约束的概念

真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。所谓约束,就是避免犯一些低级错误,比如类似于语法错误,编译器的编译失败实际上也算是一种约束。

表中一定要有各种约束,通过约束,让我们未来插入数据库表中的数据是符合预期的。

约束的本质: 通过技术手段倒逼程序员插入正确的数据。反过来站在mysql的视角,凡是插入进来的数据,都是符合数据约束的。

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

为什么数据库这么严格?

数据库作为维护用户数据的最后一道防线,必须要保证数据库的数据是满足预期的,因此数据库的约束必须严格。为了更好的约束,就需要更多的约束条件,这也是这一节的内容。

通过desc操作,其后四列就属于约束条件:

image-20230723210341424
image-20230723210341424

总结一下:约束就是表结构的设计者在其他人插入数据之前,预先把规则定好,再让被别人按照他的规则进行数据的增删查改,不满足约束的数据不会被插入到对应的表中,这样下来,插入后的数据就是完整的,并且是可预期的。

表的约束很多,这里主要介绍如下几个: null/not null,default, comment, zerofillprimary keyauto_incrementunique key

二.表的非空约束

1.NULL与’ '比较

在MySQL数据类型已经说过,这二者是不同的,NULL代表什么都没有,而' '代表一个空串。

在select语句中,NULL不会参与到相应的计算操作中。

image-20230724152011866
image-20230724152011866

2.空属性null

在这个约束中,有两个选择:

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

数据库默认字段基本都是字段允许为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。因此要添加非空约束,不让其中一个属性为空时插入。

创建表时约束不为空:not null

代码语言:javascript
复制
create table myclass(
    class_name varchar(20) not null,
    class_room varchar(20) not null,
    other varchar(20)
);
image-20230724152854498
image-20230724152854498

这样,在NULL列中就会发现显示的是No,也就是不允许为空,即我们插入数据时,代表No的两行必须插入有效数据,否则就无法插入。

image-20230724153552860
image-20230724153552860

三.默认值default

实际上就是缺省值,建表时设定之后,即便不对这个字段进行插入,其对应的值也会默认为default后面跟着的值。

image-20230724162609841
image-20230724162609841

插入default对应的字段后,就会将缺省值覆盖。

image-20230724162752027
image-20230724162752027

实际上,default就是在创建表之前将缺省值也插入进去。如果not null和default同时设置,not null的限制也会被default的缺省值补齐,因此并不是真的不插入,而是插入了缺省值。

image-20230724163850851
image-20230724163850851

我们在没有default约束,也没用not null约束时,是允许为空的,这个null值实际上却是mysqld底层优化出来的default的缺省值。

image-20230724164349296
image-20230724164349296

四.列描述comment

实际上comment描述的设置并不会阻止数据进行插入,其可以等同于注释,即对列的介绍。

image-20230724165436558
image-20230724165436558

那为什么还说comment是一种约束呢?实际上什么都约束不了啊?

其实,通过程序员的插入数据,comment会对思想上做出约束,告诉你这是一种什么数据。也算是一种软约束。

五.zerofill

zerofill约束,就是补位。对于我们所创建的表,会发现在一个整形数据类型中带有括号字段。

image-20230724175005552
image-20230724175005552

而这个字段就代表着整形int的数据的最大长度,一般的数据达不到这样的长度,那么如果使用zerofill约束,就会用0将没用到的位置进行占位。

image-20230724175447609
image-20230724175447609

插入数据:

image-20230724175543907
image-20230724175543907

可以看出二者的区别。

六.主键primary key

索引和主键之间是有联系的。

主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个。

主键;主键所在的列通常是整数类型,比如学号,编号等具有唯一性质的数据。

1.唯一主键

  • 创建表时约束某一字段为主键。
image-20230724191256459
image-20230724191256459

为了保证不能重复,不能为空,相应的创建语句在mysqld中也会添加not null,Key也会标记PRI保证不能重复。

  • 删除主键约束
image-20230724191538734
image-20230724191538734

这样,插入的数据就可以重复,但是通过观察,仍不能为空,因为not null在创建表时的添加约束期间会一并添加到约束。不过有了主键,才能更好的查找数据,因为其具有唯一性。

  • 已经建好的表对指定字段添加primary key约束
image-20230724192130042
image-20230724192130042

需要注意的是,添加primary key的字段,里面已经插入的数据不能存在重复值,否则就会违背主键的概念,导致约束添加失败。因此,为了避免这种情况,最好在创建表时一并添加主键约束。

2.复合主键

回到上述定义,一张表中最多只能有一个主键,但这并不意味着一个表中的主键只能添加到一列。一个主键也可以被添加到多列上,此时的主键被称为复合主键。

两个或者多个字段一并添加为主键,采用如下方式:

image-20230724193408221
image-20230724193408221

这就将id, course_id同时设置为主键,这两个字段就成为复合主键。即这两个字段只要不同时相同,那么就是唯一的。

验证

image-20230724193824731
image-20230724193824731

只要二个字段不是都相同,就可以进行插入,因为确定唯一性的字段有两个。

3.自增长auto_increment

自增长也算主键的一种。将其设置为主键,就不用继续管它,插入数据时它本身会为了防止重复而自增+1。看看定义是怎么给的

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

自增长的特点

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

那么此时,即便是主键的id,我们也可以不用理会,直接插入name字段也不会发生错误:

image-20230724202345230
image-20230724202345230

当然,就如同缺省值default一样,这个由于主键的唯一性多了一个自增的条,因此id也可以插入指定的数字:

image-20230724202637388
image-20230724202637388

如果继续插入,不理会id,那么它就会从1000开始自增,下一个就是1001:

image-20230724202757315
image-20230724202757315

为什么能够接着自定义的数据继续自增计数呢?

这是由于在表结构内部存在一个能够存储下一个id值的值,当下一条数据插入,就会将这个值赋值给新的数据对应的id字段:

image-20230724203132204
image-20230724203132204

而我们手动插入的值,实际上就会更改这个值,即将手动的值+1保存到此位置。因此,在建表时,我们也可以手动设置这个值:

image-20230724203751858
image-20230724203751858

通过last_insert_id函数,可以获取上一次的AUTO_INCREMENT的值:

代码语言:javascript
复制
select last_insert_id();

七.唯一键

唯一键:唯一键约束后,该字段也具备了和主键一样的唯一性。唯一键允许为空,而且可以多个为空,因为空字段不做唯一性比较。

唯一键和主键的区别:

  • 在使用中,主键是标识唯一性,而唯一键是保证业务中的数据唯一性。
  • 主键一个表只能有一个,唯一键可以有多个。
  • 主键不能为空,唯一键可以为空,甚至多个为空。

对于主键的标识唯一性以及唯一键的业务唯一性的理解:

一个表中若存在id,name,telephone三个字段,无疑id是要被标识唯一性主键的。在插入数据中,telephone作为业务上的数据,不能出现重复,一旦插入出现纰漏,将相同的telephone的数据给了不同的id,那么就造成了无法精准确定个人信息的情况,为了避免这种情况的发生,就需要将telephone进行唯一性约束

唯一性约束语法:unique

代码语言:javascript
复制
create table student(
    id char(10) primary key '学生的id',
    name varchar(20) comment '学生的名字',
    telephone varchar(11) unique comment '电话号具有唯一性'
);
image-20230726145841216
image-20230726145841216

八.外键

对于学生表和班级表,学生一定隶属于某一个班级,因此两个表之间一定存在所属关系,学生属于班级,设计表时通过外键约束学生就属于从表,班级就属于主表。

如果将学生表和班级表结合成一个表,那么在插入数据时,就需要插入大量的字段造成没必要的冗余。若将其分成两个表,那么通过一一对应的映射,来减少没必要的数据。

为什么会造成没必要的冗余?

假设学生表有三个字段,班级表有两个字段(其中有一个为公共属性)。在两个表的前提下,若要新增一名学生信息,只需要插入三个字段;若合并成一个表,那么就需要插入3+2-1=4个字段,并且我们知道组合起来的情况也会更多,两个表合并的结果就是数据位置上的相乘,比如:

两个表

image-20230726164022245
image-20230726164022245

合并成一个表

image-20230726164501055
image-20230726164501055

张三,李四的数据都分别出现了两次,所以一个表会产生数据冗余。

外键是用于定义主表和从表之间的关系

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

语法:

代码语言:javascript
复制
foreign key(字段名) references 主表(列)

实例

创建两个表,student和class

image-20230726165839395
image-20230726165839395

插入对应信息

image-20230726170523824
image-20230726170523824

上面插入的都是符合逻辑正常的插入。

如果在学生表中插入class_id=3的学生,虽然可以插入,但是class表中并没有对应的班级;如果操作delete from class where id=1;让通信101班级不存在,但学生表仍有通信101对应id的学生。因此,这就需要让两个表产生联动,插入class_id=3的学生的前提是存在id=3的班级,删除id=1的班级最后会连着学生表中所属class_id=1的学生信息一并删除,这就涉及到了外键的约束。

外键存在两种关系:

  1. 关联关系:逻辑上的关系,表与表之间有相同字段。
  2. 约束关系:通过关联关系实现表之间的约束。

此时student中的class_id存在外键之名(关联关系),但是没有外键之实。

所以,我们需要重新建立一个从表student,目的是引入外键的逻辑关系。

image-20230726172816659
image-20230726172816659

目前的学生表是空的,先插入数据:

image-20230726173206437
image-20230726173206437

若删除id=1的班级,也不会成功,因为student中还存在class_id=1的学生。只有在student中不存在id=1的学生,才能删除。

image-20230726173349925
image-20230726173349925

这就叫做外键约束。外键的本质就是产生关联,增加约束,保证表和表之间的完整性。 注:主表在从表存在的前提下,不能drop table 主表。


外键约束中,也存在constraint将外键约束命名,不过mysqld内部会自动做这样的操作。

image-20230726174325606
image-20230726174325606

九.综合案例

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

  • 商品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)

要求:

  • 每个表的主外键
  • 客户的姓名不能为空值
  • 邮箱不能重复
  • 客户的性别(男,女)

SQL操作:

代码语言:javascript
复制
-- 创建数据库
create database if not exists cfy_database
default character set utf8;

-- 选择数据库
use cfy_database;

-- 创建数据库表
-- 商品
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)
); 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-07-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.表的约束的概念
  • 二.表的非空约束
    • 1.NULL与’ '比较
      • 2.空属性null
      • 三.默认值default
      • 四.列描述comment
      • 五.zerofill
      • 六.主键primary key
        • 1.唯一主键
          • 2.复合主键
            • 3.自增长auto_increment
            • 七.唯一键
            • 八.外键
            • 九.综合案例
            相关产品与服务
            云数据库 MySQL
            腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档