mysql-210713-01
- 约束
- 什么是约束
- 常见约束
- 非空约束(not null)
- 唯一性约束(unique)
- 主键约束(primary key)
- 外键约束(foreign key)
约束
什么是约束
在创建表的时候,可以给表的字段添加相应的约束,
添加约束的目的是为了保证表中数据的合法性,有效性,完整性。
常见的约束
非空约束 (not null) 约束的字段不能为NULL
唯一约束 (unique) 约束的字段不能重复
主键约束 (primary key) 约束的字段既不能为NULL,也不能重复 (简称PK)
外键约束 (foreign key) ...... (简称FK)
检查约束 (check) 注意:Oracle数据库中有check约束,但是mysql没有,目前mysql不支持该约束
非空约束(not null)
非空约束(not null) 字段的值不能为空(NULL)
案例1
drop table if exists t_user;
create table t_user(
id int,
username varchar(255) not null, // 列级约束
password varchar(255)
);
insert into t_user(id,username,password) values (1,'','123');
insert into t_user(id,username,password) values (2,'bgy','123');
// 错误
mysql> insert into t_user(id,password) values (2,'222');
ERROR 1364 (HY000): Field 'username' doesn't have a default value
唯一性约束(unique)
唯一性约束(unique)修饰的字段具有唯一性,字段值不能重复,但可以为空(NULL)
当表中只有一个唯一性约束的时候 也叫 列级约束 (案例1)
当表中只有多个唯一性约束的时候 也叫 表级约束 (案例2)
案例1(一个字段加unique)
// 列级约束
drop table if exists t_user;
create table t_user(
uno int,
uname varchar(255) unique // 列级约束
);
mysql> insert into t_user(uno,uname) values (1001,'bgy1001');
Query OK, 1 row affected (0.01 sec)
// 值可以为空
mysql> insert into t_user(uno) values(1002);
Query OK, 1 row affected (0.01 sec)
// 值不允许重复
mysql> insert into t_user(uno,uname) values(1003,'bgy1001');
ERROR 1062 (23000): Duplicate entry 'bgy1001' for key 't_user.uname'
案例2(多个字段加unique)
// 表级约束
drop table if exists t_user;
create table t_user(
uno int,
uname varchar(255),
upassword varchar(255),
unique(uname,upassword) // 多个字段联合起来添加一个约束unique【表级约束】
);
insert into t_user values(1001,'bgy01','bgy01');
insert into t_user values(1002,'bgy01','bgy02');
insert into t_user values(1003,'bgy03','bgy01');
mysql> select * from t_user;
+------+-------+-----------+
| uno | uname | upassword |
+------+-------+-----------+
| 1001 | bgy01 | bgy01 |
| 1002 | bgy01 | bgy02 |
| 1003 | bgy03 | bgy01 |
+------+-------+-----------+
3 rows in set (0.00 sec)
// 表级约束
// 这是添加两个约束
drop table if exists t_user;
create table t_user(
uno int,
uname varchar(255) unique,
upassword varchar(255) unique
);
mysql> insert into t_user values(1001,'bgy01','bgy01');
Query OK, 1 row affected (0.01 sec)
mysql> insert into t_user values(1002,'bgy01','bgy02');
ERROR 1062 (23000): Duplicate entry 'bgy01' for key 't_user.uname'
主键约束(primary key)
主键约束(primary key) 中的字段不能为NULL,也不能为空
一张表 主键约束(primary) 只能有一个
主键作用
表的三范式中要求,第一范式中要求任何一张表中都应该有主键
主键作用:
主键是这行记录在这张表中的唯一标识。
两个人,同年同月同日生,相同地区,,,就靠身份证号来区分(主键)
主键分类
根据主键字段的字段数量划分:
单一主键:
推荐,常用
复合主键:
多个字段联合起来添加一个主键约束,
不推荐,复合主键违背三范式。
分局主键性质划分:
自然主键:
主键最好是一个和业务没有任何关系的自然数,
推荐使用。
业务主键:
主键和业务有关系,
例如:身份证号做主键,银行卡号做主键,
不推荐使用,
因为以后的业务如果发生改变,主键值也可能需要随着发生变化,
但有时候没有办法改变,因为变化可能会导致主键值的重复。
案例1(行级约束)
// 行级约束
drop table if exists t_user;
create table t_user(
uno int primary key,
uname varchar(255),
ubirth varchar(10)
);
insert into t_user(uno,uname,ubirth) values(1001,'bgy01','1999-09-09');
insert into t_user(uno,uname,ubirth) values(1002,'bgy01','1999-09-09');
mysql> select * from t_user;
+------+-------+------------+
| uno | uname | ubirth |
+------+-------+------------+
| 1001 | bgy01 | 1999-09-09 |
| 1002 | bgy01 | 1999-09-09 |
+------+-------+------------+
mysql> insert into t_user(uno,uname,ubirth) values(1002,'bgy01','1999-09-09');
ERROR 1062 (23000): Duplicate entry '1002' for key 't_user.PRIMARY'
案例2(表级约束)
// 表级约束
drop table if exists t_user;
create table t_user(
uno int,
uname varchar(255),
ubirth varchar(10),
primary key(uno)
);
案例3(复合主键)
// 复合主键
// 意思就是,uno和uname联合起来不能为空,也不能相同
drop table if exists t_user;
create table t_user(
uno int,
uname varchar(255),
ubirth varchar(10),
primary key(uno,uname)
);
案例4(主键值自增)
uno int primary key auto_increment,
uno字段自动维护一个自增数字,从1开始,以1递增
Oracle数据库中也提供了一个自增机制,
叫:序列(sequence)对象
drop table if exists t_user;
create table t_user(
uno int primary key auto_increment,
uname varchar(255),
ubirth varchar(10)
);
外键约束(foreign key)
外键约束:foreign key
foreign key(classno) references t_class(cno),
先创建父表,再创建子表,
先插入父表数据,再插入子表数据,
先删除子表数据,再删除父表数据,
先删除子表,再删除父表。
外键值可以为NULL。
外键引用字段不一定要使用主键,但是引用字段至少具有 唯一性。
案例1
两张表,
一张学生表 t_student
sno,sname,classno
一张班级表 t_class
cno cname
t_student中的cno字段 引用t_class中的cno字段,
此时t_student表叫做子表,t_class表叫做父表,
先创建父表,再创建子表,
先插入父表数据,再插入子表数据,
先删除子表数据,再删除父表数据,
先删除子表,再删除父表。
// 先删除子表,再删除父表。
drop table if exists t_student;
drop table if exists t_class;
// 先创建父表,再创建子表,
create table t_class(
cno int,
cname varchar(255),
primary key(cno)
);
create table t_student(
sno int,
sname varchar(255),
classno int,
primary key(sno),
foreign key(classno) references t_class(cno)
);
// 先插入父表数据
insert into t_class values(101,"G0301");
insert into t_class values(102,"G0302");
// 再插入子表数据
insert into t_student values(2001,'bgy',101);
insert into t_student values(2002,'laoli',102);
insert into t_student values(2003,'xiaowu',102);
select * from t_student;
select * from t_class;
结果如下↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
mysql> select * from t_student;
+------+--------+---------+
| sno | sname | classno |
+------+--------+---------+
| 2001 | bgy | 101 |
| 2002 | laoli | 102 |
| 2003 | xiaowu | 102 |
+------+--------+---------+
3 rows in set (0.00 sec)
mysql> select * from t_class;
+-----+-------+
| cno | cname |
+-----+-------+
| 101 | G0301 |
| 102 | G0302 |
+-----+-------+
2 rows in set (0.00 sec)
// 因为t_class中没有555这个数据
mysql> insert into t_student values(2004,'xiaowang',555);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`mysql_test_210711_01`.`t_student`, CONSTRAINT `t_student_ibfk_1` FOREIGN KEY (`classno`) REFERENCES `t_class` (`cno`))