MySQL数据库基础——数据库的约束
2026/9/24 17:45:28 网站建设 项目流程

文章目录

  • 约束
  • 非空约束 not null
  • 唯一约束 unique
  • 默认值 default
  • 主键 primary key
    • primary key
    • 主键的自增类型
    • 复合主键
  • 外键 foreign key
  • check(了解)

约束

约束是关系型数据库的一个重要功能,主要作用是通过加上约束的校验来保证数据的完整性,也可以理解为数据的正确性(数据本身是否正确,数据之的关联关系是否正确)

人工检查数据完整性的工作量非常的大,在数据表中定义一些约束,那么数据库写入数据的时候,数据库会帮我们做校验工作

约束一般是指定在列上的,对字段加上一些约束

非空约束 not null

作用:指定某一列不可以赋值为null

我们可以describe一下表结构看一下:

  • 在没有非空约束时,这些字段都是可以赋值为null的

约束的定义语法:

createtablestudent(idbigintnotnull);
  • 再给id赋值时写入null就会报错

唯一约束 unique

作用:为字段加上唯一约束,保证该字段不会出现重复值

createtablestudent(idbigintunique);

  • 可以看到字段id的键值Key中已经标识了UNI的唯一约束

如果都是id都是null的话不算重复,空值不能算是重复的

默认值 default

作用:在一个字段没有被赋值时,给上默认值

createtablestudent(namevarchar(50)default'无名氏');

  • 这样字段name的默认值就不再是null了,而是我们指定的“无名氏”,不过要是自己又手动赋值为null的也可以执行

主键 primary key

primary key

作用:它是 NOT NULL 和 UNIQUE 的结合,所以主键约束的列既是非空的也是唯一的。确保某列(或两个列多个列的结合)有唯一标
识,有助于更准确、更快速地找到表中的一个特定的记录。

分条总结:

  1. 唯一区分表中每条记录,不会出现重复行
  2. 作为其他表外键的引用目标,建立表与表之间关联。​
  3. MySQL会自动为主键建索引,大幅加快查询速度
createtablestudent(idbigintprimarykey);

  • 可以看到id的键值中标记了PRI的主键约束,且null值的可否赋值是NO

当然也可以使用not null和unique结合进行主键约束的定义,效果是一样的:

createtablestudent(idbigintnotnullunique);
  • 主键约束帮我们校验了非空和唯一,这两个校验在写入数据时会消耗一定的资源,对效率是有一定影响的,但是比起不做校验来说,那这个性能消耗还是承担得起的。而且主键对索引起到了非常重要的作用,所以强烈建议为每张表定义一个主键

主键的自增类型

createtablestudent(idbigintprimarykeyauto_increment);


auto increment 的作用:每次添加一条新记录时,当我们并没有给这行记录中的auto increment主键字段赋值时,数据库都会自动找到表中该字段的最大值,然后+1为该主键(字段)赋值

当我们插入一条记录:

insertintostudentvalues(null,10001,'张三');
  • 可以看到我们把第一个字段(id)的值设为null,但是它是一个自增类型的主键,就会出现下面的结果:
  • 可以看到虽然我们插入的是null,但是由于该字段是一个自增类型的主键,所以数据库会自动执行自增赋值,在表中原来的最大值id=0的基础上+1为新的id赋值,一般对自增类型的主键赋值就是直接采用null为其赋值,让数据库自己计算正确结果(而且即使insert时不管这个自增主键,也会照样自动进行自增赋值)

既然自增主键是自动赋值的,那能不能手动赋值?

也是可以的,只要不添加重复的值就行(主键是严格非空且唯一的):

  • 但是要注意一个特殊现象:如果我们往一个表中insert一条数据,但是由于种种原因,该SQL语句报错了,插入失败。但如果该表中有自增主键,那么这时即使语句没有执行成功,它的自增数也已经+1了,无法再退回去了。也就是说比如该自增主键是id,插入之前的最大值为8,即使插入失败该主键的自增数已经变为9了,下次正常成功插入一条数据,id会变为10,就会出现主键值不连续的现象(…7、8、10),这是MySQL允许的

