13.2.5 数据库约束 1.not null约束

13.2.5 数据库约束

前面创建的数据表仅仅指定了一些列定义,这仅仅是数据表的基本功能。除此之外,所有的关系数据库都支持对数据表使用约束,通过约束可以更好地保证数据表里数据的完整性约束是在表上强制执行的数据校验规则,约束主要用于保证数据库里数据的完整性。除此之外,当表中数据存在相互依赖性时,可以保护相关的数据不被删除。

5种完整性约束

大部分数据库支持下面5种完整性约束。

  • not null:非空约束,指定某列不能为空。
  • unique:唯一约束,指定某列或者几列组合不能重复。
  • primary key:主键,指定该列的值可以唯一地标识该条记录。
  • foreign key:外键,指定该行记录从属于主表中的一条记录,主要用于保证参照完整性
  • check:检查,指定一个布尔表达式,用于指定对应列的值必须满足该表达式

MySQL不支持check约束

虽然大部分数据库都支持上面5种约束,但**MySQL不支持CHECK约束**,虽然MySQLSQL语句也可以使用CHECK约束,但这个CHECK约束不会有任何作用。

约束分类

虽然约束的作用只是用于保证数据表里数据的完整性,但约束也是数据库对象,并被存储在系统表中,也拥有自己的名字。根据约束对数据列的限制,约束分为如下两类。

  • 单列约束:每个约束只约束一列。
  • 多列约束:每个约束可以约束多个数据列。

什么时候指定约束

为数据表指定约束有如下两个时机。

  • 建表的同时为相应的数据列指定约束。
  • 建表后创建,以修改表的方式来增加约束。

大部分约束都可以采用列级约束语法或者表级约束语法。下面依次介绍5种约束的建立和删除(约束通常无法修改)。
提示:
MySQL使用information_schema数据库里的TABLE_CONSTRAINTS表来保存该数据库实例中所有的约束信息,用户可以通过查询TABLE_CONSTRAINTS表来获取该数据库的约束信息。

1.NOT NULL约束

非空约束用于确保指定列不允许为空,非空约束是比较特殊的约束,它只能作为列级约束使用,只能使用列级约束语法定义。这里要介绍一下SQL中的null值,SQL中的null不区分大小写。SQL中的null具有如下特征。

  • 所有数据类型的值都可以是null,包括intfloatboolean等数据类型。
  • Java类似的是,空字符串不等于null,0也不等于null

建表的时候指定NOT NULL约束

如果需要在建表时为指定列指定非空约束,只要在列定义后增加not null即可。建表语句如下:

