目录
[1. 为什么需要约束](#1. 为什么需要约束)
[2. DEFAULT 默认值](#2. DEFAULT 默认值)
[3. NOT NULL 非空约束](#3. NOT NULL 非空约束)
[3.1 NOT NULL 的基本用法](#3.1 NOT NULL 的基本用法)
[3.2 NOT NULL 与 DEFAULT 关系](#3.2 NOT NULL 与 DEFAULT 关系)
[4. UNIQUE 唯一约束](#4. UNIQUE 唯一约束)
[4.1 UNIQUE 的基本用法](#4.1 UNIQUE 的基本用法)
[4.2 UNIQUE 与 NULL](#4.2 UNIQUE 与 NULL)
[4.3 联合唯一约束](#4.3 联合唯一约束)
[5. PRIMARY KEY 主键约束](#5. PRIMARY KEY 主键约束)
[5.1 PRIMARY KEY 的基本使用](#5.1 PRIMARY KEY 的基本使用)
[5.2 联合主键约束](#5.2 联合主键约束)
[5.3 自增长 AUTO_INCREMENT](#5.3 自增长 AUTO_INCREMENT)
[5.3.2 手动指定自增长值](#5.3.2 手动指定自增长值)
[5.3.3 设置自增长起始值](#5.3.3 设置自增长起始值)
[5.3.3 DELETE 与 TRUNCATE 对自增长值的影响](#5.3.3 DELETE 与 TRUNCATE 对自增长值的影响)
[5.4 PRIMARY KEY 与 UNIQUE 的区别](#5.4 PRIMARY KEY 与 UNIQUE 的区别)
[6. 外键约束](#6. 外键约束)
[6.1 为什么需要外键约束](#6.1 为什么需要外键约束)
[6.2 外键约束的基本使用](#6.2 外键约束的基本使用)
[6.3 给外键约束命名](#6.3 给外键约束命名)
[6.4 删除外键约束](#6.4 删除外键约束)
[7. 其他常见列属性](#7. 其他常见列属性)
[7.1 COMMENT 列描述](#7.1 COMMENT 列描述)
[7.2 ZEROFILL 零填充](#7.2 ZEROFILL 零填充)
本文内容概要
本文主要介绍 MySQL 中常见的约束及其使用方式,包括 DEFAULT 默认值、NOT NULL 非空约束、UNIQUE 唯一约束、PRIMARY KEY 主键约束以及 FOREING KEY 外键约束,并结合实际 SQL 操作理解不同约束的作用与使用场景。
除此之外,本文还会补充介绍 AUTO_INCRTMENT 自增长、COMMENT 列描述和 ZEROFILL 零填充等常用列属性,帮助我们进一步掌握 MySQL 数据表的设计与字段约束。
1. 为什么需要约束
在数据库中,我们不仅需要将数据存储起来,还需要保证存储的数据具有一定的正确性、合法性和完整性。
例如:我们创建一张学生信息表:
sql
create table student(
id int,
name varchar(20),
gender char(1)
);
如果没有对表中的字段进行任何设置,在实际业务角度,可能发生一下问题:
-
学生 id 应该用于唯一标识一个学生,不应该出现重复;
-
学生 id 不应该为空;
-
学生姓名可能要求必须填写;
-
某些字段可能需要具有默认值;
-
不同数据表之间可能需要保证数据的关联关系。
如果这些规则全部依靠程序员在业务代码中进行判断,不仅会增加程序的复杂度,而且一旦某处代码存在细微 BUG,就可能向数据库插入非法数据。因此 MySQL 提供了约束机制,可以直接在数据库层面进行限制。
约束:对数据表中字段的数据进行限制的一系列规则,用于保证数据库中数据的正确性、合法性和完整性。
2. DEFAULT 默认值
在创建数据表时,可以通过 DEFAULT 关键字为字段指定默认值。
sql
mysql> create table student(
-> id int unsigned,
-> name varchar(20),
-> gender char(1) default '男'
-> );
Query OK, 0 rows affected (0.01 sec)
查看表结构:
sql
mysql> desc student;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| gender | char(1) | YES | | 男 | |
+--------+------------------+------+-----+---------+-------+
其中,gender 字段的默认值被设置为了 '男'。
当插入数据时,如果没有为 gender 字段指定值,MySQL 就会自动使用该字段的默认值:
sql
mysql> insert into student (id, name, gender) values (1, '张三', '男');
Query OK, 1 row affected (0.00 sec)
mysql> insert into student (id, name) values (2, '李四');
Query OK, 1 row affected (0.01 sec)
mysql> insert into student (id, gender) values (3, '女');
Query OK, 1 row affected (0.00 sec)
查询数据:
sql
mysql> select * from student;
+------+--------+--------+
| id | name | gender |
+------+--------+--------+
| 1 | 张三 | 男 |
| 2 | 李四 | 男 |
| 3 | NULL | 女 |
+------+--------+--------+
可以看到:
-
第一条记录显式指定了 gender = '男';
-
第二条记录没有指定 gender,因此使用默认值 '男';
-
第三条记录没有指定 name,使用默认值 NULL;
如果没有显式指定 DEFAULT,MySQL 通常会将 NULL 作为其默认值。
NULL 表示该字段当前没有值,它并不是空字符串
'',也不是数字0。
查看建表语句:
sql
mysql> show create table student \G;
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(10) unsigned DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`gender` char(1) DEFAULT '男'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
3. NOT NULL 非空约束
3.1 NOT NULL 的基本用法
在创建数据表时,可以通过 NOT NULL 约束指定某个字段不允许为 NULL。
sql
mysql> create table student(
-> id int unsigned not null,
-> name varchar(20) not null,
-> gender char(1)
-> );
Query OK, 0 rows affected (0.01 sec)
查看数据表结构:
sql
mysql> desc student;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | NO | | NULL | |
| name | varchar(20) | NO | | NULL | |
| gender | char(1) | YES | | NULL | |
+--------+------------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
其中:
-
id 字段的 Null 为 NO,表示该字段不允许为 NULL;
-
name 字段的 Null 为 NO,表示该字段不允许为 NULL;
-
gender 字段的 Null 为 YES,表示该字段允许为 NULL。
接下来插入数据:
sql
mysql> insert into student (id, name, gender) values (1, '张三', '男');
Query OK, 1 row affected (0.01 sec)
mysql> insert into student (id, name) values (1, '张三');
Query OK, 1 row affected (0.00 sec)
第二条语句虽然没有指定 gender 字段,但由于 gender 允许为 NULL,因此可以正常插入。
如果没有为被 NOT NULL 约束的字段提供默认值:
sql
mysql> insert into student (name, gender) values ('王五', '女');
ERROR 1364 (HY000): Field 'id' doesn't have a default value
由于 id 字段被 NOT NULL 约束,并且没有设置默认值,因此插入失败。
查看当前数据:
sql
mysql> select * from student;
+----+--------+--------+
| id | name | gender |
+----+--------+--------+
| 1 | 张三 | 男 |
| 1 | 张三 | NULL |
+----+--------+--------+
2 rows in set (0.01 sec)
因此,NOT NULL 约束的作用就是:要求该字段必须具有有效值,不能存储 NULL**。**
需要注意的是,NULL 和空字符串 '' 并不是同一个概念。NOT NULL 只限制字段不能为 NULL,并不会禁止插入空字符串。
查看建表语句:
sql
mysql> show create table student \G;
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(10) unsigned NOT NULL,
`name` varchar(20) NOT NULL,
`gender` char(1) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
3.2 NOT NULL 与 DEFAULT 关系
NOT NULL 约束本身不会为字段提供默认值。
sql
mysql> insert into student (name, gender) values ('小红', '女');
ERROR 1364 (HY000): Field 'id' doesn't have a default value
mysql> insert into student (id, name, gender) values (NULL ,'小红', '女');
ERROR 1048 (23000): Column 'id' cannot be null
这两种错误虽然都与 NOT NULL 字段有关,但产生错误的原因并不相同:
- 插入数据时省略 NOT NULL 字段:由于该字段没有设置默认值,MySQL 无法确定应该为该字段插入什么值,因此报错。
- 显示向 NOT NULL 字段插入 NULL:违反了 NOT NULL 非空约束,因此报错
因此需要区分:没有提供默认值 ≠ 显式插入 NULL
前者涉及字段是否存在默认值,后者则违反 NOT NULL 非空约束。
NOT NULL 和 DEFAULT 的联合使用样例
sqlmysql> create table student( -> id int unsigned, -> name varchar(20)^C mysql> create table student( -> id int unsigned not null, -> name varchar(20) not null, -> gender char(1) not null default '男' -> ); mysql> show create table student \G; *************************** 1. row *************************** Table: student Create Table: CREATE TABLE `student` ( `id` int(10) unsigned NOT NULL, `name` varchar(20) NOT NULL, `gender` char(1) NOT NULL DEFAULT '男' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 mysql> insert into student (id, name, gender) values (10, '小华', '女'); mysql> insert into student (id, name) values (11, '小黑'); mysql> select * from student; +----+--------+--------+ | id | name | gender | +----+--------+--------+ | 10 | 小华 | 女 | | 11 | 小黑 | 男 | +----+--------+--------+ 2 rows in set (0.00 sec)
4. UNIQUE 唯一约束
4.1 UNIQUE 的基本用法
在创建数据表时,可以通过 UNIQUE 约束保证某个字段中的数据具有唯一性,即该字段中不能出现重复的数据。
例如,学生的学号通常应该具有唯一性,可以通过 UNIQUE 对学号字段进行约束。
sql
mysql> create table student(
-> id int unsigned unique,
-> name varchar(20) not null,
-> gender char(1)
-> );
Query OK, 0 rows affected (0.01 sec)
查看表结构:
sql
mysql> desc student;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | YES | UNI | NULL | |
| name | varchar(20) | YES | | NULL | |
| gender | char(1) | YES | | NULL | |
+--------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
可以看到,id 字段对应的 Key 为 UNI,表示该字段被唯一约束修饰。
向数据表中插入数据:
sql
mysql> insert into student values (1, '张三', '男');
Query OK, 1 row affected (0.00 sec)
mysql> insert into student values (2, '李四', '男');
Query OK, 1 row affected (0.00 sec)
此时 id 字段中的数据分别为 1 和 2,不存在重复,因此可以正常插入。
如果再次插入相同的 id:
sql
mysql> insert into student values (1, '王五', '男');
ERROR 1062 (23000): Duplicate entry '1' for key 'id'
由于 id 字段被 UNIQUE 约束修饰,而当前数据表中已经存在 id = 1 的记录,因此再次插入相同的数据会违反唯一约束,MySQL 会拒绝此次插入。
因此:UNIQUE 约束保证字段中的非 NULL****数据不能重复。
4.2 UNIQUE 与 NULL
需要注意的是,UNIQUE 约束和 NOT NULL 约束是两个不同的约束。
UNIQUE 负责保证数据的唯一性,但并不会限制字段不能为 NULL。
例如:
sql
mysql> insert into student (name, gender) values ('小红', '女');
Query OK, 1 row affected (0.00 sec)
mysql> insert into student (name, gender) values ('小明', '男');
Query OK, 1 row affected (0.00 sec)
查看数据:
sql
mysql> select * from student;
+------+--------+--------+
| id | name | gender |
+------+--------+--------+
| 1 | 张三 | 男 |
| 2 | 李四 | 男 |
| NULL | 小红 | 女 |
| NULL | 小明 | 男 |
+------+--------+--------+
可以看到,即使 id 字段被 UNIQUE 约束修饰,也仍然可以存在多个 NULL。
这是因为 NULL 表示未知或者不存在的值,在进行唯一性判断时,MySQL 允许唯一索引中存在多个 NULL。
因此:UNIQUE ≠ NOT NULL
如果既要求字段不能为空,又要求字段不能重复,可以同时使用:
sql
id int unsigned not null unique
4.3 联合唯一约束
除了可以约束单个字段之外,UNIQUE 还可以同时约束多个字段,这种方式称为联合唯一约束。
例如,存在如下数据表:
sql
mysql> create table course(
-> student_id int unsigned,
-> course_id int unsigned,
-> score int,
-> unique(student_id, course_id)
-> );
Query OK, 0 rows affected (0.01 sec)
unique(student_id, course_id) 表示 student_id 和 course_id 两个字段组合起来必须具有唯一性。
插入数据:
sql
mysql> insert into course values (1, 1001, 90);
Query OK, 1 row affected (0.00 sec)
mysql> insert into course values (1, 1002, 85);
Query OK, 1 row affected (0.00 sec)
mysql> insert into course values (2, 1001, 92);
Query OK, 1 row affected (0.00 sec)
虽然数据中出现了重复的 student_id 和重复的 course_id,但两个字段组成的组合并没有重复,因此可以正常插入。
如果再次插入:
sql
mysql> insert into course values (1, 1001, 95);
ERROR 1062 (23000): Duplicate entry '1-1001' for key 'student_id'
此时:
sql
student_id = 1
course_id = 1001
这一组合已经存在,因此违反联合唯一约束。
即联合唯一约束限制的并不是某一个字段单独不能重复,而是:多个字段组合之后的值不能重复。
5. PRIMARY KEY 主键约束
5.1 PRIMARY KEY 的基本使用
在一张数据表中,通常需要使用某个字段唯一标识一条记录,这个字段就可以设置为主键。
MySQL 可以通过 PRIMARY KEY 约束指定数据表的主键。
例如,学生表中的 id 可以作为每个学生的唯一标识:
sql
mysql> create table student(
-> id int unsigned primary key,
-> name varchar(20) not null,
-> gender char(1)
-> );
Query OK, 0 rows affected (0.01 sec)
查看数据表结构:
sql
mysql> desc student;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | NO | PRI | NULL | |
| name | varchar(20) | YES | | NULL | |
| gender | char(1) | YES | | NULL | |
+--------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
可以看到:
-
id 字段的 Key 为 PRI,表示该字段是主键;
-
id 字段的 Null 为 NO,表示主键字段不允许为 NULL。
向数据表中插入数据:
sql
mysql> insert into student values (1, '张三', '男');
Query OK, 1 row affected (0.00 sec)
mysql> insert into student values (2, '李四', '男');
Query OK, 1 row affected (0.00 sec)
由于两个 id 值不同,因此可以正常插入。
如果再次插入已经存在的主键值:
sql
mysql> insert into student values (1, '王五', '男');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
由于 id = 1 已经存在,再次插入相同的主键值会违反主键的唯一性,因此插入失败。
主键也不能为 NULL:
sql
mysql> insert into student values (NULL, '小红', '女');
ERROR 1048 (23000): Column 'id' cannot be null
因此,主键必须同时满足:不能重复 + 不能为空
从约束效果上可以将主键理解为:
sql
PRIMARY KEY ≈ UNIQUE + NOT NULL
需要注意的是,这只是为了方便理解主键的约束效果,并不代表主键在 MySQL 内部就是简单地由UNIQUE 和 NOT NULL 两个约束组合而成。
注:一张数据表最多只能定义一个 PRIMARY KEY。
例如,下面的定义是不允许的:
sqlcreate table student( id int primary key, number int primary key, name varchar(20) );因为一张表不能同时存在两个独立的主键。
但是,一个主键可以由多个字段共同组成,这种主键称为联合主键。
5.2 联合主键约束
有些情况下,单独使用某一个字段无法唯一标识一条记录,此时可以使用多个字段共同组成主键。
例如,一名学生可以选择多门课程,一门课程也可以被多名学生选择:
sql
mysql> create table course(
-> student_id int unsigned,
-> course_id int unsigned,
-> score int,
-> primary key(student_id, course_id)
-> );
Query OK, 0 rows affected (0.01 sec)
primary key(student_id, course_id) 表示 student_id和 course_id两个字段共同组成主键。
插入数据:
sql
mysql> insert into course values (1, 1001, 90);
Query OK, 1 row affected (0.00 sec)
mysql> insert into course values (1, 1002, 85);
Query OK, 1 row affected (0.00 sec)
mysql> insert into course values (2, 1001, 92);
Query OK, 1 row affected (0.00 sec)
虽然 student_id和 course_id单独来看都存在重复,但是两个字段组成的组合并没有重复,因此可以正常插入。
如果再次插入:
mysql> insert into course values (1, 1001, 95);
ERROR 1062 (23000): Duplicate entry '1-1001' for key 'PRIMARY'
由于:
(student_id, course_id) = (1, 1001)
这个组合已经存在,因此违反了联合主键的唯一性。
即:联合主键要求组成主键的多个字段组合后的值具有唯一性。
5.3 自增长 AUTO_INCREMENT
在创建数据表时,经常会使用一个整数类型的字段作为主键,例如学生表中的 id:
sql
create table student(
id int unsigned primary key,
name varchar(20) not null
);
由于主键要求数据唯一,因此每次插入数据时,都需要手动为 id 指定一个不同的值:
sql
insert into student values(1, '张三');
insert into student values(2, '李四');
insert into student values(3, '王五');
如果数据量非常大,每次都手动维护主键值显然比较麻烦。
MySQL 提供了 AUTO_INCREMENT 属性,可以让整数类型的字段自动增长。
sql
create table student(
id int unsigned primary key auto_increment,
name varchar(20) not null
);
此时插入数据时,就可以不用手动指定 id:
sql
insert into student(name) values('张三');
insert into student(name) values('李四');
insert into student(name) values('王五');
查询数据:
sql
mysql> select * from student;
+----+--------+
| id | name |
+----+--------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
+----+--------+
可以看到,MySQL 会自动为 id 字段分配递增的值。
5.3.1 AUTO_INCREMENT 的特点
-
通常作用于整数类型字段。
-
一张表只能存在一个 AUTO_INCREMENT 字段。
-
AUTO_INCREMENT 字段必须建立索引,因此实际开发中通常将其设置为主键。
sql
id int unsigned primary key auto_increment
-
默认情况下,自增长值从 1 开始,每次增加
1。 -
插入数据时,如果不指定自增长字段的值,MySQL 会自动生成。
例如:
sql
insert into student(name) values('小明');
也可以写成:
sql
insert into student values(NULL, '小红');
对于 AUTO_INCREMENT 字段插入 NULL 时,MySQL 会自动生成下一个自增长值。
5.3.2 手动指定自增长值
虽然字段使用了 AUTO_INCREMENT ,但是仍然可以手动指定一个合法的值:
sql
insert into student values(10, '小刚');
此时 id = 10。
如果当前自增长计数小于 10,那么之后继续插入数据时,自增长值通常会从更大的值继续增长:
sql
insert into student(name) values('小李');
此时得到:id = 11
因此,AUTO_INCREMENT 并不是限制用户不能手动插入数据,而是在用户没有指定字段值时,由 MySQL 自动生成一个值。
5.3.3 设置自增长起始值
创建表时,也可以指定自增长的起始值:
sql
create table student(
id int unsigned primary key auto_increment,
name varchar(20) not null
) auto_increment = 100;
此时第一条数据的 id 将从 100 开始:
sql
insert into student(name) values('张三');
sql
id = 100
也可以通过 ALTER TABLE 修改下一次自增长使用的值:
sql
alter table student auto_increment = 200;
5.3.3 DELETE 与 TRUNCATE 对自增长值的影响
使用 DELETE 删除数据后,自增长计数通常不会改变。
例如原来的数据为:
sql
1
2
3
执行:
sql
delete from student;
再次插入:
sql
insert into student(name) values('张三');
新数据的 id 通常会继续向后增长,而不是重新变成 1。
而使用:
sql
truncate table student;
清空表时,会重新初始化自增长计数,下一次插入数据通常会重新从 1 开始。
注意:AUTO_INCREMENT 的作用是自动生成递增值,并不代表生成的值一定连续。例如数据被删除、事务回滚等情况下,自增长序列可能出现空缺。因此不要将 AUTO_INCREMENT 理解为"保证编号连续"。
5.4 PRIMARY KEY 与 UNIQUE 的区别
primary key 和 unique 都可以保证数据具有唯一性,但两者之间仍然存在区别。
| 对比项 | PRIMARY KEY | UNIQUE |
|---|---|---|
| 是否保证唯一 | 是 | 是 |
| 是否允许 NULL | 不允许 | 可以允许 NULL |
| 一张表可以有几个 | 最多一个 | 可以有多个 |
| 主要作用 | 唯一标识一条记录 | 保证字段数据不重复 |
主键主要是用来标识唯一性字段,唯一键主要是用来处理业务逻辑上的唯一性!
6. 外键约束
6.1 为什么需要外键约束
在实际开发中,一张数据表通常无法描述所有的数据,不同的数据之间往往存在一定的关联关系。
例如:学校中会存在学生和班级 ---- 班级表和学生表
| 班级表(class) | class_id | class_name | |----------|------------| | 1 | 计算机1班 | | 2 | 计算机2班 | 学生表(student) | id | name | class_id | |----|------|----------| | 1 | 张三 | 1 | | 2 | 李四 | 1 | | 3 | 王五 | 2 | | |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---|
| | |
| | |
学生表中的 class_id 用于表示当前学生所属哪个班级。
如果只是存在这两种表,但没有任何限制:就可能会出现下面这种情况:
sql
insert into student values(4, '赵六', 100);
delete from class where id=1;
- 构建一个学生的基本信息时,插入一个不存在的班级 id
- 删除班级 id 时,有学生表依旧关联该班级 id
此时,为了保证两张表之间数据的完整性,MySQL 提供了外键约束。
6.2 外键约束的基本使用
外键约束主要用于建立两张表之间的关联关系,并保证关联数据的合法性。
通常将被引用的表成为父表,引用其他表的表成为子表。
在上述例子中:class 为父表,student 为子表。
创建班级表和学生表:
sql
create table class(
class_id int primary key,
class_name varchar(20) not null
);
create table student(
id int primary key auto_increment,
name varchar(20) not null,
class_id int,
foreign key(class_id) references class(class_id)
);
插入数据:
sql
mysql> insert into class values(1, '计算机1班');
Query OK, 1 row affected (0.01 sec)
mysql> insert into class values(2, '计算机2班');
Query OK, 1 row affected (0.00 sec)
mysql> select * from class;
+----------+---------------+
| class_id | class_name |
+----------+---------------+
| 1 | 计算机1班 |
| 2 | 计算机2班 |
+----------+---------------+
2 rows in set (0.00 sec)
insert into student (name, class_id) values ('张三', 1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into student (name, class_id) values('李四', 100);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`class_id`))
mysql> delete from class where class_id=2;
Query OK, 1 row affected (0.01 sec)
mysql> delete from class 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 (`class_id`) REFERENCES `class` (`class_id`))
插入失败原因:子表外键字段的值,必须能够在父表中存在。
删除失败原因:父表中字段被子表所引用。如果父表修改被引用数据也会失败。
注:此处引用,一定是被子表中所占用,就相当于例子中的班级 id=1 被占用,但班级 id=2 未被占用,父表可以对其删除和修改。
建表 SQL 语句:
sql
mysql> show create table student \G;
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`class_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `class_id` (`class_id`),
CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`class_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
6.3 给外键约束命名
创建外键时,也可以显式指定外键约束的名字。如果不指定,MySQL 会默认生成。
sql
create table student(
id int primary key auto_increment,
name varchar(20) not null,
class_id int,
constraint fk_student_class
foreign key(class_id)
references class(class_id)
);
show create table student \G;
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`class_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_student_class` (`class_id`),
CONSTRAINT `fk_student_class` FOREIGN KEY (`class_id`) REFERENCES `class` (`class_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
fk_student_class 就是当前外键约束的名称。
显示命名外键的好处:删除或者管理外键时更加方便。
6.4 删除外键约束
删除外键时,需要通过外键约束名称进行删除:
sql
alter table student drop foreign key fk_student_class;
7. 其他常见列属性
前面介绍的 DEFAULT、NOT NULL、UNIQUE、PRIMARY KEY、FOREIGN KEY 主要用于对数据进行约束,除此之外,在定义字段时还可以使用一些其他属性。
7.1 COMMENT 列描述
在创建数据表时,可以通过 COMMENT 为字段添加描述信息,用于说明当前字段的含义。
基本语法:字段名 数据类型 其他属性 comment '字段描述'
sql
create table student(
id int unsigned primary key auto_increment comment '学生编号',
name varchar(20) not null comment '学生姓名',
age tinyint unsigned comment '学生年龄'
);
desc student;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint(3) unsigned | YES | | NULL | |
+-------+---------------------+------+-----+---------+----------------+
show create table student \G;
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '学生编号',
`name` varchar(20) NOT NULL COMMENT '学生姓名',
`age` tinyint(3) unsigned DEFAULT NULL COMMENT '学生年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
show full columns from student \G;
*************************** 1. row ***************************
Field: id
Type: int(10) unsigned
Collation: NULL
Null: NO
Key: PRI
Default: NULL
Extra: auto_increment
Privileges: select,insert,update,references
Comment: 学生编号
*************************** 2. row ***************************
Field: name
Type: varchar(20)
Collation: utf8_general_ci
Null: NO
Key:
Default: NULL
Extra:
Privileges: select,insert,update,references
Comment: 学生姓名
*************************** 3. row ***************************
Field: age
Type: tinyint(3) unsigned
Collation: NULL
Null: YES
Key:
Default: NULL
Extra:
Privileges: select,insert,update,references
Comment: 学生年龄
COMMENT 并不会影响字段中实际存储的数据,它主要是用来提高表结构的可读性。对于结构比较复杂的数据表,通过字段描述可以更加直观理解每个字段的作用。
注:字段描述需要通过查看建表语句或者查看字段的详细信息查看,不能通过 desc 查看。
7.2 ZEROFILL 零填充
ZEROFILL 是 MySQL 数值类型曾经提供的一种显示属性。
它的主要作用是:当数值实际显示宽度不足指定宽度时,在数值左侧使用 0 进行填充。
例如:
sql
create table test(
id int(5) zerofill
);
insert into test values (12);
insert into test values (123);
insert into test values (123456);
select * from test;
+----------+
| id |
+----------+
| 00012 |
| 00123 |
| 12344444 |
+----------+
其中 int(5) 中的 5 表示的是显示宽度,而不是 INT 类型能够存储的数据位数,当插入的数据显示宽度不足指定宽度时,在数组左侧使用 0 进行填充,当超过指定宽度时,正常显示。
sql
show create table test \G;
*************************** 1. row ***************************
Table: test
Create Table: CREATE TABLE `test` (
`id` int(5) unsigned zerofill DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
如果一个数值字段使用了 zerofill,MySQL 会自动为该字段添加 unsigned 属性。
补充说明:ZEROFILL 已不推荐使用
MySQL 官方已经将:ZEROFILL 以及整数类型的显示宽度标记为 Deprecated(弃用),未来版本可能移除相关支持。官方建议可以使用 LPAD() 完成补零显示,或者直接使用 CHAR类型保存需要固定格式的内容。因此对于 ZEROFILL:了解其作用和历史用法即可,在新的数据库设计中一般不建议继续使用。