《MySQL:MySQL表的约束-主键/复合主键/唯一键/外键》

表的约束:表中一定要有各种约束,通过约束,让未来插入数据库表中的数据是符合预期的。约束本质是通过技术手段,倒逼程序员插入正确的数据。即,站在mysql的视角,凡是插入进来的数据,都是符合数据约束的!

约束的最终目标:保证数据的完整性和可预期性。
真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性。

空属性

两个值:null(默认的)和not null(不为空)

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

例:

创建一个班级表,包含班级名和班级所在的教室。

正常的逻辑是这样的:

  • 如果没有班级名,则不知道在哪个班级
  • 如果没有教室,则不知道在哪上课

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

如果对班级和教室不加约束,可以为空(默认的)。

插入数据的时候,没有给班级名或教室也能插入成功,插入的数据不符合不符合预期。显然这种不加约束的做法是不符合逻辑的。

对班级和教室进行约束,不能为空。

插入数据的时候,没有给班级名或教室名,就插入失败;能插入的数据一定是给了班级名和教室,一定是符合预期的。所以建表的时候一定要加约束。

defalut

如果设置了。用户插入的时候,如果显示的有插入的有具体的数据,就使用用户插入的数据;如果没有就用默认设置的。

如果设置了默认值,可以省略该字段,就使用默认值,只有设置了default的字段才能省略。

那么not null 和 default 有什么区别呢?

  • 如果没有明确指定一列要插入,用的是default,如果建表中,对应的列默认没有设置default,无法不直接插入。
  • default 和 not null 并不冲突,而是互相补充的。
  • not null:当用户想插入的时候,无非插入的数据要么是 null,要么是合法数据,如果字段为 not null,插入 null 则报错。
  • default:当用户忽略了某一列的时候,如果该列设置了默认值则使用默认值,如果没有设置,直接报错。用于为列指定一个默认值。

总结:

  • 如果用户想显示的插入数据,就是 not null 在约束,如果为 not null ,则插入数据不能为null。
  • 如果用户不显示的插入数据,就是 default 在约束,如果没有设置 default ,则该列不能直接插入**。**

建t14表的时候,字段没有指定 null 和 default,为什么也能直接插入呢?

MySQL会对sql指令优化。默认指定字段为 null、default 默认值也为 null。

列描述

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

zerofill

看下面这张表。

mysql会对sql语句做优化,将字段a int unsigned 类型优化为 int(10)unsigned;将字段b int 类型优化为 int(11)。10和11表示什么?其实没有zerofill括号内的数字是没有意义的。

括号内的数字表示数据的宽度。为什么int unsigned默认为10呢?

因为无符号整数表示-2147483648 到 2147483647,最大为21亿多,10位就足够将一个整数的数据位全部表示出来了;int 默认为11,因为有符号整数表示0 到 4294967295,最大为42亿多,加上符号位11位,11位就足够将一个有符号的整数的数据位全部表示出来了,

但是对列添加了zerofill属性后,显示的结果就有所不同了。修改t16a字段的属性。

可以看到,本来应该显示为1的,添加zerofill后,显示成了0001,这就是zerofill属性的作用,如果插入数据的宽度小于设定的宽度(这里设置的是4),自动填充0;如果插入宽度大于设定的值,显示的还是它本身。

要注意的是,这只是最后显示的结果,在MySQL中实际存储的还是插入的数据本身。

主键

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

  • 创建表的时候直接在字段上指定主键
  • 主键约束:主键对应的字段不能重复,一旦重复,操作失败
  • 删除主键
  • 创建表时没有指定主键,可以在创建表之后追加主键。如果创建表之后插入了数据,然后再指定某一个字段为主键时,必须要保证该字段数据不能重复

复合主键

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

注意:一张表中只能有一个主键,但是不意味着,一个主键只能添加给一个字段。

id和course共同组成了一个主键。即,一个学生不能重复选同一门课程。