1
2
3
4
5
CREATE TABLE `hehe` (
`hehe_id` int(11) NOT NULL,
`hehe_name` varchar(255) NOT NULL,
`hehe_gender` varchar(2)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

not null约束的默认值

**在插入数据的时候,如果某列没有赋值,MySQL会赋给一个默认值.**
对于not null约束的列,

  • 如果类型为int,则默认值为0
  • 如果默认值为varchar,则默认值为空字符串.

实例

现在插入一条数据insert into hehe(hehe_gender) values('小王');,这里只给第三个属性赋值,第一和第二没有赋值,此时表中的数据如下所示:

1
2
3
4
5
6
7
8
9
10
mysql> insert into hehe(hehe_gender) values('小王');
Query OK, 1 row affected

mysql> select * from hehe;
+---------+-----------+-------------+
| hehe_id | hehe_name | hehe_gender |
+---------+-----------+-------------+
| 0 | | 小王 |
+---------+-----------+-------------+
1 row in set

可以看到第一列填入了默认值0,而第二列好像什么都没有填入,但其实第二列填入的是空字符串而不是NULL(not null约束的列当然不能填入null).
现在再来插入一条数据:insert into hehe(hehe_id) values(1);这里只填入第一列,第二列和第三列让MySQL默认填写.
查询结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mysql> select * from hehe;
+---------+-----------+-------------+
| hehe_id | hehe_name | hehe_gender |
+---------+-----------+-------------+
| 0 | | 小王 |
+---------+-----------+-------------+
1 row in set
mysql> insert into hehe(hehe_id) values(1);
Query OK, 1 row affected

mysql> select * from hehe;
+---------+-----------+-------------+
| hehe_id | hehe_name | hehe_gender |
+---------+-----------+-------------+
| 0 | | 小王 |
| 1 | | NULL |
+---------+-----------+-------------+
2 rows in set

因为第三列的hehe_gender默认值为NULL,所以MySQL给该列填上了默认值NULL,
而第二列的hehe_name使用了not null约束,不能填写NULL,此时MySQL填写上一个空字符串.

alter table修改表时增加和删除非空约束

除此之外,也可以在使用alter table修改表时增加或者删除非空约束,SQL命令如下:

增加非空约束

1
2
alter table hehe
modify hehe_gender varchar(2) not null

效果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> desc hehe;
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| hehe_id | int(11) | NO | | NULL | |
| hehe_name | varchar(255) | NO | | NULL | |
| hehe_gender | varchar(2) | YES | | NULL | |
+-------------+--------------+------+-----+---------+-------+
3 rows in set

mysql> alter table hehe
modify hehe_gender varchar(2) not null;
Query OK, 3 rows affected
Records: 3 Duplicates: 0 Warnings: 2

mysql> desc hehe;
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| hehe_id | int(11) | NO | | NULL | |
| hehe_name | varchar(255) | NO | | NULL | |
| hehe_gender | varchar(2) | NO | | NULL | |
+-------------+--------------+------+-----+---------+-------+
默认值

此时再次查询表中数据,可以发现第二行第三列的值已经变成列空字符串了,不再是原来的NULL,如下所示:

1
2
3
4
5
6
7
8
mysql> select * from hehe;
+---------+-----------+-------------+
| hehe_id | hehe_name | hehe_gender |
+---------+-----------+-------------+
| 0 | | 小王 |
| 1 | | |
+---------+-----------+-------------+
2 rows in set

取消非空约束并指定默认值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mysql> desc hehe;
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| hehe_id | int(11) | NO | | NULL | |
| hehe_name | varchar(255) | NO | | NULL | |
| hehe_gender | varchar(2) | NO | | NULL | |
+-------------+--------------+------+-----+---------+-------+
3 rows in set

mysql> alter table hehe
modify hehe_name varchar(255) default 'xyz' null;
Query OK, 3 rows affected
Records: 3 Duplicates: 0 Warnings: 0

mysql> desc hehe;
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| hehe_id | int(11) | NO | | NULL | |
| hehe_name | varchar(255) | YES | | xyz | |
| hehe_gender | varchar(2) | NO | | NULL | |
+-------------+--------------+------+-----+---------+-------+
3 rows in set
默认值

这时候我们再次查询:

1
2
3
4
5
6
7
8
mysql> select * from hehe;
+---------+-----------+-------------+
| hehe_id | hehe_name | hehe_gender |
+---------+-----------+-------------+
| 0 | | 小王 |
| 1 | | |
+---------+-----------+-------------+
2 rows in set

这里可以发现第二列原来的默认值(空字符串),并没有直接变成xyz.这是因为default语句定义的字符串默认值,在新插入的记录才有效(其实原来的空字符串也是字符串,MySQL该列已经有数据了不需要自己填写默认值,所以不会使用xyz覆盖原来的空字符串)
现在再插入一条记录insert into hehe (hehe_id) values(2);此时第二列没有赋值,将填入默认值xyz.如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql> select * from hehe;
+---------+-----------+-------------+
| hehe_id | hehe_name | hehe_gender |
+---------+-----------+-------------+
| 0 | | 小王 |
| 1 | | |
+---------+-----------+-------------+
2 rows in set

mysql> insert into hehe (hehe_id) values(2);
Query OK, 1 row affected

mysql> select * from hehe;
+---------+-----------+-------------+
| hehe_id | hehe_name | hehe_gender |
+---------+-----------+-------------+
| 0 | | 小王 |
| 1 | | |
| 2 | xyz | |
+---------+-----------+-------------+
3 rows in set
mysql>