zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

【MySQL】表的基本约束

2023-04-18 16:05:17 时间

目录

1、约束类型

2、NOT NULL

3、UNIQUE

4、DEFAULT


1、约束类型

关键字解释
NOT NULL指示某列不能为空值
UNIQUE保证某列的每一行的值不重复
DEFAULT当没有给某个列赋值时的默认值
PRIMARY KEYNOT NULL 和 UNIQUE 的结合,确保某列(或多列) 有唯一标识,称为主键
FOREIGN KEY保证一个表中的数据匹配另一个表中的值的参照完整性
CHECK

保证列中的值符合指定的条件 (MySQL 5 不支持,不介绍)

数据库的约束,其实是在方便程序猿,就拿 NOT NULL 来举例,指定某列中的每一行不能为 NULL,即也就标识了这个列的每一行必须存在数据,如果把这个作为一个君子间的约定,那就不靠谱,指定不那天某个程序猿忘了这个约定,果真搞了个空值,可能会给程序引发一些BUG,所以干脆把这种约定交给计算机来处理,一旦你没按照这个约定,就给你报错!

所以,约束就是让数据库帮助程序猿更好的检查数据是否正合理/正确!


2、NOT NULL

这个 NOT NULL,在创建表的时候,可以指定某列不为空,那么现在我们就来重新创建一张学生表:

create table student (
    id int,
    name varchar(10) not null,
    sex varchar(1),
    java float(5, 2),
    python float(5, 2)
);

这里创建表的时候,直接在设置对应列的后面加上 not null,这个关键字即可。

如上代码意味着将来我要往 student 表中插入数据,name 这一列中每一行必须有数据,简单来说,就是每个学生不能没有姓名。

前面我们讲过可以指定列插入,也即不完全插入,那么现在就来测试一下:

insert into student(id, name) values(1, '张三');
-- Query OK, 1 row affected (0.01 sec)

这里显示插入成功,因为我们只是针对 name 这一列设置为 not null,所以不影响 java 和 python 字段,也即 id,java,python 这三个字段是允许不插入数据的,那么当我们插入数据时,不给 name 字段插入数据会怎么样呢?

insert into student(id, java) values(1, 97.2);
-- ERROR 1364 (HY000): Field 'name' doesn't have a default value

这里出现了 error,读这个报错信息,说 name 这个字段没有默认值,别忘了,在没有设默认值的时候,默认为 NULL,也就是在你新增的时候,必须给这个字段指定一个值。

那么问题来了,NULL 算值吗?既然你说这个字段没有默认值,那我放个 NULL 总可以了吧?看代码:

insert into student(id, name, java) values(1, null, 97.2);
-- ERROR 1048 (23000): Column 'name' cannot be null

那么通过这个报错,我们又能发现,name 字段不能为 null,即 null 是空值,也就是没有值的意思。所以在数据库中 null 不是值,是表示没有数据!

接下来我们去查看设置成 not null 之后,表结构上发生了哪些变化:

desc student;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id     | int(11)     | YES  |     | NULL    |       |
| name   | varchar(10) | NO   |     | NULL    |       |
| sex    | varchar(1)  | YES  |     | NULL    |       |
| java   | float(5,2)  | YES  |     | NULL    |       |
| python | float(5,2)  | YES  |     | NULL    |       |
+--------+-------------+------+-----+---------+-------+
-- 5 rows in set (0.00 sec)

看到这个表的结构,相信就水落石出了!我们最后在作一次总结: 

总结:严格意义上来说,指定字段设置 not null,表明该字段不能为空,由于 Default(默认值)是 NULL,也就是在你没有给某个字段设置默认值的时候,你插入受 not null 限制的字段时,必须指定一个值。如果你指定了默认值,只要默认值不为 null,就可以使用默认值的值,简而言之,指定字段设置 not null,之后表明该字段不能为空! 


3、UNIQUE

这个单词翻译过来就是唯一的,独一无二的,见名知意,给哪个字段加上这个约束,哪个字段的值就不能重复了,必须是唯一的!

接下来我们重新创建一个表,演示 unique 的作用以及一些细节问题:

-- 如果存在 student 表, 请先删除该表.
create table student (
    id int unique,
    name varchar(10),
    sex varchar(1)
);

这次我们将学生的 id 设置是唯一的,那现在我们接下来就插入数据了:

insert into student values(1, '张三', '男');
-- Query OK, 1 row affected (0.01 sec)

insert into student values(1, '李四', '男');
-- ERROR 1062 (23000): Duplicate entry '1' for key 'id'

这里我们发现,插入第一条数据好好的没事,当插入第二条数据时报错了!阅读这个报错信息,它告诉我们,键 “id” 出现重复条目 “1”,相信看到这,你大概能知道 unique 的约束作用了。

那么 id 字段设置了 unique 约束,表的结构发生了哪些变化呢?

mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  | UNI | NULL    |       |
| name  | varchar(10) | YES  |     | NULL    |       |
| sex   | varchar(1)  | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
-- 3 rows in set (0.00 sec)

明显看到 Key 不能重复了,这里有一个问题,我们没有把 id 字段设置 not null 约束,那么这个字段设置 unique 约束后可以出现两个空值吗?也即可以不设置任何值吗?

insert into student values(null, '李四', '男');
-- Query OK, 1 row affected (0.00 sec)

insert into student values(null, '王五', '男');
-- Query OK, 1 row affected (0.01 sec)

显而易见,允许这样做,这里再次验证了前面的说法,null 表示没有任何值,而 unique 是针对值重复,这个字段的值是唯一的,null 表示没有值,所以 unique 限制不了 null,这是很多小伙伴初学阶段容易犯错的细节点,你 get 到了吗?

数据库是如何判定当前这个数据是重复的呢?

先查找,再插入,所以在加上这个约束后,数据库的执行过程可能就变慢了,效率可能会受到影响,但是总比你手动检查要好上不少吧!

注意:unique 和 not null,可以一起使用,相当于主键约束(后面期),每一列可以有多个约束。


4、DEFAULT

这个约束是当字段中没有插入数据的时候默认的数据。

这里重新创建一张学生表,将 name 字段的默认值为:"无名氏":

create table student (
    id int,
    name varchar(10) default '无名氏',
    sex varchar(1)
);

这样我们再来指定列插入一条数据:

insert into student(id, sex) values(1, '男');
-- Query OK, 1 row affected (0.00 sec)

select * from student;
+------+-----------+------+
| id   | name      | sex  |
+------+-----------+------+
|    1 | 无名氏    | 男   |
+------+-----------+------+
-- 1 row in set (0.00 sec)

这里可以发现,在没有给 name 字段插入数据的时候,默认的数据就是设置的默认值 "无名氏"。

当然设置了 DEFAULT 不影响你手动指定数据,它只针对你没有指定数据时会给你插入一个你设定的默认值罢了!

这里可能有小伙伴好奇心重,于是想,我能不能手动把默认值设置为 null 呢?即空值呢?

create table student (
    id int,
    name varchar(10) default null,
    sex varchar(1)
);
-- Query OK, 0 rows affected (0.03 sec)

可以是可以,但完全没必要啊!!! 这样做图个啥呢?

再进一步钻牛角尖,那我能在前面加上一个 not null 吗?这过分了啊!!!这不冲突才怪呢!

create table student (
    id int,
    name varchar(10) not null default null,
    sex varchar(1)
);
-- ERROR 1067 (42000): Invalid default value for 'name'

 后面这俩段代码,大家伙就当个乐子看了,没有研究的价值的!


下期预告:【MySQL】主键约束和外键约束