一.约束(constraint)
1.什么是约束
在创建表的时候,我们可以给表中的字段加上一些约束,来保证这个表中数据的完整性,有效性。
约束的作用就是为了保证表中的数据有效。
2.约束包括哪些
- 非空约束:not null
- 唯一性约束:unique
- 主键约束:primary key(简称PK)
- 外键约束:foreign key(简称FK)
- 检查约束:check(mysql不支持,oracle支持)
我们这里重点学习四个约束:
- not null
- unique
- primary key
- foreign key
3.非空约束 : not null
非空约束约束的字段不能为NULL。
- 第一步:
drop table if exists t_vip;
- 第二步:
create table t_vip( id int, name varchar(255) not null );
- 第三步:
insert into t_vip(id,name) values(1,'zhangsan');//正确
insert into t_vip(id,name) values(2,'lisi');//正确
insert into t_vip(id) values(3);//报错
实际工作技巧:
XXXX.sql这种文件被称为sql脚本文件,脚本文件中编写了大量的sql语句,我们在执行sql脚本文件的时候可以使用sql脚本文件,在mysql当中怎么执行sql脚本呢?
mysql> source D:\course\03-MYSQL\document\vip.sql
4.唯一性约束 : unique
唯一性约束约束的字段不能重复,但是可以为NULL。
- 第一步:
drop table if exists t_vip;
- 第二步:
create table t_vip(
id int,
name varchar(255) unique,
email varchar(255)
);
- 第三步:
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');//正确
insert into t_vip(id,name,email) values(2,'lisi','lisi@123.com');//正确
insert into t_vip(id,name,email) values(3,'wangwu','wangwu@123.com');//正确
insert into t_vip(id,name,email) values(4,'wangwu','wangwu@123.com');//错误
insert into t_vip(id) values(4);//正确
insert into t_vip(id) values(5);//正确
- 第四步:
select * from t_vip;
| id | name | email |
| 1 | zhangsan| zhangsan@123.com |
| 2 | lisi | lisi@123.com |
| 3 | wangwu | wangwu@123.com |
| 4 | NULL | NULL |
| 5 | NULL | NULL |
name虽然被unique约束了,但是可以为NULL。
新需求:name和email两个字段联合起来具有唯一性!!!
错误做法:
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) unique,
email varchar(255) unique
);
这样操作表示name和email各自唯一。
正确做法:
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255),
email varchar(255),
unique(name,email)
);
注意:约束直接添加在列后面被称为列级约束,约束没有田间在列的后面,这种约束被称为表级约束,需要给多个字段联合起来添加某一个约束的时候,需要使用表级约束。
5.not null和unique联合
- 第一步:
drop table id exists t_vip;
第二步:create table t_vip(
id int,
name varchar(255) not null unique
);
第三步:desc t_vip;
| field | type | null | key | default | extra |
| id | int(11) | YES | | NULL | |
| name | varchar(255) | NO | PRI | NULL | |
**注意:在mysql当中,如果一个字段同时被not null和unique约束的话,该字段自动变成主键字段。(注意:oracle当中不一样!)**
第四步:insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'zhangsan');//错误,name不能重复
insert into t_vip(id,name) values(2);//错误,name不能为NULL
6.主键约束(primary key,简称PK) 非常重要,五颗星*****
(1).主键约束的相关术语?
主键约束:就是一种约束。
主键字段:被添加主键约束的字段。
主键值:主键字段中的每一个值。
(2).什么是主键?有什么用?
主键值是每一行记录的唯一标识,在实际的开发中,很可能会有几条完全相同的记录,主键值相当于它们的身份证号,可以区分这些记录。
任何一张表都应该有主键,没有主键,表无效!!!
**主键的特征:not null + unique (主键值不能是NULL,同时也不能重复)**
(3).怎么给一张表添加主键约束呢?列级约束
第一步:drop table if exists t_vip;
第二步:create table t_vip(
id int primary key,
name varchar(255)
);
第三步: insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'lisi');
insert into t_vip(id,name) values(2,'wangwu');//错误,不能重复
insert into t_vip(id,name) values('zhaosi');//错误,不能为NULL
(4).可以使用表级约束添加主键吗?
第一步:drop table if exists t_vip;
第二步:create table t_vip(
id int,
name varchar(255),
primary key(id)//表级约束
);
第三步: insert into t_vip(id,name) values(1,'zhangsan');
(5).表级约束主要是给多个字段联合起来添加约束?
第一步:drop table if exists t_vip;
第二步:create table t_vip(
id int,
name varchar(255),
email varchar(255),
primary key(id,name)//表级约束
);
第三步: insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(1,'lisi','lisi@123.com');//正确
insert into t_vip(id,name,email) values(1,'lisi','wangwu@123.com');//错误,不能重复
在实际开发中不建议使用复合主键,建议使用单一主键!
因为主键值存在的意义就是这行记录的身份证号,只要意义达到即可,单一主键可以做到,复合主键比较复杂,不建议使用!!
(6).一个表主键约束能加两个吗?
第一步:drop table if exists t_vip;
第二步:create table t_vip(
id int primary key,
name varchar(255) primary key
);//错误,主键重复定义
结论:一张表,主键约束只能添加一个,主键只能有一个。
(7).主键值建议使用:
int
bigint
char 等类型。不建议使用varchar来做主键,因为主键值一般是定长的。
(8).主键除了:单一主键和复合主键之外,还可以这样进行分类
自然主键:主键值是一个自然数,和业务没关系。
业务主键:主键值和业务紧密关联,例如拿银行卡账号做主键值,这就是业务主键。
在实际开发中使用自然主键比较多,因为主键只要做到不重复就行,不需要有意义。业务主键不好,业务主键一旦和业务挂钩,那么业务变动时可能会影响主键值,所以业务主键不建议使用,尽量使用自然主键。
(9).在mysql中,有一种机制,可以帮助我们自动维护一个主键值:auto_increment表示自增,从1开始,以1递增。
第一步:drop table if exists t_vip;
第二步:create table t_vip(
id int primary key auto_increment,
name varchar(255)
);
第三步: insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
第四步:select * from t_vip;
| id | name |
| 1 | zhangsan |
| 2 | zhangsan |
| 3 | zhangsan |
| 4 | zhangsan |
7.外键约束(foreign key,简称FK) 非常重要,五颗星*****
(1). 外键约束的相关术语?
外键约束:就是一种约束。
外键字段:被添加主键约束的字段。
外键值:主键字段中的每一个值。
业务背景:请设计数据库表,来描述”班级和学生“的信息
方案一:班级和学生存储在一张表中
| no(pk) | name | cno | classname |
| 1 | jack | 100 | 北京市大兴区亦庄镇第二中学高三1班 |
| 2 | lucky | 100 | 北京市大兴区亦庄镇第二中学高三1班 |
| 3 | lilei | 100 | 北京市大兴区亦庄镇第二中学高三1班 |
| 4 | hanmeimei | 101 | 北京市大兴区亦庄镇第二中学高三1班 |
| 5 | zhangsan | 101 | 北京市大兴区亦庄镇第二中学高三2班 |
| 6 | lisi | 100 | 北京市大兴区亦庄镇第二中学高三2班 |
| 7 | wangwu | 101 | 北京市大兴区亦庄镇第二中学高三2班 |
| 8 | zhaoliu | 101 | 北京市大兴区亦庄镇第二中学高三2班 |
分析以上方案的缺点:数据冗余,空间浪费,这个设计是比较失败的!!!
方案二:班级一张表,学生一张表
t_class 班级表
|classno(pk)| classname |
|100 | 北京市大兴区亦庄镇第二中学高三1班 |
|101 | 北京市大兴区亦庄镇第二中学高三1班 |
t_student学生表
| no(pk) | name | cno |(FK引用t_class这张表的classno)
| 1 | jack | 100 |
| 2 | lucky | 100 |
| 3 | lilei | 100 |
| 4 | hanmeimei | 100 |
| 5 | zhangsan | 101 |
| 6 | lisi | 101 |
| 7 | wangwu | 101 |
| 8 | zhaoliu | 101 |
当cno字段没有任何约束的时候,可能会导致数据无效。当t_student中cno出现一个102(即学生表里的学生不是所存在班级的),所以为了保证cno字段中的值都是100和101,需要给cno字段添加外键约束。
那么:cno字段就是外键字段,cno字段中的每一个值都是外键值。
注意:
第一步:
drop table if exists t_student;
drop table if exists t_class;
第二步:
create table t_class(
classno int primary key,
classname varchar(255)
);
create table t_student(
no int primary key auto increment,
name varchar(255),
cno int,
foreign key(cno) references t_class(classno)
);
第三步:
insert into t_class(classno,classname) values(100,'北京市大兴区亦庄镇第二中学高三1班');
insert into t_class(classno,classname) values(101,'北京市大兴区亦庄镇第二中学高三1班');
insert into t_student(name,cno) values('jack',100);
insert into t_student(name,cno) values(lucy',100);
insert into t_student(name,cno) values('lilei',100);
insert into t_student(name,cno) values('hanmeimei',100);
insert into t_student(name,cno) values('zhangsan',1001);
insert into t_student(name,cno) values('lisi',101);
insert into t_student(name,cno) values('wangwu',101);
insert into t_student(name,cno) values('zhaoliu',101);
**注意:t_class是父表,t_student是子表
删除表的顺序是:先删子,再删父
创建表的顺序是:先创父,再创子
删除数据的顺序:先删子,再删父
插入数据的顺序:先插入父,再插入子
!!重点!!:子表中的外键引用父表中的某个字段,被引用的这个字段不一定是主键,但至少具有unique约束!!!!
说明:外键值可以为NULL。**
```