目录
- 表的约束
- 空属性(非空约束)
- 默认值(default约束)
- 列描述(comment)
- zerofill
- 主键(primary key约束)
- 自增长
- 唯一键(unique约束)
- 外键
表的约束
如果我自由自在的去往文件里写数据的话,你可以写整数,浮点数,类型写错了都没问题,你想怎么写就怎么写,这叫没约束, 有约束才是好的,能将错误给你暴露出来,就和我们平常写代码一样写错时会编译报错一样。
表的约束:表中一定要有各种约束,通过约束,让我们未来插入数据库表中的数据是符合预期的。约束本质是通过技术手段倒逼程序员,插入正确的数据。反过来,站在程序员使用数据的时候,就不用担心数据是否不符合预期,是否不正常,凡是在插入进来的数据,都是符合数据约束的
约束的最终目的:保证数据的完整性和可预期性
表的约束有很多,这里主要介绍如下几个:null/not null,default,comment,zerofill,primary_key,auto_increment,unique_key。
空属性(非空约束)
在学C/C++的时候整数0和’\0’和NULL在数字上都是0,但在mysql中表示没有,在mysql中单引号双引号都表示字符串,我们一般写为单引号,''表示空串,这表示有,但为空串,而NULL表示没有。
null不参与运算
示例:
数据库插入时默认字段为null空,但是实际开发时,尽可能保证字段不为空not null,因为数据为空没办法参与运算。
案列:创建一个班级表,包含班级名和班级所在的教室
站在正常的业务逻辑中:
- 如果班级没有名字,你不知道你在哪个班级
- 如果教室名可以为空,就不知道在哪上课
所以我们在设计数据库表的时候,一定要在表中进行限制,满足上面条件的数据就不能插入到表中。这就是“约束”。
我们other属性列没有写default null,但查看的时候有,这是因为mysql对我们的雨具做了重新调整和优化。
站在用户角度设置了not null能拦住插入控制,站在mysql的角度,有not null的列属性未来一定有具体的值。
默认值(default约束)
默认值:某一种数据会经常的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候,用户可以选择性的使用默认值。
示例:插入一个人的信息性别的时候,默认值设为男,如果你插入时指定了性别为女,则为女。
不指定性别,默认插入为男。
如果一个属性列既设定为not null 又设定为default,是否冲突?
发现某一属性列设置了not null,mysql就不会自动优化default null添加默认值。
结论:default和not null并不冲突,而是互相补充的。当用户想插入的时候,插入NULL,被非空约束着;当用户没有插入的时候,因为没有设置默认值,报错了,被default约束着。
列描述(comment)
comment,专门用来描述的字段。
这个字段的约束在哪里呢?这是一种软约束,程序员能根据这个描述大概能知道应该插入什么数据。
zerofill
建表的时候圆括号里面写了10,这个10代表什么意思呢?其实没有zerofill这个属性,括号内的数字是毫无意义的。
zerofill的作用:如果宽度小于设定的宽度,自动填充0。要注意的是,这只是最后显示的结果,在MySQL中实际存储的还是2,0000000002知识设置了zerofill属性后的一种格式化输出而已。
主键(primary key约束)
primary key用来约束某一字段,该字段不能重复,不能为空,一张表中最多只能有一个主键;主键所在的列通常是整数类型。
示例:
可以看到mysql对我们的语句进行了优化
主键插入了相同的值,报错了。
对于程序员来讲:你插入的数据不能重复,重复了/冲突了不让你插入,倒逼程序员插入的时候不重复。站在mysql的角度,这个表里面的主键数据一定是不冲突的。
一张表中最多只能有一个主键,不意味着一个表中的主键只能添加给一列,一个主键也可以添加到多列上。这也叫做复合主键。
这两个合起来才称为主键,只有这两个同时相等才会报错。
自增长
auto_increment:当对应的字段插入时不给值,系统会自动插入一个值,这个值是当前字段中已有的最大值+1。通常和主键搭配使用,作为逻辑主键。
自增长的特点:
- 任何一个字段要做自增长,前提是本身是一个索引
- 自增长字段必须是整数
- 一张表最多只能有一个自增长
示例:
我们没有插入id属性这一列,自增的插入了。
mysql给我们的语句优化:显示的是下一次auto_increment将要插入的值为多少
主键是和索引强相关的。索引是什么?索引是加速mysql查找的技术策略,比如有一本书,有800页,你要找到多线程的那一页,如果不看目录,你就只能线性遍历,效率是很低的。
目录本质上是key(页数)value(主题)的结果。目录的作用是加速我们快速的去定位某一个内容,因为多花了20页的纸来保存目录,花更多的时间以提高我们查找效率。索引的本质就是以空间换时间。
后面会有专门的章节来讲索引。这里做个预备,方便之后更易理解。
唯一键(unique约束)
先直接上示例:
插入相同的失败了,意料之中。
发现可以插入NULL,并且多个NULL也不会冲突。为什么呢?因为NULL不参与运算,怎么比较运算都返回NULL。
与主键不同,主键不能插入NULL,并且主键一个表中只能有一个,而唯一键可以有多个。
主键和唯一键都表示唯一性,那我建表时应该如何选择呢?
建表的本质就是来描述一个对应的对象,mysql的表就相当于C/C++中的结构体,来描述抽象的事物,一个人是有很多的属性,从一个人身上的众多唯一键属性的一列挑一个作为我们的主键,比如一个人有身份证,有学号,在社会中可以选择身份证作为主键,在学校可以将学号作为主键,但是他们都具有唯一性。这就是他们之间的关系。
电话两个人是一样的,在现实生活中这是不合理的。主键保证了唯一性,但其他的属性不代表不需要唯一性,以防这种情况出现,就需要唯一键来约束。
关于唯一键和主键的区别:
我们可以简单理解成,主键更多的是标识唯一性,而唯一键更多的是保证在业务上,不要和别的信息出现重复。
外键
外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表则必须是有主见约束或unique约束。当定义外键后,要求外键列数据必须在主键的主键列存在或外键为null。
示例1:
如果将班级表中的数据都设计在每个学生表的后面,那就会出现数据冗余,所以我们只要设计成这样就能将班级信息和学生信息分开,并且也形成了关联关系。
这是不合理的,没有class_id为3的班级,却插入成功了。
这也是不合理的,class_id为1的班级还有学生,却能直接删除了,这些学生已经悬空了,不属于任何班级了。
如何解决上述的问题呢?上面之所以引发这些问题,就是因为没有约束,所以我们要构建外键约束。
发现之前的操作,现在都被拦截了。这就是外键的约束,
外键的两方面的概念:
- 主表和从表产生关联关系:使两个表产生了联系。
- 产生外键的约束:保证了数据的完整性。