扩展:索引
前面讲了,数据库会为主键自动建索引,那什么是索引呢?(只做简要介绍,后面深入讲)

  • 索引就是个目录,保存了“该主键字段的每列数据在哪一行存着”这样的位置信息,是额外存的结构,占磁盘空间,不是表本身的数据,它可以加快 where 、排序 order by 、分组 group by 的查询速度。

  • 默认只有主键和唯一键自动建唯一索引,因为唯一性约束本质上就是通过唯一索引来实现的。

  • 具体来讲就是:唯一约束的本质就是“不允许重复值”,数据库在插入或更新数据时,需要快速检查这个值是否已经存在。没有索引,数据库就得全表扫描才能判断重复,效率太低。所以数据库会自动为唯一约束创建一个唯一索引,用它来快速查重。

  • 其他字段不会自带索引,要手动创建。​当然我们也不会给所有字段建索引:索引占空间,还会拖慢增、删、改操作(查询的时候确实靠索引提速,但对数据执行增删改操作的同时要维护索引,所以增删改的操作会变慢),所以只给经常用来 where 、 order by 的字段建。

  • 唯一键就是被unique约束的字段,全称“唯一约束键”,主键是一种特殊的唯一键。

不过在MySQL(InnoDB)中:主键默认是聚簇索引,数据行按主键顺序物理存储;唯一键默认是非聚簇索引(辅助索引)。

要注意:

  • auto_increment 不能随便给普通字段用,一般搭配主键。auto_increment要求:字段必须是唯一索引,而主键本身就是唯一索引

原因:
① 数据库重启后,需要利用唯一索引快速获取字段最大值,初始化自增计数器。所以没有唯一索引都找不到最大值,怎么进行+1赋值?
② 唯一索引提供唯一性约束,防止你在手动为字段赋值(和上面演示的类似)时造成字段值重复。
③ MySQL InnoDB语法硬性要求。

虽然auto_increment 不是主键的专属属性,它只要求必须用在唯一索引上(其他非主键的唯一索引字段在语法上也可以使用auto_increment),但工程实践中确实只会给主键用,不会给其他字段加auto_increment

复合主键

  • 一个表中不允许出现多个主键:

  • 但是一个主键可以包含多个字段(复合主键)

复合主键语法:

createtablestudent(idbigint,namevarchar(20),primarykey(id,name));

  • 复合主键:在唯一校验时,对于两行数据,只有复合主键中所有的列都相同才被判定为重复。所以(1,‘张三’)和(2,‘张三’)就被认为是不重复的,这两条记录都可以成功插入

外键 foreign key

  • 可以看出左边学生表的主键是‘编号’,右边班级表的主键也是‘编号’,可以看到班级表的主键在学生表中也存在,那么它就叫做学生表的外键,表与表之间就是通过外键-主键进行关联的。当然上述的这个主键也可换做是具有唯一索引的字段,也是一样的效果

那么我们正常地创建这两个表:

当我们再向学生表中插入一个班级id=5的学生时,发现是可以成功添加的,但是在班级表中查找后发现实际上并不存在班级id为5的班级

insertintostudent(name,class_id)values('武松',5);
  • 手动定义外键约束就可以解决这样的问题

语法:

foreignkey(字段名1)references主表(字段名2)

意思是约束外键字段:字段1,它依赖/参考于主表的字段2:

  • 这样一来子表student就对主表class产生了依赖,数据库就会进行对该表中的外键值的校验,再插入一个主表中不存在的值就会报错。
  • 这样通过外键约束,保证了数据的完整性和关系的正确性

当子表中存在对主表数据的依赖的时候,能不能删除主表中相应的记录?

  • 当然是不可以的,如果要删除主表中的记录,子表中不能有对该条记录的依赖,也就意味要先删除子表中的外键字段值,再去删除主表中对应的主键字段值

check(了解)

作用:检查字段的值是否满足你写的条件,不满足就拒绝插入/修改。

但是MySQL8.0之后的版本才生效,之前的版本都不支持该约束(写了也没用,不生效)

-- 写法1:写在字段后面createtablestudent(idintprimarykeyauto_increment,ageintcheck(age>0andage<150));-- 写法2:写在所有字段后面(可以同时检查多个字段)createtablestudent(idintprimarykeyauto_increment,ageint,scoreint,check(age>0),check(scorebetween0and100));

以及像这样的写法:

check(genderin('男','女'))#性别只能是男/女
  • 就是因为他的版本兼容性差,所以一般也不使用它,可能部署到其他的数据库就失效了,但是代码还在,这就可能会导致错误

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询