目录
一、什么是约束:
二、非空约束:
三、default默认值:
非空约束和default默认值:
四、列描述:
五、zerofill:
六、主键
删除主键:
对已经创建好的表设置主键:
符合主键:
七、自增长:
八、唯一键:
九、外键:
十、综合案例:
一、什么是约束:
在 MySQL 中,约束是用于对表中数据的值进行限制的规则,目的是确保数据的完整性,一致性和有效性,它们通过定义列的取值范围,唯一性,关联性等,防止无效或不合理的数据被插入到数据库中
比如当我们进行插入的时候,如果因为粗心在住址上插入了人名,或者是在成绩上插入了学号,这样显然是不行的,所以为了避免这些问题,表中就需要有各种约束来让数据库中插入的数据是符合预期的
在我们之前的学习中,已经学过了数据类型,这其实也是一种约束,但是我们需要更多额外的约束来保证数据库中数据的预期
二、非空约束:
空属性有两个,分别是空和非空,
- 空表示该数据可以为空,也就是NULL
- 非空表示该数据不能为空,必须要插入数据
如下,我们创建一个表,让id可以为空,让grade不能为空
当创建成功的时候,进行查看的时候可以看到有一行NULL,如果是yes就表示该字段能够为空,如果为NO表示该字段必须插入
接着我们进行insert插入:
insert into t10 (id,grade) values (1,100);insert into t10 (id,grade) values (NULL,100);insert into t10 (id,grade) values (2,NULL);
可以发现,当id插入空的时候能够成功插入,但是如果是grade插入空的时候不能插入
进行查询的时候也能发现只成功插入了两行
我们也可以用如下指令来进行查看创建表的时候的约束条件
show create table 表名 \G
NULL 和 空' '
其中,' '和NULL并不等价,' '指的是已经插入了数据,只不过插入的是空串' ',而NULL是什么都没有插入的,并且NULL是不参与计算的:
三、default默认值:
这个和C++中的缺省参数差不多,当给一列设置默认值后,当向这一列进行插入的时候,如果不指定数据,那么就会采用默认值进行插入
如下,使用SQL语句创建表,其中名字约束不能为空,年龄age设置默认值为18,性别设置默认男
接下来进行查看该表的信息:
发现在default这一栏能够看到我们默认的缺省值
接着我们进行插入实验:
insert into t11 (name) values ('张三');
因为存在缺省值,所以在插入的时候可以不用指定插入的数据
当然,如果指定数据了,就用你所指定数据的值:
非空约束和default默认值:
当我们一个字段带上默认值的时候,这个字段一般是不会为空的,除非我们主动插入NULL,当我们插入数据的时候没有指明该字段的值,那么就会使用我们的缺省值
接下来可以做一个测试来理解这两:
如上,创建一个表,让name不能为空,让age有缺省值,让grade既不能为空又有缺省值
当我们对name进行插入的时候,
如上,正常插入是没问题的,但是当我们插入NULL的时候,毕竟前面设置了不能为空,所以报错name不能为空,当我们不管name的时候,发现报错说name没有缺省值
也就是说,当我们给某一列设置了NOT NULL,但是我们没有显示插入,那么就会使用缺省值,但是如果我们也没有设置缺省值,那么就会报错
所以,上述的grade,我们已经给他设置了缺省值,所以其应该是能够不管的
所以关于not null和default,二者是能够一起约束同一列的,当用户插入是否为空的时候,就由NULL和NOT NULL来进行插入的;当用户忽略插入这一列的时候,这个时候就是default来约束了,如果设置了default,就是用这个默认值,当没有设置缺省值就不能够忽略,如果忽略就报错了
注意:MySQL中,如果我们在创建表的时候没有设置默认值,其会自动给我们设置默认值NULL
四、列描述:
列描述是在创建表的时候对某一列进行描述的,类似于C++中的注释,并没有防止插入的场景
当创建成功后,可以通过show create table 表名 \G 来查看创建时的细节,desc 表名是看不到的
五、zerofill:
这个是格式化显示数据
- 如果插入的数据宽度小于限定的宽度就补齐0,
- 如果插入的数据宽度大于限定的宽度就不管
当我们创建的时候,用zerofill约束后,可以看到默认给我们int后面带上了数字,这个数字也是可以自己定义的
然后我们对其进行插入,然后在查看,发现被zerofill约束的值,如果比int后面的值要小,就会在前面补齐0
如果插入的数据比int后面的值大,就不管
六、主键
当我们在创建表的时候需要确保一条信息的唯一性,这样方便我们通过这一属性进行查找唯一行,这就是主键值key
当我们使用主键的时候,主键修饰的字段数据是不能为空的,并且一张表里面只能有一个主键,并且主键所在的列通常是整数型的
primary key
接下来创建一张学生信息的表,然后通过主键约束学生的学号保证学生学号的唯一性
create table t15(id int primary key comment '这是学生的id',name varchar(20) comment '这是学生的名字',age tinyint unsigned comment '这是学生的年龄');
接下来我们创建好了表,可以看到,被主键约束后的字段在显示中是能够看到的,表现为PRI,并且在NULL那一列,是自动设置成了不能为空的,对应着主键是不能够为空的
主键约束为了保证主键的唯一性,在向这个表进行插入的时候,主键是不能够重复的
如上,当进行插入的时候,可以看到,id不同是可以插入的,一旦当id相同的时候,会发现MySQL会报错导致插入失败,这样就能够保证id的唯一性了
删除主键:
alter table 表名 drop primary key;
这是删除一个表中的主键的,因为主键在表中只有一个,所以是不需要指明主键名字
当进行删除后,重新观察表,发现主键没有了
对已经创建好的表设置主键:
alter table 表名 add primary key(字段列表)
符合主键:
主键是只能有一个的,但是一个主键是能够由多个字段共同组成的
create table t16(id int,name varchar(20),class int,primary key(id,class));
如上,在创建时设置复合主键,这样二者是不能够同时重复的
然后我们进行插入数据测试:
如上,当插入刘备后,仅仅修改id或者是class是能够插入的
但是当id和class都一样的时候,才不允许插入
七、自增长:
自增长一般最好配合主键使用,其作用是让主键的值自动增长,并且在插入的时候可以不指定数据,此时其就会在当前字段中,找出最大的一个,将这个最大值+1后作为数据插入
在主键后面加上如下
auto_increment
create table t17(id int primary key auto_increment,name varchar(20));
接着查看当前表,发现和之前单单只有主键不同,其在extra部分有auto_increment修饰该字段
接着如果我们向该表中进行插入时,是可以忽略id的,如果是空表的话,id值会从1开始增长
当然,也可以显示插入,那么插入的数据就是我们写的
那么如果我们后面在忽略id的话,就会从11开始
那么MySQL是如何知道我们下一个是多少的呢?
当我们查看创建表的信息的时候,发现了如上红框框的,其里面存储的就是下一个主键自增的值
八、唯一键:
unique
主键是唯一的,那么现在怎么还有一个唯一键呢?
在我们的表中,比如学生表,一般不仅仅只有一个唯一属性,比如学生的学号,学生的qq,学生的电话号码,所以在一个表中,往往有很多唯一性的字段,那么如果只有一个主键的话,是不够的,所以就需要唯一键的修饰
唯一键和主键都能保证数据的唯一性,不同的是,唯一键所约束的字段可以为空,主键不可以,但是空字段不做唯一性的比较
唯一键更重要的是站在业务的角度去理解,主键和唯一键不是对立的,主键保证表当中记录的唯一性,唯一键保证当前列的数据不会出现重复
下面也举个学生表的例子,我们让逻辑上具有唯一性的学号为主键,让其他具有唯一性,如qq,电话号码等为唯一键
mysql> create table t18(-> id int unsigned primary key auto_increment,-> name varchar(20) not null,-> QQ int unique-> );
如上,我们创建好表后进行查看,发现在key那一栏中,我们设置好的键值是能够看得到的,发现UNI就是当前字段被我们设置好了
接着向表中进行插入数据:
如上,我们对id进行忽略了,因为我们让其自增长了,然后当插入的时候,QQ不一样的时候是能够插入的,但是当QQ一样的话,会因为唯一键冲突而导致插入失败
我们并没有对唯一键设置非空约束,并且其默认也是可以为空的,所以我们可以给插入NULL:
九、外键:
外键强调的是表与表之间的约束,定义主表和从表之间的关系,外键约束主要是定义在从表上的,主表必须有主键约束或者是唯一键约束,并且当外键定义后,要求插入外键列的数据必须在主表对应列存在或为NULL
主表不一定需要主键。但被外键引用的字段必须满足唯一性约束,即该字段需是主键或唯一索引,主键是唯一性约束的一种常见形式,但不是唯一选择
foreign key(字段名) references 主表(列)
比如创建两个表,一个表记录学生信息,另一个表记录班级信息,班级必须有编号,学生也必须有对应的班级号,这个时候这两者就必须有联系,不然的话学生里面插入了不存在的班级号,或者当班级被删除的时候里面还有学生信息,这都是不符合逻辑的,所以需要定义外键来将这二者约束起
首先创建主表,在班级学生例子里面,班级为主表
mysql> create table class(-> id int primary key,-> class_name varchar(20)-> );
创建好班级表,并且将班级id设置成主键
接着创建学生从表:
mysql> create table student(-> id int primary key auto_increment,-> name varchar(20) not null,-> class_id int,-> foreign key(class_id) references class(id)-> );
这里的foreign中 所创建的 class_id 和 class表中的id其类型必须相等
如上,当在学生表中看见key下面的MUL,就证明成功创建了外键
那么测试插入:首先向班级中插入班级数据
接着向学生表中插入数据:
如果是正常插入是可以的,但是如果插入不存在的班级是不被允许的
但是其是可以为空的,也就是插入空班级,也就是当前学生的班级未确定
并且当class中有学生后,删除class表中的数据是不行的
注意设置外键的时候:
- foreign中 所创建的 class_id 和 class表中的id其类型必须相等
- 主表无需主键,但被引用字段必须具有唯一性约束(主键或唯一键)
- 外键可引用主键或唯一键,而不仅限于主键
十、综合案例:
创建一个案例,一个商场中的表
商品表goods:商品编号goods_id,商品名称goods_name,单价unitprice,供应商provider
客户表customer:客户编号customer_id,姓名name,QQ,性别sex
购买表purchase:订单号order_id,客户编号customer_id,商品编号goods_id,购买数量nums
要求:
设置每个表都设置主键
将购买表中的客户编号和商品编号用商品表和客户表中的对应id约束
客户的姓名,商品的供应商不能为空值
QQ不能重复
客户的性别用enum(男,女)
创建商品表
mysql> create table goods(-> goods_id int unsigned primary key auto_increment,-> goods_name varchar(20) unique,-> unitprice double comment '这是商品的单价',-> provider varchar(20) not null unique comment '供应商'-> );
创建客户表
mysql> create table customer(-> customer_id int primary key auto_increment,-> name varchar(20) not null,-> QQ int unsigned unique,-> sex enum('男','女') default '男' -> );
创建购买表
mysql> create table purchase(-> order_id int unsigned primary key auto_increment,-> customer_id int,-> goods_id int unsigned,-> nums int unsigned default 1,-> foreign key(goods_id) references goods(goods_id),-> foreign key(customer_id) references customer(customer_id)-> );
向商品中插入数据:
向客户表中插入数据,并且当插入QQ相等的时候会受唯一键约束导致插入失败
向商品表中插入数据,当外键约束的字段插入对应不到商品表或者客户表中的编号的时候,MySQL会阻止插入