自增长

auto_increment:当对应的字段指定了auto_increment,插入数据的时候,该字段给值,则用该值;如果该字段不给值,会自动的被系统触发,系统会从当前字段已经有的最大值+1,得到一个新的不同值,赋值给要插入数据的该字段。通常和主键搭配使用,作为逻辑主键。

如果建表的时候,不指定 auto_increment 的具体值,则从1开始。如果插入的数据被 auto_increment 指定的字段不给值,就从1自增。

如果插入的数据该字段有值,则使用该值。以后插入的数据,该字段如果不给值,则从该字段的最大值开始自增。

其实,插入一个数据的时候,表中就已经记录了下次要插入的数据的该字段的值了。

唯一键

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

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

唯一键和主键的区别:

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

外键

外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表必须是有主键约束或unique唯一键约束的。当定义外键之后,要求外键列数据必须在主表的主键列存在或为null。
foreign key ( 字段名 ) references 主表 ( 列 )

案例:建立两张表。我们来简单实现学生的插入和班级的删除,看看有什么问题。

  • 建立学生表和班级表。
  • 插入班级信息。
  • 插入学生信息。

按照我们设计的学生表来看,插入"103王五3"是没有问题的,但是不符合逻辑,因为班级表中,只有两个班级,班级号分别为1,2,没有班级号为3的班级,显然这种设计是有问题的。也就是不能插入一个不存在的班级。

  • 删除班级信息。

如果删除班级号1的班级,显然也是不符合逻辑的,此时班级有学生,不能删除班级。也就是不能删除一个有学生的班级。

即,上面的设计是没有约束的,会引发相关的不符合逻辑的问题。

此时,就引入了外键来解决上面的问题。学生依赖于班级,所以学生表为从表,班级表为主表。学生表中有班级号,班级表中也有班级号,所以班级号就可以作为关联主表和从表的外键。

外键约束有两个关键点:

  • 从表和主表的关联关系
  • 产生外键约束

我们来重新设计表结构。

  • 先建立主表班级表。
  • 插入班级信息。
  • 再建立从表学生表。
  • 插入学生信息。

如果插入的学生信息,班级号在班级表中不存在,则报错。即插入的班级一定是存在的。此时,外键班级号就让从表和主表就有了关联关系,同时产生了约束。

  • 删除班级信息。

如果删除的班级还有学生,就报错,不让删除,班级中没有学生才能删除。即删除的班级一定是没有学生的。此时,外键班级号就让从表和主表有了关联关系,同时产生了约束。

这就约束了,但凡插入表中的数据、删除表中的数据的操作,一定是合法的符合逻辑的操作。

至此,本篇一共总结了八种约束。

相关推荐
Hello World呀3 分钟前
oracle查询当前用户所有字段和表
数据库·oracle
ssauuuuuu5 分钟前
Oracle高级语法篇-merge into语句
数据库·oracle
一只鹿鹿鹿33 分钟前
【测试文档】项目测试文档,测试管理规程,测试计划,测试文档模版,软件测试报告书(Word)
数据库·后端·spring·单元测试
2302_7995257438 分钟前
【Redis】SpringDataRedis
java·数据库·redis
玩转数据库管理工具FOR DBLENS1 小时前
项目预期管理:超越甘特图,实现客户价值交付
数据库·职场和发展·项目管理·产品经理·数据库开发·甘特图
自由鬼1 小时前
开源身份和访问管理(IAM)解决方案:Keycloak
服务器·数据库·安全·开源·身份认证·单点登录
等等5431 小时前
mysql——基础知识
数据库·mysql
济宁雪人1 小时前
MySQL数据库(基础篇)
数据库·mysql
{⌐■_■}1 小时前
【MySQL】索引运算与NULL值问题详解:索引字段应尽量 NOT NULL ,NULL值不能参与部分索引运算
android·数据库·mysql