表的约束:表中一定要有各种约束,通过约束,让未来插入数据库表中的数据是符合预期的。约束本质是通过技术手段,倒逼程序员插入正确的数据。即,站在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的班级,显然也是不符合逻辑的,此时班级有学生,不能删除班级。也就是不能删除一个有学生的班级。
即,上面的设计是没有约束的,会引发相关的不符合逻辑的问题。
此时,就引入了外键来解决上面的问题。学生依赖于班级,所以学生表为从表,班级表为主表。学生表中有班级号,班级表中也有班级号,所以班级号就可以作为关联主表和从表的外键。
外键约束有两个关键点:
- 从表和主表的关联关系
- 产生外键约束
我们来重新设计表结构。
- 先建立主表班级表。
- 插入班级信息。
- 再建立从表学生表。
- 插入学生信息。
如果插入的学生信息,班级号在班级表中不存在,则报错。即插入的班级一定是存在的。此时,外键班级号就让从表和主表就有了关联关系,同时产生了约束。
- 删除班级信息。
如果删除的班级还有学生,就报错,不让删除,班级中没有学生才能删除。即删除的班级一定是没有学生的。此时,外键班级号就让从表和主表有了关联关系,同时产生了约束。
这就约束了,但凡插入表中的数据、删除表中的数据的操作,一定是合法的符合逻辑的操作。
至此,本篇一共总结了八种约束。