表中一定要有各种约束,通过约束,让我们未来插入数据库表中的数据是符合预期的。约束的本质: 通过技术手段,倒逼程序员,插入正确的数据。反过来,站在MySQL的视角,凡是插入进来的数据,都是符合数据约束的!
约束的最终目标:保证数据的完整性和可预期性
真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。比如有一个字段是email,要求是唯一的。
表的约束很多,这里主要介绍如下几个: null/not null,default, comment, zerofill,primary,key,auto_increment,unique key。
创建一个班级表,包含班级名,班级所在的教室,班级类型;前两个字段不能为空,创建时带上not null
选项,后一个字段没有要求。
创建后,查看这张表发现,前两个字段是否允许列为空Null那一列写的是NO,后一个字段那一列写的是YES;
查看表创建时的详细信息,前两个字段那里有 NOT NULL,最后一个字段是DEFAULT NULL(下面解释)
向其中插入数据,此时3个字段均有值,可以成功插入
下面的方式插入字段,省略最后一个字段可以插入成功
将前两个字段(不能为空)中任意一个设为NULL, 就会报错
默认值:某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候,用户可以选择性的使用默认值。
默认值的生效:数据在插入的时候不给该字段赋值,就使用默认值
创建一张表,设置3个字段,姓名设为不可为空;年龄设置为给默认值,性别设置为不为空可以给默认值
创建后查看这张表,会发现Default这一列后两个字段有默认值,Null这一列age是YES, gender是NO,符合我们我们的预期。
查看表创建时的详细信息,也能看到
向表中插入数据时,如果不指明用户的年龄或性别,那么就会使用对应的默认值(缺省值)
解释一个字段同时设置not null
和default
两个值
default:如果设置了,用户将来插入,有具体的数据,就用用户的,没有就用默认的
如果我们没有明确指定一列要插入,用的是default;如果建表中,对应列默认没有设置default值,无法直接插入
这里同时设置not null
和default
的意义:
用户想要插入只能插入合法数据,不能为NULL; 如果用户没有把这一列带上,就是用明确的default值
列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或DBA来进行了解,相当于语言学习中的注释。
比如创建一个表,表当中包含用户名、用户的年龄和用户的性别,在每一个字段后面添加上对应的列描述
创建之后,查看表创建时的详细信息(通过desc查看不到注释信息)
数值类型后面的圆括号中的数字,代表的是显示宽度,数值类型设置zerofill属性后,如果数据的宽度小于设定的宽度则自动填充0,否则正常显示。
创建一张表,数据类型是int,不写后面的圆括号,默认创建后圆括号显示是10
向这张表插入数据,正常显示
修改表结构,给b列添加上zerofill属性,由于a列数据的显示宽度为10,因此查看表中数据可以看到a列数据中宽度不足10位的数据都自动在前面填充0
我们在向其中插入数据,还是刚才的显示规则,这是我们去查找值为200的,后发现查找到的是b;
证明了:设置了zerofill
属性后的只是对原来数值的一种格式化输出,在MySQL中实际存储的还是原来的数值
同时设置了zerofill
属性对存储的数据并不影响
将上面的int(10)修改为int(4)
后向其中插入一些值,不足4位不0填充,超过4位正常显示
主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个
主键:主键所在的列通常是整数类型。
创建表的时候直接在字段上指定主键
创建一张表,给学生id属性后面加primary key, 查表时会发现id这一字段有PRI的字样
向其中插入数据,一旦id重复就会报错
需要注意:只有列当中的值不为空并且不重复的列才能被设置成主键,如果列中已经有了重复的的值,则设置主键失败。这也说明要先把表结构设计好,不然后面插入有数据很难进行操作。
alter table 表名 drop primary key;
alter table 表名 add primary key(字段列表)
创建一张表,将id和课程id设为复合主键
向表中插入数据时,只有插入的学生ID和课程ID同时出现冲突时才会产生主键冲突,否则就允许插入
auto_increment
:当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操作,得到一个新的不同的值。通常和主键搭配使用,作为逻辑主键。
自增长的特点:
创建一张表,将id这一字段设为主键,同时带上auto_increment
选项,创建后查看表,Extra这一列会有auto_increment
向表中插入第一条记录时如果没有指明自增长字段的值,那么自增长字段的值默认将会从1开始。id不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操作,得到一个新的不同的值。
后续向表中插入不指明自增长字段的值,则自增长的值就会依次递增
如果指明了自增长的值,就会插入这个指明的值
如果后续插入还是不指明自增长的值,这次插入就会在上次插入的基础上自增长
其实原理很简单,查看创建表的详细信息,这里就会保存下一次自增长的值
同时在创建表时,也可以自己指明自增长的值,此时插入数据就会以此值为基础自增长
last_insert_id();
获取最后一个自增长的值
一个自增长应用的例子:
比如用户注册QQ号时腾讯内部会向这个用户返回QQ账号,此账号是一个唯一值,它的原理: 相当于向数据库后台插入一条记录,数据库后台把用户QQ这个字段设置了自增长
一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键:唯一键就可以解决表中有多个字段需要唯一性约束的问题。
唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较。
关于唯一键和主键的区别:我们可以简单理解成,主键更多的是标识唯一性的。而唯一键更多的是保证在业务上,不要和别的信息出现重复。
创建一张表,将id设为主键,电话号码和qq号设为唯一键,查看表就会发现Key一列是唯一键的有UNI字样
向其中插入值,除主键外,对于电话号码和qq号2个唯一键有任意一个值相同都会因为唯一键冲突插入失败,只有两者完全不同才会插入成功
同时唯一键允许插入为空
外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表则必须是有主键约束或unique约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null。
语法:
foreign key (字段名) references 主表(列)
首先创建一张这样的班级表
再创建一个学生表,表当中包含学生的id、姓名以及学生所在班级对应的id,学生id设为主键,班级id设为外键
表创建成功后查看表,学生表中的班级id对应的Key列出现了MUL
,这表明class_id已经成功被设置成了外键
向学生表中插入记录时,如果插入的记录对应的班级id是班级表中存在的,或者插入的班级id为null,那么此时是允许进行插入的。
如果插入一个完全不存在的班级id,是不允许插入的
在这里班级表是主表,学生表是从表,让class_id和id形成关联的关系,这就是外键约束。
有一个商店的数据,记录客户及购物情况,有以下三个表组成:
要求:
-- 创建数据库
create database if not exists bit32mall
default character set utf8 ;
-- 选择数据库
use bit32mall;
-- 创建数据库表
-- 商品
create table if not exists goods
(
goods_id int primary key auto_increment comment '商品编号',
goods_name varchar(32) not null comment '商品名称',
unitprice decimal not null default 0 comment '单价,单位分',
category varchar(12) comment '商品分类',
provider enum('供应商A','供应商B') not null comment '供应商名称'
);
-- 客户
create table if not exists customer
(
customer_id int primary key auto_increment comment '客户编号',
name varchar(32) not null comment '客户姓名',
address varchar(256) comment '客户地址',
email varchar(64) unique key comment '电子邮箱',
sex enum('男','女') not null comment '性别',
card_id char(18) unique key comment '身份证'
);
-- 购买
create table if not exists purchase
(
order_id int primary key auto_increment comment '订单号',
customer_id int comment '客户编号',
goods_id int comment '商品编号',
nums int default 1 comment '购买数量',
foreign key (customer_id) references customer(customer_id),
foreign key (goods_id) references goods(goods_id)
);