写在前面
我们已经会创建数据表了,不过有时候会看到not null等字样,这些便是字段约束的内容,我们好好看一看什么是约束,又有哪些约束,这份博客时纯理论的,我们自己要理解这里面的内容
什么是字段约束
简而言之,字段约束就是将字段的内容定一个规则,我们要按照规则办事,常见的字段约束有下面几个
约束的分类
这里我们先把约束给大家列出来,后面都会谈到.
- not null – 指示某列不能存储 NULL 值
- unique – 保证某列的每行必须有唯一的值
- default – 规定没有给列赋值时的默认值
- **primary key ** – not null 和 unique 的结合。确保某列(或两个列多个列的结合)有唯一标
识,有助于更容易更快速地找到表中的一个特定的记录 - foreign key – 保证一个表中的数据匹配另一个表中的值的参照完整性
- check – 保证列中的值符合指定的条件。对于MySQL数据库,对check子句进行分析,但是忽略
check子句 ,我们不太常用,就不说了
为何要有字段约束
- 保证数据的完整性
- 保证数据的有效性
完整性
我们有时候填表会发现有些是必填项,这里就是not null的作用,他要求这个表格不能为空,获取我们完整的信息
有效性
在这里我们假设一个个场景,要是张三的电话号码是123×××××××45,那么李四的电话号码绝对不会和张三一摸一样,这里就体现出unique的作用了
我们先创建一个表格,来仔细看看
create table books(
book_id char(10) not null,
book_name varchar(20) unique,
book_price int
);
非空约束 not null
非空约束比较简单,就是要求我们不能为空,命令为 not null
在上面我们就看到了这行代码 book_id char(10) not null, 这就是说book_id不可以为空
我们观察一下表结构,你就会发现在null这一列id是禁止为空的.
唯一约束 unique
这里也很简单,唯一 的意思就是各不相同,代码是**book_name varchar(20) unique,**这里就不演示表结构了,上面的key中的name的UNI就是唯一的.
默认值约束 default
这个时定义默认值的,要是我们不定义,它是NULL,如果我们设置了,这就会改变.我们重新创建表.
create table books(
book_id char(10),
book_name varchar(20) default 'unknow',
book_price int
);
我们先测试一下,只要我们插入数据,都会把这个数据保存下来,无论是不是null.
insert into types values (1,NULL,'测试');
一旦我们部分列插入,没有插入的数据就会变成默认值.
insert into types (type_id,type_remark)values (1,'测试'); -- 部分列插入
主键约束 primary key
这个约束我们在MySQL中最常用到的约束,这里的主键约束相当于唯一约束和非空约束的集合,不过也会有一些另外的不同.
- 主键约束 = 非空约束 + 唯一约束
- 主键约束也是一个标识,就像人的身份证
- 主键一个表只能存在一个,而且一个主键只能作为一列.
创建主键
我们最好每一张数据表都创建一个主键,后面我们用到索引的时候会说一下原因
我们在创建字段的时候指定.
create table Persons(
per_id char(10),
per_name char(12),
per_age int(3),
per_tele char(10) primary key -- 创建字段时指定
);
也可以在创建表的最后指定主键,不过要把字段和类型说完整,当然不完整也是可以的,但是这种方法我们一般不用,都是在字段后面直接指定主键的.
create table Persons(
per_id char(10),
per_name char(12),
per_age int(3),
per_tele char(10),
primary key(per_tele char(10)) -- 最后指定
);
删除主键
这里就体现出主键约束和其他的一些不同,我们删除时就不需要看具体的字段
alter table Persons drop primary key;
添加主键
对于一张没有主键的表,我们也可以等后面给他添加上.
alter table Persons modify per_tele char(10) primary key; -- modify 调整
不能为空
这里我们就要看一下什么叫做不能为空,对于简单的默认值是null我们就不看了,这里重点看一下默认值是其他的时候,看看效果如何.我们先来创建一个表.
create table books(
book_id char(10),
book_name varchar(20) primary key default 'unknow',
book_price int
);
这里我们部分列插入数据,先来插入一行看看效果.
insert into books (book_id,book_price)values ('123',15);
从这里看我们成功了,也就是是说,所谓的不能为空,就是数据不能是null.
不能相同
这个就不给大家解释这么多了,我们再次插入一下数据.这里就会报错,原因就逐渐的数据是不能重复的,要知道默认值是一样的,所以报错.
insert into books (book_id,book_price)values ('456',20);
主键的自动增长
在实际生活中,我们可能会遇到这么一个问题,很多字段我们不能保证他们不为空或者是两两不同的,我们可以创建出一个额外的字段让他们好寻找,自然而然的就会以1、2、3、…来标识,不过这也太麻烦了,我们出现了自动增长的形式
create table types(
type_id int primary key auto_increment,
type_name varchar(20),
type_remark char(11)
);
这个代码将type_id设置为自动增长主键
我们先来插入一个数据,对于自动增长的主键,这里我们先来设置为null.
insert into types values (null,'123','20');
这里我们就会发现,对自动增长的主键,我们即使设置为null,他也会从1开始自动增长.
这里我们闲来测试一下如果我们只是插入部分列,看一下自动主键是不是会增长.
insert into types (type_name,type_remark)values ('789','20');
从这我们就可一看到就看到,对于自动增长的主键,我们无论是指定null,还是不做数据的插入,都会自己加上1.
不过自动增长也有一些缺陷,要是我们删除一行,其他的type_id的值是不变的,也就是我们删除了中间数据,后面的自动增长的主键的值是不是改变的
delete from types where type_name = '456'; -- 可以 用 = 判断字符类型
这里我好好解释一下,只要我们添加了一行数据,他就会+1,即使我们后来删除了,它也不会 -1,是一直加的
这里还需要指出,如果我们明确指出主键的确定值,这个主键值就变了.之后再次插入,主键值还是相对于上一个+1.这里就不演示了.
联合主键
这里我先建一个数据表格,这张表中我们会发现,我们学生和课程只有在一起我们才能得到真实的成绩。所以这就出现了联合主键,联合主键,顾名思义就是多个主键联合形成一个主键组合,体现在联合.
我发现这里的字段都不能作为主键,但是学生和课程连在一起却可以,这就是联合主键
如何定义联合主键
create table grades(
stu_name char(10),
stu_class char(5),
stu_grade int,
primary key(stu_name,stu_class) -- stu_name 和 stu_class 一起 定义主键
);
这里面提示一下我们很少使用联合主键,我们可以额外提供一个字段作为识别
外键约束
我们可能会疑惑什么是外键约束,我直接说一下,外键约束时联系多张表的约束,下面我用例子为大家说明一下我们先创建两张表
-- 班级表
create table class(
id int primary key auto_increment,
name varchar(20)
);
-- 学生表
create table student(
id int primary key auto_increment,
name varchar(20),
classId int
);
每一个同学肯定是属于一个班级的,我们向往班级表中插入一些数据
insert into class values
(null ,'java1班'),
(null ,'java2班'),
(null ,'java3班'),
(null ,'java4班');
下面我们可以假设这样一个场景,有一名同学叫做 李白,在 java1班学习,我们可以这么记录
insert into student values (null,'李白',1); -- java1班 的id 是1
上面的情况很正常,但要是我们下面这么插入数据.
insert into student values (null,'杜甫',100);
我们没有id 是100的班级,但是我们也成功插入了,这就和实际产生了差异,这就引出了外键约束。外键很简单,要是两张表有联系就可以使用外键约束
正确使用外键
我们向把班级表和学生表删除,重新创建.不过在之前,我们先来提一个结论.我们喜欢把班级表这种叫做父表,学生表叫做子表.
drop tables class,student; -- 这里语法支持的
我们这里重新创建一下班级表,这里后面在解释.
-- 创建班级表 不变
create table class(
id int primary key auto_increment,
name varchar(20)
);
-- 添加数据
insert into class values
(null ,'java1班'),
(null ,'java2班'),
(null ,'java3班'),
(null ,'java4班');
创捷学生表就比较麻烦了,主要是外键的创建有些麻烦,我们先列出格式
foreign key(本表的字段) references 其他表的表名(其他表的表名的字段) -- ()号是存在的
create table student(
id int primary key auto_increment,
name varchar(20),
classId int,
foreign key(classId) references class(id) -- 解释这句话 我们定义一个外键,是classId,链接 class表中的 id 字段
);
当我们开始插入数据后,MySQL会自动帮助我们进行校验,我们来几次
insert into student values
(null,'李白',1),
(null,'刘备',2),
(null,'曹操',3),
(null,'杜甫',3);
但我们插入class中不存在的id时,出现错误.这是由于在班级表中找不到id为10的班级,所以不能插入成功.
insert into student values (null,'错误',10);
外键约束的缺陷
我们使用外键会有一些小问题的。
- 效率有些低,我们插入数据时要查询另一张表的数据,索引中我们会提高效率
- 不太能删除被关联的表,下面我用代码表示一下
这里我们解释一下第二个,一旦我们把班级表给删除掉,你就会发现自己不能这么做.原因就是这个表被一个表依附
drop table class;
那么我们对于班级表中的数据可以删除吗?这里要分情况.如果学生表的数据依赖了你要删除的数据,这就不能删,反之可以删.
我们在想不是可以这么想,如果学生表中没有数据,班级表可以删吗?抱歉,不能.
这里我们就有疑惑了,我们知道淘宝商城.对于商城而言,肯定存在一张表来存放商品的id,每一个用户的购物车都存在一张购物表.这个表应该存在一个外键来连接商城表的商品的id.那么我们在想,有的时候商品会下架,那么你的购物车中就会显示这个商品已经没有了.这是怎么做到的,好象不符合我们上面谈到的.
实际上,这种删除不是真正的删除,而是逻辑意义上的,商品表中存在一个isOK的列,商品存在就是1,下架就是0.这就是我们的解决办法有的人可能会感到疑惑,那么这张商品表不是越来越大吗,是的,但是我们要记住,现在硬盘不值钱,所以数据多了也没事.