MySQL约束 主键约束丨唯一约束丨非空约束丨外键级联
Posted 南有乔木i
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL约束 主键约束丨唯一约束丨非空约束丨外键级联相关的知识,希望对你有一定的参考价值。
约束是作用于表中字段上的规则,用于限制存储在表中的数据。保证数据库中数据的正确、有效性和完整性。
关键字 | 约束 | 描述 |
---|---|---|
not null | 非空约束 | 限制该字段的数据不能为null |
unique | 唯一约束 | 保证该字段的所有数据都是唯一、不重复的 |
primary key | 主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 |
default | 默认约束 | 保存数据时,如果未指定该字段的值,则采用默认值 |
check | 检查约束 (8.0.16版本之后) | 保证字段值满足某一个条件 |
foreign key | 外键约束 | 用来让两张表的数据之间建立连接,保证数据的一致性和完整性 |
unsigned | 无符号 | 只能是0或正整数 |
auto_increment | 自动增长 | 字段类型必须是整数类型 |
约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束。
主键约束
用来唯一标识数据库中的每一条记录,通常不用业务字段作为主键,单独给每张表设计一个 id 的字段,把 id 作为主键。主键是给数据库和程序使用的,不是给最终的客户使用的。所以主键有没有含义没有关系,只要不重复,非空就行。
- 主键约束要求字段的值在全表必须唯一,而且不能为null值。
- 建议主键使用数字类型,因为数字的检索速度非常快,而且还可以设置自增长。
关键字 | 描述 |
---|---|
primary key | 字段值唯一,且不能为null |
auto_increment | 表示自动增长(字段类型必须是整数类型) |
unsigned | 无符号 |
字段名 字段类型 primary key
:在创建表的时候给字段添加主键alter table 表名 add primary key(字段名);
:在已有表中添加主键caeate table 表名(列名 int primary key auto_increment) auto_increment=起始值;
:修改自增长的默认值起始值alter table 表名 auto_increment=起始值;
:创建好以后修改起始值
delete 和 truncate 对自增长的影响:
- delete:删除所有的记录之后,自增长没有影响。
- truncate:删除以后,自增长又重新开始。
-- 创建表学生表 st5, 包含字段(id, name, age)将 id 做为主键
create table st5 (
id int primary key, -- id 为主键
name varchar(20),
age int
)
desc st5;
-- 删除 st5 表的主键
alter table st5 drop primary key;
-- 添加主键
alter table st5 add primary key(id);
-- AUTO_INCREMENT 的默认开始值是 1,修改起始值
-- 指定起始值为 1000
create table st4 (
id int primary key auto_increment,
name varchar(20)
) auto_increment = 1000;
-- 创建好以后修改起始值
alter table st4 auto_increment = 2000;
-- 创建t_teacher表,主键是整数无符号类型,并且自增长
create table t_teacher(
id int unsigned primary key auto_increment,
name varchar(20) not null,
tel char(11) not null unique
);
唯一约束
- 唯一约束要求字段值如果不为null,那么在全表必须唯一。
关键字 | 描述 |
---|---|
unique | 字段值唯一,且可以为null |
字段名 字段类型 unique
:表中某一列不能出现重复的值alter table 表名 drop index 字段名;
:删除唯一约束
-- 创建学生表 st7, 包含字段(id, name),name 这一列设置唯一约束
create table st7 (
id int,
name varchar(20) unique
)
非空约束
- 非空约束要求字段的值不能为null值
- null值是没有值,而不是""空字符串
关键字 | 描述 |
---|---|
not null | 字段值不能为null |
default | 默认值 |
字段名 字段类型 not null
:某一列不能为 null字段名 字段类型 default 默认值
:不传参数的话,指定一个默认值
如果字段设置了非空与唯一约束,该字段与主键的区别:
- 主键在一个表中,只能有一个。不能出现多个主键。主键可以单列,也可以是多列。
- 自增长只能用在主键上。
-- 创建表学生表 st8, 包含字段(id,name,gender)其中 name 不能为 NULL
create table st8 (
id int,
name varchar(20) not null,
gender char(1)
)
-- 创建一个学生表 st9,包含字段(id,name,address), 地址默认值是广州
create table st9 (
id int,
name varchar(20),
address varchar(20) default '广州'
)
外键约束
外键约束用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性。
- 主表:一方,用来约束别人的表
- 从表:多方,被别人约束的表
关键字 | 描述 |
---|---|
foreign key | 保持关联数据的逻辑性 |
- 新建表时增加外键:
create table 表名(
字段名 数据类型 [约束],
...... ,
[constraint] [外键约束名称] foreign key(外键字段名) references 主表名(主键字段名)
);
- 已有表增加外键:
alter table 从表 add [constraint] [外键约束名称] foreign key (外键字段名) references 主表(主键字段名);
- 删除外键:
alter table 从表 drop foreign key 外键名称;
-- 创建从表 employee 并添加外键约束 emp_depid_fk
create table employee(
id int primary key auto_increment,
name varchar(20),
age int,
dep_id int, -- 外键对应主表的主键
-- 创建外键约束
constraint emp_depid_fk foreign key (dep_id) references department(id)
);
-- 删除 employee 表的 emp_depid_fk 外键
alter table employee drop foreign key emp_depid_fk;
-- 在 employee 表存在的情况下添加外键
alter table employee add constraint emp_depid_fk
foreign key (dep_id) references department(id);
外键级联
添加了外键之后,再删除父表数据时产生的约束行为,就称为删除/更新行为。具体的删除/更新行为有以下几种:
行为 | 说明 |
---|---|
no action | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。(与restrict一致) 默认行为。 |
restrict | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。 (与no action一致) 默认行为。 |
cascade | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有,则也删除/更新外键在子表中的记录。 |
set null | 当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(这就要求该外键允许取null)。 |
set default | 父表有变更时,子表将外键列设置成一个默认的值 (Innodb不支持)。 |
关键字 | 描述 |
---|---|
on update cascade | 级联更新,只能是创建表的时候创建级联关系。更新主表中的主键,从表中的外键列也自动同步更新 |
on delete cascade | 级联删除 |
- 在修改和删除主表的主键时,同时更新或删除副表的外键值,称为级联操作:
alter table 表名 add constraint 外键名称 foreign key (外键字段名称) references 主表名称(主表列名称) on update cascade / on delete cascade;
-- 创建 employee 表,添加级联更新和级联删除
create table employee(
id int primary key auto_increment,
name varchar(20),
age int,
dep_id int, -- 外键对应主表的主键
-- 创建外键约束
constraint emp_depid_fk foreign key (dep_id)
references department(id) on update cascade on delete cascade
)
-- 添加外键,并设置级联更新
ALTER TABLE employee ADD CONSTRAINT emp_dep_fk FOREIGN KEY ( dep_id ) REFERENCES department ( id ) ON UPDATE CASCADE;
-- 添加外键,并设置级联删除
ALTER TABLE employee ADD CONSTRAINT emp_dep_fk FOREIGN KEY ( dep_id ) REFERENCES department ( id ) ON DELETE CASCADE;
-- 添加外键,并设置级联更新并删除
ALTER TABLE employee ADD CONSTRAINT emp_dep_fk FOREIGN KEY ( dep_id ) REFERENCES department ( id ) ON UPDATE CASCADE ON DELETE CASCADE;
-- 删除或修改外键时,并把使用到该外键的修改为null
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on update set null on delete set null ;
「MySQL」- 约束详解
目录
约束的认识
约束是一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性 , MySQL数据库通过约束防止无效的数据进入到表中,以保护数据的实体完整性 , 在 MySQL 中一共分为以下几种约束类型
约束类型 | 说明 |
---|---|
not null | 指示某列不能存储 NULL 值。 |
unique | 保证某列的每行必须有唯一的值。 |
default | 规定没有给列赋值时的默认值 |
primary key | not null 和 unique 的结合。 确保某列或多个列的结合有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。 |
foreign key | 保证一个表中的数据匹配另一个表中的值的参照完整性 |
约束的应用场景一般分为以下两种
-
创建数据表的时候添加约束
create table <数据表名>(<列名1> <约束类型> , <列名2> <约束类型>,.......)
-
修改现有表的约束类型
-- 给现有数据表添加字段并设置约束条件 alter table <数据表名> add <字段名> <类型> <约束条件>; -- 修改现有数据表的约束条件 alter table <数据表名> modify <字段名> <类型> <约束条件>; -- alter table <数据表名> drop <约束名> <约束键名>;
非空约束 ( not null )
创建表时,可以指定某列添加非空约束 , 使其在添加数据时该列必须要添加有效的数据.
1.创建数据表添加非空约束
命令
create table <数据表名>(<列名> not null);
示例
在数据库中创建一张 student 数据表 , 并把 id 字段设置为非空约束
-- 重新设置学生表结构
drop table if exists student;
-- 创建 student 数据表
create table student (
id int not null,
sn int,
name varchar(20),
qq_mail varchar(20)
);
查看 student 表结构观察变化 , 可以看到 , 在 id 字段中的 Null 此时的状态是 NO , 意味着 , 在添加数据的时候 , id 字段不接受 null 值
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
如果在添加数据时 id 列为 null 或者不添加 id 列, 此时就会出现报错
-- 全列添加
mysql> insert into student values(null,2001,'张三','123@qq.com');
ERROR 1048 (23000): Column 'id' cannot be null
-- error : 列'id'不能为空
-- 指定列添加
mysql> insert into student(sn,name,qq_mail) values(2001,'张三','123@qq.com');
ERROR 1364 (HY000): Field 'id' doesn't have a default value
-- error : 字段id没有默认值
2.现有数据表添加非空约束
命令
alter table <数据表名> modify <字段名> <类型> not null;
示例
在现有 student 表中的 sn 字段添加非空约束
alter table student modify sn int not null;
查看表结构 , 可以看到 sn 字段中的 Null 选项的状态也变成了 NO
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| sn | int(11) | NO | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
3.删除非空约束
命令
alter table <数据表名> modify <字段名> <类型>;
示例
在现有 student 表中 , 删除 sn 字段的非空约束
alter table student modify sn int;
查看表结构 , 可以看到 sn 字段中的 Null 选项状态变回了 YES
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
唯一约束 ( unique )
在创建数据表时 , 可以指定某列添加唯一约束 , 使该列在添加数据时 , 不能添加重复的数据
1.创建表添加唯一约束
命令
create table <数据表名>(<列名> unique);
示例
在数据库中创建一张 student 数据表 , 并把 id 字段设置为唯一约束
-- 重新设置学生表结构
drop table if exists student;
-- 创建 student 数据表
create table student (
id int unique,
sn int,
name varchar(20),
qq_mail varchar(20)
);
查看 student 表结构观察变化 , 可以看到 , 在 id 字段中的 Key 此时的状态是 UNI ,代表当前 id 字段的值是唯一的 , 不接受重复值
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | YES | UNI | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
如果在添加数据时 , 添加 id 列的数据是重复的 , 那么就会报错
-- 第一次添加数据
insert into student values(1,2001,'张三','123@qq.com');
Query OK, 1 row affected (0.00 sec)
-- 第二次添加数据
insert into student values(1,2001,'张三','123@qq.com');
ERROR 1062 (23000): Duplicate entry '1' for key 'id'
-- error : 为键“id”复制项“1”
2.现有数据表添加非空约束
命令
-- 第一种方式
alter table <数据表名> add unique(<字段名>);
-- 第二种方式
alter table <数据表名> modify <字段名> <类型> unique;
示例
在现有 student 表中给 sn 字段添加唯一约束
alter table student add unique(sn);
上面这种添加方式也可以写成下面这种 , 效果一样
alter table student modify sn int unique;
查看 student 表结构 , 可以看到 sn 字段中的 Key 此时的状态变成了 UNI
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | YES | UNI | NULL | |
| sn | int(11) | YES | UNI | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
3.删除唯一约束
删除唯一约束的方法不一样 , 需要先在表中先找到该唯一约束的约束名称
命令
alter table <数据表名> drop index <约束名>;
查看约束对应的约束名称
show create table <数据表名>;
示例
删除 student 表中 sn 字段的唯一约束
-
先查看 student 表中所有约束信息 , 找到 sn 对应的约束名
student 表对应的以下两个约束 , `` 引起的就是约束名show create table student;
UNIQUE KEY `id` (`id`), UNIQUE KEY `sn` (`sn`)
-
使用对应的键名删除 student 表中唯一约束
alter table student drop index sn;
-
查看表结构 , 可以看到 sn 字段中的 Key 选项状态为空了
mysql> desc student; +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | id | int(11) | YES | UNI | NULL | | | sn | int(11) | YES | | NULL | | | name | varchar(20) | YES | | NULL | | | qq_mail | varchar(20) | YES | | NULL | | +---------+-------------+------+-----+---------+-------+ 4 rows in set (0.00 sec)
默认约束 ( default )
在创建数据表时 , 给指定字段添加默认约束并设置默认值 , 在添加记录时如果该列未指定值 , 就会按照默认值填充
1.创建表添加默认约束
命令
create table <数据表名>(<列名> <类型> default <默认值>);
示例
在数据库中创建一张 student 数据表 , 并把 name 字段设置默认值约束 , 默认值为 "未命名"
-- 重新设置学生表结构
drop table if exists student;
-- 创建 student 数据表
create table student (
id int,
sn int,
name varchar(20) default '未命名',
qq_mail varchar(20)
);
查看 student 表结构 , 可以看到 , 在 name 字段中的 Default 选项的值已经被更改成 未命名 了
mysql> desc student;
+---------+-------------+------+-----+-----------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+-----------+-------+
| id | int(11) | YES | | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | 未命名 | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+-----------+-------+
4 rows in set (0.00 sec)
添加数据不指定 name 列 , 则会填充默认值
-- 不指定 name 字段添加数据
insert into student(id,sn,qq_mail) values(1,2001,'123@qq.com');
-- 全列查询
mysql> select * from student;
+------+------+-----------+------------+
| id | sn | name | qq_mail |
+------+------+-----------+------------+
| 1 | 2001 | 未命名 | 123@qq.com |
+------+------+-----------+------------+
1 row in set (0.00 sec)
2.现有表中添加默认约束
命令
alter table <数据表名> alter <字段名> set default <默认值>;
示例
在现有 student 表中 , 给 qq_mail 字段添加默认值约束 , 默认值为 "未指定"
alter table student alter qq_mail set default '未指定';
查看 student 表结构观察 , qq_mail 字段中的 Default 选项的值已经被更改成 未指定 了
mysql> desc student;
+---------+-------------+------+-----+-----------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+-----------+-------+
| id | int(11) | YES | | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | 未命名 | |
| qq_mail | varchar(20) | YES | | 未指定 | |
+---------+-------------+------+-----+-----------+-------+
4 rows in set (0.00 sec)
3.删除默认约束
命令
alter table <数据表名> alter <字段名> drop default;
示例
删除 student 表中 name 字段的默认约束
alter table student alter name drop default;
查看 student 表结构 , 可以看到 name 字段中的 Default 选项的值已经返回为 null 了
mysql> desc student;
+---------+-------------+------+-----+-----------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+-----------+-------+
| id | int(11) | YES | | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | 未指定 | |
+---------+-------------+------+-----+-----------+-------+
4 rows in set (0.00 sec)
主键约束 ( primary key )
主键约束其实就是 非空约束 和 唯一约束的组合 , 给指定字段添加主键约束 , 在添加数据时 , 该列不能为空且不能重复 ,一张数据表中只能有一个主键 ! ! !
1.创建表添加主键约束
命令
create table <数据表名>(<列名> <类型> primary key);
示例
在数据库中创建一张 student 数据表 , 并把 id 字段设置主键约束
-- 重新设置学生表结构
drop table if exists student;
-- 创建 student 数据表
create table student (
id int primary key,
sn int,
name varchar(20),
qq_mail varchar(20)
);
查看 student 表结构 , 可以看到在 id 字段中的 key 选项的状态变成了 PRI 且 Null 选项状态为 NO , 这就是主键约束的效果
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
对 student 表添加数据不指定 id 列或者添加的 id 列的值重复或为 null 时将会报错
-- 第一次添加
insert into student values(1,2001,'张三','123@qq.com');
-- 添加成功
-- 第二次添加
insert into student values(1,2001,'张三','123@qq.com');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
-- error : 键“PRIMARY”的重复项“1”
-- 添加记录 , id 列为 null
insert into student values(null,2001,'张三','123@qq.com');
ERROR 1048 (23000): Column 'id' cannot be null
-- error : 列'id'不能为空
-- 不指定 id 列添加记录
insert into student(sn,name,qq_mail) values(2001,'张三','123@qq.com');
ERROR 1364 (HY000): Field 'id' doesn't have a default value
-- error : 字段id没有默认值
2.自增主键
实际开发中,往往有一系列的策略来保证 主键 不重复,最简单粗暴的做法,就是"自增主键",MySQL 内置了自增主键的功能 (在 primary key 后面加上 auto_increment ==> primary key auto_increment),此时在一列中就成了自增主键,用户插入数据的时候可以不必手动干预了,如果当前 id 列为自增主键,这个时候 id 列是可以为null的,为 null 表示由MySql的自增主键自动进行自增
命令
create table <数据表名>(<列名> <类型> primary key auto_increment);
示例
在数据库中创建一张 student 数据表 , 并把 id 字段设置主键约束 , 并添加自增主键
-- 重新设置学生表结构
drop table if exists student;
-- 创建 student 数据表
create table student (
id int primary key auto_increment,
sn int,
name varchar(20),
qq_mail varchar(20)
);
查看 student 表结构 , 可以看到 , id 字段中除了 Key 选项中状态为 PRI 和 Null 选项状态为 NO 之外 , 还有一个 Extra 选项的值也是 auto_increment 了
mysql> desc student;
+---------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
再添加记录时 , 如果 id 列为 null , 此时自增主键会自动给 id 列添加一个值 , 能保证不重复
-- 添加记录 , id 列由自增主键默认给值
mysql> insert into student values(null,2001,'张三','123@qq.com');
Query OK, 1 row affected (0.00 sec)
-- 添加记录 , id 列由自增主键默认给值
mysql> insert into student values(null,2001,'张三','123@qq.com');
Query OK, 1 row affected (0.00 sec)
-- 添加记录 , id 列由自增主键默认给值
mysql> insert into student values(null,2001,'张三','123@qq.com');
Query OK, 1 row affected (0.00 sec)
-- 手动干预 id 列添加数据
mysql> insert into student values(10,2001,'张三','123@qq.com');
Query OK, 1 row affected (0.00 sec)
-- 添加记录 , id 列由自增主键默认给值
mysql> insert into student values(null,2001,'张三','123@qq.com');
Query OK, 1 row affected (0.00 sec)
查看表中所有列 , 添加语句 id 为 null 的命令自增主键都会默认添加一个值且每个值都不重复 , 如果手动干预超过了当前自增主键的最大值 , 自增主键就会从当前手动干预的值开始继续往下自增 , 这是因为自增主键在MySQL内部维护了一个"全局变量"的东西 , 每次添加的记录如果指定的是 null , 全局变量 ++ , 如果手动添加的值 , 超过当前的全局变量 , 全局变量则会直接更新成当前最大的值.
mysql> select * from student;
+----+------+--------+------------+
| id | sn | name | qq_mail |
+----+------+--------+------------+
| 1 | 2001 | 张三 | 123@qq.com |
| 2 | 2001 | 张三 | 123@qq.com |
| 3 | 2001 | 张三 | 123@qq.com |
| 10 | 2001 | 张三 | 123@qq.com |
| 11 | 2001 | 张三 | 123@qq.com |
+----+------+--------+------------+
5 rows in set (0.00 sec)
3.现有表中添加默认约束
由于自增主键在一张表中只能有一个 , 所以这里我们需要重新设置以下 student 表结构 , 也就是先把 student 表先删除 , 然后创建一张没有任何约束的 student 表
-- 重新设置学生表结构
drop table if exists student;
-- 创建 student 数据表
create table student (
id int,
sn int,
name varchar(20),
qq_mail varchar(20)
);
-- 查看表结构
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
命令
alter table <数据表名> add primary key(<字段名>);
示例
将 student 表中的 id 字段设置为主键
alter table student add primary key(id);
查看 student 表结构 , 可以看到 id 列中的 Key 选项的状态已经改成 PRI 了 且 Null 选项状态为 NO
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
4.删除主键约束
命令
alter table <数据表名> drop primary key;
示例
删除 student 表中的主键约束
alter table student drop primary key;
查看表结构 , 发现虽然 id列中的 Key 选项的状态已经变成空白 , 但是 Null 选项中的状态还是 NO , 表示不允许填空值 , 所以要将效果移除干净还要执行一次删除非空约束的命令
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
-- 删除非空约束
alter table student modify id int;
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
外键约束 ( foreign key )
外键用于关联其它表中的主键或唯一键 , 在插入数据时 , 必须插入另一张表中的主键的有效数据
先准备另一张带有主键约束的表
-- 创建一张班级表 , 班级 id 设置为主键
create table class(
class_id int primary key auto_increment,
class_name varchar(20)
);
1.创建表添加外键约束
命令
create table <数据表名>(<列名1> <类型>,<列名2> <类型>,....,foreign key(<外键指定字段>)) references <主数据表> (<指定主表主键>);
示例
创建一张 student 表 , 并指定 id 列作为外键 , 指向 class 表中的 class_id 主键
-- 重新设置学生表结构
drop table if exists student;
-- 创建 student 数据表
create table student (
id int,
sn int,
name varchar(20),
qq_mail varchar(20),
foreign key(id) references class(class_id)
);
查看两张表结构 , 在 class 表中 class_id 字段中的 Key 的状态为主键 , 在 student 表中 id 字段中的状态为 MUL , 表示是外键约束
-- 查看 class 表结构
mysql> desc class;
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| class_id | int(11) | NO | PRI | NULL | auto_increment |
| class_name | varchar(20) | YES | | NULL | |
+------------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
-- 查看 student 表结构
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | YES | MUL | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
class 表为记录为空的情况下,student 表此时添加数据会报错
insert into student values(1,2001,'张三','123@qq.com');
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`id`) REFERENCES `class` (`class_id`))
-- error : 无法添加或更新子行:外键约束失败(' test ')。' student ', CONSTRAINT ' student_ibfk_1 ' FOREIGN KEY (' id ') REFERENCES ' class ' (' class_id '))
正确的添加记录 , 是需要先给 class 主表添加记录,因为 class 表带自增主键,id 列可以为 null , 只有在 class 表中有记录之后 , student 中才能进行添加记录。
-- class 表添加两条记录
insert into class values(null,'1班');
Query OK, 1 row affected (0.00 sec)
insert into class values(null,'2班');
Query OK, 1 row affected (0.00 sec)
-- student 表添加三条记录
insert into student values(1,2001,'张三','123@qq.com');
Query OK, 1 row affected (0.00 sec)
insert into student values(2,2001,'李四','123@qq.com');
Query OK, 1 row affected (0.00 sec)
insert into student values(1,2001,'王五','123@qq.com');
Query OK, 1 row affected (0.00 sec)
不过需要注意 , 在 student 表中添加数据中 id 列 的值必须符合主表 class 中 class_id 中的值 , 由于在 class 表当中,class_Id 列只有 1 和 2 , 此时 student 表添加 id 为 3 的记录,由于外键约束失败导致插入失败
-- student 表添加数据 , id 列的值不符合 class_id 的值 , 所以会添加失败
insert into student values(3,2001,'赵六','123@qq.com');
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`id`) REFERENCES `class` (`class_id`))
-- 无法添加或更新子行:外键约束失败(' test ')。' student ', CONSTRAINT ' student_ibfk_1 ' FOREIGN KEY (' id ') REFERENCES ' class ' (' class_id '))
如果此时去删除或者修改 class 表中的记录 , 会发生什么? 依旧会报错 , 一旦受约束表当中存入了当前约束表当中的值,那么此时约束表的记录就不能轻易的去删除或者修改 ! !
-- 修改 class 表中的 class_id 的值
update class set class_id = 3 where class_id=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`id`) REFERENCES `class` (`class_id`))
-- error : 无法删除或更新父行:外键约束失败(' test ')。' student ', CONSTRAINT ' student_ibfk_1 ' FOREIGN KEY (' id ') REFERENCES ' class ' (' class_id '))
外键约束带来的效果是 :
-
往 student 表中添加的记录, id 列的值必须在 class 表中的 class_id 列存在~
-
student 表指定的这个外键约束,必须是 class 表的 主键/唯一键
-
外键约束建立好了之后,此时 class 表中的 class_id 就不能随便改了
2.在现有表中添加外键约束
在这里重新设置一下 student 表结构 , 让 student 表不添加任何约束
-- 重新设置学生表结构
drop table if exists student;
-- 创建 student 数据表
create table student (
id int,
sn int,
name varchar(20),
qq_mail varchar(20)
);
-- 查看 student 表结构
mysql> desc student;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| sn | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| qq_mail | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
命令
alter table <数据表名> add foreign key(<外键指定字段>) references <主数据表> (<指定主表主键>);
示例
-
在现有 student 表中 , 给 id 列添加外键约束 , 关联 class 表中的 class_id 列
alter table student add foreign key(id) references class(class_id);
查看 student 表结构 , 可以看到 , id 字段中的 Key 选项状态已经改成了 MUL 主键约束的状态了
mysql> desc student; +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | id | int(11) | YES | MUL | NULL | | | sn | int(11) | YES | | NULL | | | name | varchar(20) | YES | | NULL | | | qq_mail | varchar(20) | YES | | NULL | | +---------+-------------+------+-----+---------+-------+ 4 rows in set (0.00 sec)
注意 : 如果在修改时 , student 表中预修改字段中已有数据 , 且绑定外键约束的主表中的主键字段没有该数据 , 会修改失败
3.删除外键约束
删除外键约束的方法和删除唯一约束的方法差不多 , 需要先在表中先找到该外键约束的约束名称 , 通过约束名称解除外键链接 , 在通过键名取消外键状态
命令
alter table <数据表名> drop foreign key <约束名> , drop index <对应的键名>;
查看约束对应的约束名称
show create table <数据表名>;
示例
删除 student 表中的外键约束
-
先查看 student 表中所有约束信息 , 找到 id 字段对应的约束名和键名
show create table student;
student 表对应的以下一个外键约束 , `` 引起的 student_ibfk_1就是约束名 , KEY 后面反引号引起的 'id' 是键名
KEY `id` (`id`), CONSTRAINT `student_ibfk_1` FOREIGN KEY (`id`) REFERENCES `class` (`class_id`);
-
使用对应的键名解除 student 表中外键约束 , 在使用对应的键名删除 Key 状态
alter table student drop foreign key student_ibfk_1 , drop index id;
-
查看表结构 , 可以看到虽然 id 字段中的 Key 选项仍然为空了, 此时的 class 表中是没有数据的 , 向 student 表中插入数据 , 是可以进行插入的 , 这就证明 student 表中的外键约束解除了 , 不受到 class 表的影响。
mysql> desc student; +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | sn | int(11) | YES | | NULL | | | name | varchar(20) | YES | | NULL | | | qq_mail | varchar(20) | YES | | NULL | | +---------+-------------+------+-----+---------+-------+ 4 rows in set (0.00 sec) -- 查看 class 表中的数据 select * from class; Empty set (0.00 sec) -- 对 student 表添加记录 insert into student values(1,2001,'张三','123@qq.com'); Query OK, 1 row affected (0.00 sec) insert into student values(2,2001,'李四','123@qq.com'); Query OK, 1 row affected (0.00 sec) -- 查看 student 表中的数据 select * from student; +------+------+--------+------------+ | id | sn | name | qq_mail | +------+------+--------+------------+ | 1 | 2001 | 张三 | 123@qq.com | | 2 | 2001 | 李四 | 123@qq.com | +------+------+--------+------------+ 2 rows in set (0.00 sec)
本章到此结束,如果文中有写的不对或不懂的地方,欢迎评论区讨论,谢谢!
以上是关于MySQL约束 主键约束丨唯一约束丨非空约束丨外键级联的主要内容,如果未能解决你的问题,请参考以下文章