首先我们来想象一下,前几篇文章在我们操作数据库的过程中,自由度是很高的,想给哪个赋值就给哪个赋值,但是这样子,就会造成我们所创建的数据库数据不完整,例如我创建一个学生信息表,你可能添加时候忘了添加学号、忘了添加名字、忘了添加成绩等等,因此我们就需要利用约束来创建我们的表,对表中的数据进行限定,保证数据的正确性、有效性和完整性
1. 非空约束
非空约束顾名思义就是约束它不能为空,也就是必填项,其所使用的关键字是NOT NULL
,关于该非空约束有三种操作,为方便讲解,以下的语句均是对bound1表中的NAME项进行操作:
- 创建表时添加非空约束:
CREATE TABLE bound1(id INT,NAME VARCHAR(8) NOT NULL);
- 创建常规表后再添加非空约束:
ALTER TABLE bound1 MODIFY NAME VARCHAR(8) NOT NULL;
- 删除非空约束:
ALTER TABLE bound1 MODIFY NAME VARCHAR(8);
下面来操作一下,这里先新建一个表,添加一个数据看看
CREATE TABLE bound1(id INT,NAME VARCHAR(8) NOT NULL);
INSERT INTO bound1(id,NAME) VALUES(1,"amy");
SELECT * FROM bound1;
ok,这项数据是可以成功添加的,那么下面我们来添加一下只有id的项看看是否能够成功
INSERT INTO bound1(id) VALUES(2);
显然是不行的,我们可以把非空约束删掉再试一次
ALTER TABLE bound1 MODIFY NAME VARCHAR(8);
INSERT INTO bound1(id) VALUES(2);
SELECT * FROM bound1;
去掉非空约束后便可以正常添加了,如果,此时你又想把非空约束加回去行不行呢?我们来试试
ALTER TABLE bound1 MODIFY NAME VARCHAR(8) NOT NULL;
咦,怎么不行?语句错了吗?其实没有,出现该问题的原因是你的表中的NAME项已经有一个NULL值存在,不符合非空约束,因此需要把该项删除才能成功添加非空约束
换言之,添加约束的前提是该表中对应的数据需要符合该约束,随后介绍的约束也是如此
2. 唯一约束
唯一约束,同样也是字面意思,用于约束该项的值不与已存在的值重复,更贴近生活的例子是学生的学号、自然人的身份证号、机动车号牌等,同样的,该约束也是有三种操作,以下的语句均是对bound2表中的id项进行操作:
- 创建表时添加唯一约束:
CREATE TABLE bound2(id INT UNIQUE,NAME VARCHAR(8));
- 创建常规表后再添加唯一约束:
ALTER TABLE bound2 MODIFY id INT UNIQUE;
- 删除唯一约束:
ALTER TABLE bound2 DROP INDEX id;
看到删除唯一约束时可能有同学会参考上一节中的删除非空约束想用MODIFY
进行修改,但其实删除唯一约束用MODIFY
是不行的,必须使用这里所介绍的DROP
国际惯例,还是来操作一下,这里先新建一个表,添加一个数据看看
CREATE TABLE bound2(id INT UNIQUE,NAME VARCHAR(8));
INSERT INTO bound2(id,NAME) VALUES(1,"amy");
SELECT * FROM bound2;
下面再给他添加一个重复的id看看可不可以
INSERT INTO bound2(id,NAME) VALUES(1,"john");
结果你肯定也猜到是不行的,另外约束的删除和新增的效果和步骤跟上一节一样,这里不再重复演示了
3. 主键约束
什么叫主键约束呢?主键约束的精粹在于“主”,正所谓一山不能容二虎,既然是“主”,那就必须是“唯一”的,另外,“主”的位置也是不可或缺的,因此也必须是“非空”的,那么综上所述,主键约束的含义就是非空且唯一,同样的,该约束也是有三种操作,以下的语句均是对bound3表中的id项进行操作:
- 创建表时添加主键约束:
CREATE TABLE bound3(id INT PRIMARY KEY,NAME VARCHAR(8));
- 创建常规表后再添加主键约束:
ALTER TABLE bound3 MODIFY id INT PRIMARY KEY;
- 删除主键约束:
ALTER TABLE bound3 DROP PRIMARY KEY;-- 去除主键约束后其还是非空约束
ALTER TABLE bound3 MODIFY id INT;-- 因此需要再次去除非空约束
是不是感觉这个删除又有点特别?对,就是这么特别,它需要执行两条语句才能把主键约束的项变成普通项,若只执行第一条语句它只会把主键约束变成非空约束
好啦,下面来操作一下吧,这里先新建一个表,添加一个数据看看
CREATE TABLE bound3(id INT PRIMARY KEY,NAME VARCHAR(8));
INSERT INTO bound3(id,NAME) VALUES(1,"amy");
SELECT * FROM bound3;
没毛病,那下面再来添加一个重复id,一个空id的项看看是否能够成功
INSERT INTO bound3(id,NAME) VALUES(1,"john");
INSERT INTO bound3(NAME) VALUES("kc");
显然都是不行的,一个提示为不能重复,一个提示为不能为空,下面再来体验一下这个特别的删除,这里先执行前面介绍的第一条删除语句
ALTER TABLE bound3 DROP PRIMARY KEY;
然后添加一个重复id的项看看
INSERT INTO bound3(id,NAME) VALUES(1,"john");
SELECT * FROM bound3;
显然添加成功了,下面再来看看添加一个空id项
INSERT INTO bound3(NAME) VALUES("kc");
这报错就来了,因此这就是我前面所说的,第一条删除语句只把主键约束变成了非空约束,若需要变成普通项,则还需要执行第二条语句
ALTER TABLE bound3 MODIFY id INT;
再添加那个空id数据试试看
INSERT INTO bound3(NAME) VALUES("kc");
SELECT * FROM bound3;
这时候就可以成功添加了,同样的,若此时想重新添加主键约束,必须要把表中重复的与空的项删除才可以
自动增长
自动增长是针对主键约束中为数值类型的列服务的,有什么情况下需要用到自动增长呢?例如学生的学号,我们都知道学号是有规律增长的,因此我们可以使用AUTO_INCREMENT
关键字实现该值的自动增长,该操作同样有三种,以下的语句均是对bound4表中的id项进行操作:
- 创建表时添加主键约束并且添加自动增长:
CREATE TABLE bound4(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(8));
- 创建主键约束表后再添加自动增长:
ALTER TABLE bound4 MODIFY id INT AUTO_INCREMENT;
- 删除自动增长:
ALTER TABLE bound4 MODIFY id INT;
注意,删除自动增长语句仅取消了自动增长,其仍然是主键约束,接下来还是演示时间,这里先新建一个表,添加一个数据看看
CREATE TABLE bound4(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(8));
INSERT INTO bound4(id,NAME) VALUES(1,"amy");
SELECT * FROM bound4;
下面来添加一个空id项看看能不能实现自动增长
INSERT INTO bound4(NAME) VALUES("kc");
SELECT * FROM bound4;
显然我们的id没有赋值,但它可以实现自动增长赋值,下面我来接连添加两条数据,一个给id赋值,一个不给id赋值,那么你感觉不给id赋值的会跟着哪个数值实现自动增长呢?
INSERT INTO bound4(id,NAME) VALUES(5,"john");
INSERT INTO bound4(NAME) VALUES("jam");
你觉得自动增长的一项是6还是跟回之前的数字是3呢?下面来揭开谜底
显然是跟着最后的一项数值实现自动增长的
4. 外键约束
外键约束就没有前面几项约束理解起来那么简单了,但也不要怕,还是挺容易明白的,首先我们来看一个数据表
你会发现,这里研发部都在广州,销售部都在深圳,那么两项都写出来,显得这个数据库都有点繁杂,即有冗余的部分,有没有办法可以解决呢?有的,我们可以把它分开两个表,一个储存人员信息与部门代号,一个储存部门的详细信息,同时也要让他们之间产生关联
为什么要产生关联呢?例如举一个简单的例子,假如我公司只有两个部门,代号分别是1和2,但是你在添加人员信息时候写错了部门代号为5,这样子就会添加了错误的数据,那么产生关联后有什么作用呢?假如你让两个表产生了关联,那么当你添加错误代号时候就会报错提醒你不能成功添加
总的来说,外键约束就是让表与表之间产生关系,从而保证数据的正确性,同样的,其相关操作也是三种:
- 创建表时添加外键约束:
CREATE TABLE 表名(列名1 数据类型1, 列名2 数据类型2, ... , 列名n 数据类型n, CONSTRAINT 外键名称 FOREIGN KEY(副表列名) REFERENCES 主表名(主表列名));
- 创建普通表后再添加外键约束:
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY(副表列名) REFERENCES 主表名(主表列名);
- 删除外键约束:
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
注意:
- 要分清楚上面所提到的主表和副表,副一定是受到主的限制的,副表主表之间也是如此,还是以员工表和部门表为例子,一定是先有部门才有员工归属到这个部门,因此,员工表是副表,部门表是主表,再直白一点说,以上三条语句的都是副表上进行操作的
- 语句中的外键名称,其实就是你给这个副表与主表的关系起个名,你喜欢起什么名字都行,记住就好
搞清楚之后,我们来新建一个,bound5是部门表(主表),bound6是员工表(副表),添加一下数据
CREATE TABLE bound5(id INT PRIMARY KEY AUTO_INCREMENT,department VARCHAR(8),city VARCHAR(8));
CREATE TABLE bound6(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(8),department INT,CONSTRAINT 5and6 FOREIGN KEY (department) REFERENCES bound5(id));
INSERT INTO bound5(department,city) VALUES("研发部","广州"),("销售部","深圳");
INSERT INTO bound6(NAME,department) VALUES("张三",1),("李四",2),("王五",1),("赵六",1),("田七",2),("何八",2);
然后分别来看看两个表
对了,教你一种方法看看有没有成功添加外键约束
好啦,那我们前面所说的约束作用怎么体现出来呢?注意看,部门表中只有两个部门,编号是1和2,那么下面我们往员工表上添加两个部门编号为5的员工信息看看能不能成功
INSERT INTO bound6(NAME,department) VALUES("吴九",5),("陈十",5);
显然是不可以的,那么如果我在部门表加上编号为5的部门之后再试试呢?
INSERT INTO bound5(id,department,city) VALUES(5,"人事部","上海");
INSERT INTO bound6(NAME,department) VALUES("吴九",5),("陈十",5);
毫无意外地添加成功了,那这时候集团老板觉得这个部门编号太跳脱了,应该改回3,可不可以呢?
UPDATE bound5 SET id=3 WHERE id=5;
对不起,不可以,这是为啥呢?因为关联了呀,要是你改了编号,我那些写着部门编号是5的员工不就不属于任何部门了吗?那我裁掉这个部门总行了吧,试试看
DELETE FROM bound5 WHERE id=5;
怎么还是不行?同样道理嘛,部门裁掉之后员工也是无家可归了呀,不过别担心,还有高级操作可以让两个表产生联动,下面来看看级联操作
级联操作
级联操作,说白了就是来解决刚才说到的两个痛点的,级联操作可以实现同步更新或同步删除,它的语法也很简单,ON UPDATE CASCADE
表示同步更新,ON DELETE CASCADE
表示同步删除,需要哪个就写哪个,下面来看一下:
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY(副表列名) REFERENCES 主表名(主表列名) ON UPDATE CASCADE ON DELETE CASCADE;
让我们来添加级联操作再看看刚刚的更改部门编号能否成功
ALTER TABLE bound6 ADD CONSTRAINT 5and6 FOREIGN KEY (department) REFERENCES bound5(id) ON UPDATE CASCADE ON DELETE CASCADE;
UPDATE bound5 SET id=3 WHERE id=5;
显然更改了部门表后员工表也自动同步更改了,那么删除操作是怎么样的呢?再来试试看
DELETE FROM bound5 WHERE id=3;
显然部门表中的部门被删除了,员工表中的相关员工也被自动删除了,即使级联操作可以给我们带来便利,但是在不是非常确定表表之间产生的连带关系的时候,我们还是要谨慎操作这一特性
至此,约束的相关内容也全部介绍完啦,下篇文章中将会介绍多表关系